Index: ctl/explainShape.cpp =================================================================== --- ctl/explainShape.cpp (revision 7584) +++ ctl/explainShape.cpp (working copy) @@ -41,6 +41,10 @@ #include "images/ex_seek.xpm" #include "images/ex_setop.xpm" #include "images/ex_result.xpm" +// Greenplum images +#include "images/ex_broadcast_motion.xpm" +#include "images/ex_redistribute_motion.xpm" +#include "images/ex_gather_motion.xpm" #define BMP_BORDER 3 @@ -178,6 +182,9 @@ if (token == wxT("Total")) return 0; else if (token == wxT("Trigger")) return 0; + else if (token == wxT("Settings:")) return 0; /* Greenplum */ + else if (token == wxT("Slice")) return 0; /* Greenplum */ + else if (token.Mid(0,6) == wxT("(slice")) return 0; /* Greenplum */ else if (token == wxT("Result")) s = new ExplainShape(ex_result_xpm, descr); else if (token == wxT("Append")) s = new ExplainShape(ex_append_xpm, descr); else if (token == wxT("Nested")) @@ -319,12 +326,20 @@ s = new ExplainShape(ex_scan_xpm, descr, 3, 2); } else if (token2 == wxT("Seek")) s = new ExplainShape(ex_seek_xpm, descr, 3, 2); - // Recursive Union + // Recursive Union else if (token == wxT("Recursive") && token2 == wxT("Union")) s = new ExplainShape(ex_recursive_union_xpm, descr); else if (token == wxT("WindowAgg")) s = new ExplainShape(ex_windowagg_xpm, descr); + // Greenplum additions + else if (token == wxT("Gather") && token2 ==wxT("Motion")) + s = new ExplainShape(ex_gather_motion_xpm, descr); + else if (token == wxT("Broadcast") && token2 ==wxT("Motion")) + s = new ExplainShape(ex_broadcast_motion_xpm, descr); + else if (token == wxT("Redistribute") && token2 ==wxT("Motion")) + s = new ExplainShape(ex_redistribute_motion_xpm, descr); + if (!s) s = new ExplainShape(ex_unknown_xpm, descr); Index: include/ctl/explainCanvas.h =================================================================== --- include/ctl/explainCanvas.h (revision 7584) +++ include/ctl/explainCanvas.h (working copy) @@ -47,7 +47,7 @@ ExplainShape(const char *bmp[], const wxString &description, long tokenNo=-1, long detailNo=-1); static ExplainShape *Create(long level, ExplainShape *last, const wxString &str); - void SetCondition(const wxString &str) { condition = str; } + void SetCondition(const wxString &str) { if (condition.Length()==0) condition = str; else condition += wxT(" ") + str; } long GetLevel() { return level; } wxRealPoint GetStartPoint(); wxRealPoint GetEndPoint(int kidNo); Index: include/debugger/dbgPgConn.h =================================================================== --- include/debugger/dbgPgConn.h (revision 7584) +++ include/debugger/dbgPgConn.h (working copy) @@ -66,6 +66,7 @@ bool BackendMinimumVersion(int major, int minor); bool EdbMinimumVersion(int major, int minor); bool GetIsEdb(); + bool GetIsGreenplum(); DebuggerApiVersions DebuggerApiVersion(); wxString GetVersionString(); bool isConnected() const; // Returns true if the connection attempt succeeded @@ -89,6 +90,7 @@ frmDebugger *m_frame; int m_minorVersion, m_majorVersion; bool m_isEdb; + bool m_isGreenplum; DebuggerApiVersions m_debuggerApiVersion; }; Index: include/frm/frmMain.h =================================================================== --- include/frm/frmMain.h (revision 7584) +++ include/frm/frmMain.h (working copy) @@ -223,6 +223,13 @@ wxWindow *StartDialog(frmMain *form, pgObject *obj); }; +class greenplumHelpFactory : public actionFactory +{ +public: + greenplumHelpFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar, bool bigTool); + wxWindow *StartDialog(frmMain *form, pgObject *obj); +}; + class slonyHelpFactory : public actionFactory { public: Index: include/db/pgConn.h =================================================================== --- include/db/pgConn.h (revision 7584) +++ include/db/pgConn.h (working copy) @@ -87,11 +87,13 @@ bool HasPrivilege(const wxString &objTyp, const wxString &objName, const wxString &priv); bool HasFeature(int feature=0); bool BackendMinimumVersion(int major, int minor); + bool BackendMinimumVersion(int major, int minor, int patch); bool EdbMinimumVersion(int major, int minor); wxString SystemNamespaceRestriction(const wxString &nsp); int GetMajorVersion() const { return majorVersion; } int GetMinorVersion() const { return minorVersion; } bool GetIsEdb(); + bool GetIsGreenplum(); wxString EncryptPassword(const wxString &user, const wxString &password); wxString qtDbString(const wxString& value); pgConn *Duplicate(); @@ -163,8 +165,9 @@ wxString qtString(const wxString& value); bool features[32]; - int minorVersion, majorVersion; + int minorVersion, majorVersion, patchVersion; bool isEdb; + bool isGreenplum; wxString reservedNamespaces; Index: include/precomp.h =================================================================== --- include/precomp.h (revision 7584) +++ include/precomp.h (working copy) @@ -105,6 +105,7 @@ #include "dlg/dlgType.h" #include "dlg/dlgUser.h" #include "dlg/dlgView.h" +#include "dlg/dlgExtTable.h" #include "frm/frmAbout.h" #include "frm/frmBackup.h" @@ -187,6 +188,8 @@ #include "schema/pgType.h" #include "schema/pgUser.h" #include "schema/pgView.h" +#include "schema/pgExtTable.h" +#include "schema/pgResQueue.h" #include "slony/dlgRepCluster.h" #include "slony/dlgRepListen.h" Index: include/parser/keywords.h =================================================================== --- include/parser/keywords.h (revision 7584) +++ include/parser/keywords.h (working copy) @@ -459,7 +459,12 @@ RAW_EDB = 815, RETURN_EDB = 816, SYSDATE_EDB = 817, - SYSTIMESTAMP_EDB = 818 + SYSTIMESTAMP_EDB = 818, + + /* The following additions are keywords in Greenplum Database */ + DISTRIBUTED = 900, + LOG_P = 901 + }; #endif /* KEYWORDS_H */ Index: include/utils/misc.h =================================================================== --- include/utils/misc.h (revision 7584) +++ include/utils/misc.h (working copy) @@ -160,6 +160,7 @@ HELP_PGADMIN, HELP_POSTGRESQL, HELP_ENTERPRISEDB, + HELP_GREENPLUM, HELP_SLONY } HelpType; @@ -214,6 +215,8 @@ PGM_UNKNOWN, PGM_UNIQUE, PGM_VIEW, + PGM_EXTTABLE, + PGM_RESOURCE_QUEUE, PGM_JOB, PGM_SCHEDULE, Index: include/schema/module.mk =================================================================== --- include/schema/module.mk (revision 7584) +++ include/schema/module.mk (working copy) @@ -49,7 +49,10 @@ $(srcdir)/include/schema/pgTrigger.h \ $(srcdir)/include/schema/pgType.h \ $(srcdir)/include/schema/pgUser.h \ - $(srcdir)/include/schema/pgView.h + $(srcdir)/include/schema/pgView.h \ + $(srcdir)/include/schema/pgExtTable.h \ + $(srcdir)/include/schema/pgResQueue.h \ + $(srcdir)/include/schema/pgPartition.h EXTRA_DIST += \ $(srcdir)/include/schema/module.mk Index: include/schema/pgTable.h =================================================================== --- include/schema/pgTable.h (revision 7584) +++ include/schema/pgTable.h (working copy) @@ -62,6 +62,9 @@ void iSetPrimaryKeyColNumbers(const wxString& s) {primaryKeyColNumbers = s; } wxString GetPrimaryKeyName() const { return primaryKeyName; } void iSetPrimaryKeyName(const wxString& s) {primaryKeyName = s; } + wxString GetDistributionColNumbers() const { return distributionColNumbers; } // for Greenplum + void iSetDistributionColNumbers(const wxString& s) { distributionColNumbers = s; if (s.Length() > 0) distributionIsRandom = false; } // for Greenplum + void iSetDistributionIsRandom() { distributionIsRandom = true; } double GetEstimatedRows() const { return estimatedRows; } void iSetEstimatedRows(const double d) { estimatedRows=d; } wxString GetTablespace() const { return tablespace; }; @@ -95,6 +98,14 @@ void iSetShowExtendedStatistics(bool b) { showExtendedStatistics = b; } wxString GetFillFactor() { return fillFactor; } void iSetFillFactor(const wxString& s) { fillFactor = s; } + wxString GetAppendOnly() { return appendOnly; } + void iSetAppendOnly(const wxString& s) { appendOnly = s; } + wxString GetCompressLevel() { return compressLevel; } + void iSetCompressLevel(const wxString& s) { compressLevel = s; } + wxString GetPartitionDef() { return partitionDef; } + void iSetPartitionDef(const wxString& s) { partitionDef = s; } + bool GetIsPartitioned() const { return isPartitioned || partitionDef.Length() > 0; } + void iSetIsPartitioned(bool b) { isPartitioned = b; } bool HasStats() { return true; } @@ -116,15 +127,20 @@ void UpdateInheritance(); bool GetVacuumHint(); wxString GetCols(ctlTree *browser, size_t indent, wxString &QMs, bool withQM); - - void AppendStuff(wxString &sql, ctlTree *browser, pgaFactory &factory); + void AppendStuff(wxString &sql, ctlTree *browser, pgaFactory &factory); + void AppendStuffNoSql(wxString &sql, ctlTree *browser, pgaFactory &factory); + wxULongLong rows; double estimatedRows; wxString fillFactor; - bool hasOids, hasSubclass, rowsCounted, isReplicated, showExtendedStatistics; + wxString appendOnly; + wxString compressLevel; + wxString partitionDef; + bool isPartitioned; + bool hasOids, hasSubclass, rowsCounted, isReplicated, showExtendedStatistics, distributionIsRandom; long inheritedTableCount; wxString quotedInheritedTables, inheritedTables, primaryKey, quotedPrimaryKey, - primaryKeyName, primaryKeyColNumbers, tablespace; + primaryKeyName, primaryKeyColNumbers, tablespace, distributionColNumbers; wxArrayString quotedInheritedTablesList, inheritedTablesOidList; slSet *replicationSet; OID tablespaceOid; Index: include/schema/pgDatabase.h =================================================================== --- include/schema/pgDatabase.h (revision 7584) +++ include/schema/pgDatabase.h (working copy) @@ -40,6 +40,7 @@ pgDatabase *GetDatabase() const { return (pgDatabase*)this; } bool BackendMinimumVersion(int major, int minor) { return connection()->BackendMinimumVersion(major, minor); } + bool BackendMinimumVersion(int major, int minor, int patch) { return connection()->BackendMinimumVersion(major, minor, patch); } void ShowTreeDetail(ctlTree *browser, frmMain *form=0, ctlListView *properties=0, ctlSQLBox *sqlPane=0); void ShowHint(frmMain *form, bool force); Index: include/schema/pgRole.h =================================================================== --- include/schema/pgRole.h (revision 7584) +++ include/schema/pgRole.h (working copy) @@ -73,6 +73,8 @@ void iSetSuperuser(const bool b) { superuser=b; } bool GetUpdateCatalog() const { return updateCatalog; } void iSetUpdateCatalog(const bool b) { updateCatalog=b; } + wxString GetRolQueueName() const { return rolqueuename; } + void iSetRolQueueName(const wxString& newVal) { rolqueuename = newVal; } long GetConnectionLimit() const { return connectionLimit; } void iSetConnectionLimit(long newVal) { connectionLimit=newVal; } wxArrayString& GetRolesIn() { return rolesIn; } @@ -94,6 +96,7 @@ bool HasReferences() { return true; } private: wxString password; + wxString rolqueuename; wxDateTime accountExpires; bool superuser, createDatabase, createRole, updateCatalog, inherits, canLogin; long connectionLimit; Index: include/images/module.mk =================================================================== --- include/images/module.mk (revision 7584) +++ include/images/module.mk (working copy) @@ -204,7 +204,13 @@ $(srcdir)/include/images/view.xpm \ $(srcdir)/include/images/viewdata.xpm \ $(srcdir)/include/images/viewfiltereddata.xpm \ - $(srcdir)/include/images/views.xpm + $(srcdir)/include/images/views.xpm \ + $(srcdir)/include/images/ex_broadcast_motion.xpm \ + $(srcdir)/include/images/ex_redistribute_motion.xpm \ + $(srcdir)/include/images/ex_gather_motion.xpm \ + $(srcdir)/include/images/exttable-sm.xpm \ + $(srcdir)/include/images/exttables.xpm \ + $(srcdir)/include/images/exttable.xpm EXTRA_DIST += \ $(srcdir)/include/images/module.mk \ Index: include/dlg/module.mk =================================================================== --- include/dlg/module.mk (revision 7584) +++ include/dlg/module.mk (working copy) @@ -53,6 +53,7 @@ $(srcdir)/include/dlg/dlgUser.h \ $(srcdir)/include/dlg/dlgView.h \ $(srcdir)/include/dlg/dlgManageMacros.h \ + $(srcdir)/include/dlg/dlgExtTable.h \ $(srcdir)/include/dlg/dlgSelectDatabase.h EXTRA_DIST += \ Index: debugger/dbgPgConn.cpp =================================================================== --- debugger/dbgPgConn.cpp (revision 7584) +++ debugger/dbgPgConn.cpp (working copy) @@ -381,6 +381,8 @@ } if (result == wxT("0")) m_minorVersion = 2; + + m_isGreenplum = version.Upper().Matches(wxT("*GREENPLUM DATABASE*")); } } @@ -467,5 +469,12 @@ return m_isEdb; } +bool dbgPgConn::GetIsGreenplum() +{ + // to retrieve edb flag + BackendMinimumVersion(0,0); + return m_isGreenplum; +} + Index: frm/frmEditGrid.cpp =================================================================== --- frm/frmEditGrid.cpp (revision 7584) +++ frm/frmEditGrid.cpp (working copy) @@ -36,6 +36,7 @@ #include "schema/pgCatalogObject.h" #include "schema/pgTable.h" #include "schema/pgView.h" +#include "schema/pgExtTable.h" // wxAUI #include @@ -273,6 +274,14 @@ hasOids=false; tableName = view->GetSchema()->GetQuotedFullIdentifier() + wxT(".") + view->GetQuotedIdentifier(); } + else if (obj->GetMetaType() == PGM_EXTTABLE) + { + pgExtTable *exttable=(pgExtTable*)obj; + + relkind = 'x'; + hasOids=false; + tableName = exttable->GetSchema()->GetQuotedFullIdentifier() + wxT(".") + exttable->GetQuotedIdentifier(); + } else if (obj->GetMetaType() == PGM_CATALOGOBJECT) { pgCatalogObject *catobj=(pgCatalogObject*)obj; @@ -3013,7 +3022,7 @@ if (obj) { pgaFactory *factory=obj->GetFactory(); - return factory == &tableFactory || factory == &viewFactory || factory == &catalogObjectFactory; + return factory == &tableFactory || factory == &viewFactory || factory == &extTableFactory || factory == &catalogObjectFactory; } return false; } Index: frm/frmOptions.cpp =================================================================== --- frm/frmOptions.cpp (revision 7584) +++ frm/frmOptions.cpp (working copy) @@ -170,6 +170,7 @@ lstDisplay->Append(_("pgAgent jobs")); lstDisplay->Append(_("Groups/group roles")); lstDisplay->Append(_("Users/login roles")); + lstDisplay->Append(_("ResQueues/resource queues")); lstDisplay->Append(_("Catalogs")); lstDisplay->Append(_("Casts")); lstDisplay->Append(_("Languages")); @@ -189,12 +190,14 @@ lstDisplay->Append(_("Rules")); lstDisplay->Append(_("Sequences")); lstDisplay->Append(_("Tables")); + lstDisplay->Append(_("External Tables")); lstDisplay->Append(_("FTS Configurations")); lstDisplay->Append(_("FTS Dictionaries")); lstDisplay->Append(_("FTS Parsers")); lstDisplay->Append(_("FTS Templates")); lstDisplay->Append(_("Types")); lstDisplay->Append(_("Views")); + lstDisplay->Append(_("Partitions")); for (unsigned int x=0; x < lstDisplay->GetCount(); x++) lstDisplay->Check(x, settings->GetDisplayOption(lstDisplay->GetString(x))); Index: frm/frmGrantWizard.cpp =================================================================== --- frm/frmGrantWizard.cpp (revision 7584) +++ frm/frmGrantWizard.cpp (working copy) @@ -25,6 +25,7 @@ #include "schema/pgSequence.h" #include "schema/pgTable.h" #include "schema/pgView.h" +#include "schema/pgExtTable.h" // Icons #include "images/index.xpm" @@ -135,6 +136,7 @@ !factory->IsCollectionFor(triggerFunctionFactory) && !factory->IsCollectionFor(procedureFactory) && !factory->IsCollectionFor(viewFactory) && + !factory->IsCollectionFor(extTableFactory) && !factory->IsCollectionFor(sequenceFactory)) return; } @@ -180,6 +182,9 @@ privList = wxT("EXECUTE"); privChar = "X"; break; + case PGM_EXTTABLE: + privList = wxT("SELECT,RULE"); + privChar = "r"; default: break; } @@ -271,8 +276,15 @@ case PGM_SEQUENCE: tmp = securityPage->GetGrant(wxT("arwdRxt"), wxT("TABLE ") + obj->GetQuotedFullIdentifier()); break; + case PGM_EXTTABLE: + tmp = securityPage->GetGrant(wxT("r"), wxT("TABLE ") + obj->GetQuotedFullIdentifier()); default: - tmp = securityPage->GetGrant(wxT("arwdRxt"), obj->GetTypeName().Upper() + wxT(" ") + obj->GetQuotedFullIdentifier()); + if (obj->GetTypeName().Upper() == wxT("EXTERNAL TABLE")) // somewhat of a hack + { + tmp = securityPage->GetGrant(wxT("r"), wxT("TABLE ") + obj->GetQuotedFullIdentifier()); + } + else + tmp = securityPage->GetGrant(wxT("arwdRxt"), obj->GetTypeName().Upper() + wxT(" ") + obj->GetQuotedFullIdentifier()); break; } @@ -308,6 +320,7 @@ case PGM_FUNCTION: case PGM_SEQUENCE: case PGM_VIEW: + case PGM_EXTTABLE: if (obj->IsCollection() && obj->GetSchema()->GetMetaType() != PGM_CATALOG) return obj->GetSchema()->CanEdit(); break; Index: frm/frmQuery.cpp =================================================================== --- frm/frmQuery.cpp (revision 7584) +++ frm/frmQuery.cpp (working copy) @@ -43,6 +43,7 @@ #include "schema/pgDatabase.h" #include "schema/pgTable.h" #include "schema/pgView.h" +#include "schema/pgExtTable.h" #include "schema/pgServer.h" #include "utils/favourites.h" #include "utils/sysLogger.h" @@ -795,6 +796,7 @@ { wxT("TYPE"), 0, 11}, { wxT("USER"), 0, 12}, { wxT("VIEW"), 0, 11}, + { wxT("EXTTABLE"), 0, 12}, { 0, 0 } }; @@ -932,6 +934,8 @@ if (conn->GetIsEdb()) DisplayHelp(page, HELP_ENTERPRISEDB); + else if (conn->GetIsGreenplum()) + DisplayHelp(page, HELP_GREENPLUM); else DisplayHelp(page, HELP_POSTGRESQL); } @@ -2415,6 +2419,11 @@ pgView *view = (pgView*)obj; return StartDialogSql(form, obj, view->GetSelectSql(form->GetBrowser())); } + else if (obj->IsCreatedBy(extTableFactory)) + { + pgExtTable *exttable = (pgExtTable*)obj; + return StartDialogSql(form, obj, exttable->GetSelectSql(form->GetBrowser())); + } return 0; } @@ -2464,6 +2473,11 @@ pgView *view = (pgView*)obj; return StartDialogSql(form, obj, view->GetUpdateSql(form->GetBrowser())); } + /* else if (obj->IsCreatedBy(extTableFactory)) + { + pgExtTable *exttable = (pgExtTable*)obj; + return StartDialogSql(form, obj, exttable->GetUpdateSql(form->GetBrowser())); + }*/ return 0; } Index: frm/frmBackup.cpp =================================================================== --- frm/frmBackup.cpp (revision 7584) +++ frm/frmBackup.cpp (working copy) @@ -197,6 +197,9 @@ cmd += wxT(" -p ") + NumToStr((long)server->GetPort()) + wxT(" -U ") + server->GetUsername(); + + if (object->GetConnection()->GetIsGreenplum()) + cmd += wxT(" --gp-syntax "); return cmd; } Index: frm/frmMainConfig.cpp =================================================================== --- frm/frmMainConfig.cpp (revision 7584) +++ frm/frmMainConfig.cpp (working copy) @@ -481,7 +481,8 @@ FillList(wxT("explain_pretty_print")); // Client Connection Defaults / Other Defaults FillList(wxT("enable_hashjoin")); // Query Tuning / Planner Method Configuration FillList(wxT("cpu_operator_cost")); // Query Tuning / Planner Cost Constants - FillList(wxT("geqo")); // Query Tuning / Genetic Query Optimizer + if (!conn || !conn->GetIsGreenplum()) // Greenplum doesn't have the Genetic Query Optimizer + FillList(wxT("geqo")); // Query Tuning / Genetic Query Optimizer FillList(wxT("default_statistics_target")); // Query Tuning / Other Planner Options FillList(wxT("deadlock_timeout")); // Lock Management FillList(wxT("shared_buffers")); // Resource Usage / Memory @@ -497,7 +498,8 @@ FillList(wxT("checkpoint_segments")); // Write-Ahead Log / Checkpoints FillList(wxT("add_missing_from")); // Version and Platform Compatibility / Previous PostgreSQL Version FillList(wxT("transform_null_equals")); // Version and Platform Compatibility / Other Platforms and Clients - FillList(wxT("trace_notify")); // Developer Options + if (!conn || !conn->GetIsGreenplum()) // Greenplum doesn't have trace_notify visible + FillList(wxT("trace_notify")); // Developer Options FillList(wxT("hba_file")); // Ungrouped @@ -694,8 +696,14 @@ wxWindow *mainConfigFileFactory::StartDialog(frmMain *form, pgObject *obj) { - frmConfig *dlg = new frmMainConfig(form); + pgServer *server=0; + if (CheckEnable(obj)) + server=obj->GetServer(); + if (server == 0 || !server->GetConnection()->GetIsGreenplum()) + server = 0; // make this work like it always did if not Greenplum. But wouldn't it be better to work for all DBs this way? + frmConfig *dlg = new frmMainConfig(form,server); dlg->Go(); - dlg->DoOpen(); + if (server==0 || !CheckEnable(obj)) + dlg->DoOpen(); return dlg; } Index: frm/frmHbaConfig.cpp =================================================================== --- frm/frmHbaConfig.cpp (revision 7584) +++ frm/frmHbaConfig.cpp (working copy) @@ -386,8 +386,14 @@ wxWindow *hbaConfigFileFactory::StartDialog(frmMain *form, pgObject *obj) { - frmConfig *dlg = new frmHbaConfig(form); + pgServer *server=0; + if (CheckEnable(obj)) + server=obj->GetServer(); + if (server ==0 ||!server->GetConnection()->GetIsGreenplum()) + server = 0; // make this work like it always did if not Greenplum. But wouldn't it be better to work for all DBs this way? + frmConfig *dlg = new frmHbaConfig(form,server); dlg->Go(); - dlg->DoOpen(); + if (server==0 || !CheckEnable(obj)) + dlg->DoOpen(); return dlg; } Index: frm/frmMain.cpp =================================================================== --- frm/frmMain.cpp (revision 7584) +++ frm/frmMain.cpp (working copy) @@ -425,6 +425,7 @@ new pgsqlHelpFactory(menuFactories, helpMenu, toolBar, true); new edbHelpFactory(menuFactories, helpMenu, toolBar, true); + new greenplumHelpFactory(menuFactories, helpMenu, toolBar, true); new slonyHelpFactory(menuFactories, helpMenu, toolBar, true); // Don't include this seperator on Mac, because the only option @@ -1200,6 +1201,19 @@ return 0; } +greenplumHelpFactory::greenplumHelpFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar, bool bigIcon) : actionFactory(list) +{ + mnu->Append(id, _("&Greenplum Database Help"), _("Display help on the Greenplum Database system.")); +} + + +wxWindow *greenplumHelpFactory::StartDialog(frmMain *form, pgObject *obj) +{ + DisplayHelp(wxT("index"), HELP_GREENPLUM); + return 0; +} + + slonyHelpFactory::slonyHelpFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar, bool bigIcon) : actionFactory(list) { mnu->Append(id, _("&Slony Help"), _("Display help on the Slony replication system.")); Index: db/pgConn.cpp =================================================================== --- db/pgConn.cpp (revision 7584) +++ db/pgConn.cpp (working copy) @@ -285,6 +285,12 @@ return isEdb; } +bool pgConn::GetIsGreenplum() +{ + // to retrieve Greenplum flag + BackendMinimumVersion(0,0); + return isGreenplum; +} wxString pgConn::SystemNamespaceRestriction(const wxString &nsp) { @@ -334,7 +340,7 @@ if (!majorVersion) { wxString version=GetVersionString(); - sscanf(version.ToAscii(), "%*s %d.%d", &majorVersion, &minorVersion); + sscanf(version.ToAscii(), "%*s %d.%d.%d", &majorVersion, &minorVersion, &patchVersion); isEdb = version.Upper().Matches(wxT("ENTERPRISEDB*")); // EnterpriseDB 8.3 beta 1 & 2 and possibly later actually have PostgreSQL 8.2 style @@ -346,12 +352,25 @@ if (ExecuteScalar(wxT("SELECT count(*) FROM pg_attribute WHERE attname = 'proconfig' AND attrelid = 'pg_proc'::regclass")) == wxT("0")) minorVersion = 2; } + + isGreenplum = version.Upper().Matches(wxT("*GREENPLUM DATABASE*")); } return majorVersion > major || (majorVersion == major && minorVersion >= minor); } +// Greenplum sometimes adds features in patch releases, because Greenplum +// releases are not coordinated with PostgreSQL minor releases. +bool pgConn::BackendMinimumVersion(int major, int minor, int patch) +{ + if (!majorVersion) + BackendMinimumVersion(0,0); + + return majorVersion > major || (majorVersion == major && minorVersion > minor) || (majorVersion == major && minorVersion == minor && patchVersion >= patch); +} + + bool pgConn::EdbMinimumVersion(int major, int minor) { return BackendMinimumVersion(major, minor) && GetIsEdb(); Index: db/keywords.c =================================================================== --- db/keywords.c (revision 7584) +++ db/keywords.c (working copy) @@ -135,6 +135,7 @@ {"disable", DISABLE_P, UNRESERVED_KEYWORD}, {"discard", DISCARD, UNRESERVED_KEYWORD}, {"distinct", DISTINCT, RESERVED_KEYWORD}, + {"distributed", DISTRIBUTED, UNRESERVED_KEYWORD}, /* Greenplum Keyword */ {"do", DO, RESERVED_KEYWORD}, {"document", DOCUMENT_P, UNRESERVED_KEYWORD}, {"domain", DOMAIN_P, UNRESERVED_KEYWORD}, @@ -227,6 +228,7 @@ {"localtimestamp", LOCALTIMESTAMP, RESERVED_KEYWORD}, {"location", LOCATION, UNRESERVED_KEYWORD}, {"lock", LOCK_P, UNRESERVED_KEYWORD}, + {"log", LOG_P, RESERVED_KEYWORD}, /* Greenplum Keyword */ {"login", LOGIN_P, UNRESERVED_KEYWORD}, {"long", LONG_EDB, RESERVED_KEYWORD}, /* EnterpriseDB Keyword */ {"mapping", MAPPING, UNRESERVED_KEYWORD}, Index: utils/sysSettings.cpp =================================================================== --- utils/sysSettings.cpp (revision 7584) +++ utils/sysSettings.cpp (working copy) @@ -74,6 +74,8 @@ engtype = wxT("Groups-login roles"); else if (objtype == _("Users/login roles")) engtype = wxT("Users-login roles"); + else if (objtype == _("ResQueues/resource queues")) + engtype = wxT("ResQueues-resource queues"); else if (objtype == _("Catalogs")) engtype = wxT("Catalogs"); else if (objtype == _("Casts")) @@ -135,6 +137,8 @@ else if (objtype == _("Sequences")) engtype = wxT("Sequences"); else if (objtype == _("Tables")) + engtype = wxT("Partitions"); + else if (objtype == _("Partitions")) engtype = wxT("Tables"); else if (objtype == _("FTS Configurations")) engtype = wxT("FTS Configurations"); @@ -151,6 +155,8 @@ } else if (objtype == _("Views")) engtype = wxT("Views"); + else if (objtype == _("External Tables")) + engtype = wxT("External Tables"); // If we just want the default, return it. if (GetDefault) @@ -170,6 +176,7 @@ else if (objtype == _("pgAgent jobs")) engtype = wxT("pgAgent jobs"); else if (objtype == _("Groups/group roles")) engtype = wxT("Groups-login roles"); else if (objtype == _("Users/login roles")) engtype = wxT("Users-login roles"); + else if (objtype == _("ResQueues/resource queues")) engtype = wxT("ResQueues-resource queues"); else if (objtype == _("Catalogs")) engtype = wxT("Catalogs"); else if (objtype == _("Casts")) engtype = wxT("Casts"); else if (objtype == _("Languages")) engtype = wxT("Languages"); @@ -189,12 +196,14 @@ else if (objtype == _("Rules")) engtype = wxT("Rules"); else if (objtype == _("Sequences")) engtype = wxT("Sequences"); else if (objtype == _("Tables")) engtype = wxT("Tables"); + else if (objtype == _("Partitions")) engtype = wxT("Partitions"); else if (objtype == _("FTS Configurations")) engtype = wxT("FTS Configurations"); else if (objtype == _("FTS Dictionaries")) engtype = wxT("FTS Dictionaries"); else if (objtype == _("FTS Parsers")) engtype = wxT("FTS Parsers"); else if (objtype == _("FTS Templates")) engtype = wxT("FTS Templates"); else if (objtype == _("Types")) engtype = wxT("Types"); else if (objtype == _("Views")) engtype = wxT("Views"); + else if (objtype == _("External Tables")) engtype = wxT("External Tables"); Write(wxT("Display/") + engtype, display); } Index: utils/tab-complete.inc =================================================================== --- utils/tab-complete.inc (revision 7584) +++ utils/tab-complete.inc (working copy) @@ -357,6 +357,7 @@ {"UNIQUE", NULL, NULL}, /* for CREATE UNIQUE INDEX ... */ {"USER", Query_for_list_of_roles}, {"VIEW", NULL, &Query_for_list_of_views}, + {"EXTTABLE", NULL, &Query_for_list_of_views}, {NULL, NULL, NULL} /* end of list */ }; @@ -783,7 +784,7 @@ static const char *const list_COMMENT[] = {"CAST", "CONVERSION", "DATABASE", "INDEX", "LANGUAGE", "RULE", "SCHEMA", "SEQUENCE", "TABLE", "TYPE", "VIEW", "COLUMN", "AGGREGATE", "FUNCTION", - "OPERATOR", "TRIGGER", "CONSTRAINT", "DOMAIN", "LARGE OBJECT", NULL}; + "OPERATOR", "TRIGGER", "CONSTRAINT", "DOMAIN", "LARGE OBJECT", "EXTTABLE", NULL}; COMPLETE_WITH_LIST(list_COMMENT); } Index: utils/misc.cpp =================================================================== --- utils/misc.cpp (revision 7584) +++ utils/misc.cpp (working copy) @@ -662,6 +662,7 @@ { static wxHelpControllerBase *pgHelpCtl=0; static wxHelpControllerBase *edbHelpCtl=0; + static wxHelpControllerBase *greenplumHelpCtl=0; static wxHelpControllerBase *slonyHelpCtl=0; static wxString pgInitPath = wxEmptyString; static wxString edbInitPath = wxEmptyString; @@ -683,6 +684,11 @@ edbInitPath = settings->GetEdbHelpPath(); break; + case HELP_GREENPLUM: + DisplayExternalHelp(helpTopic, settings->GetPgHelpPath(), greenplumHelpCtl, (pgInitPath != settings->GetPgHelpPath() ? true : false)); + pgInitPath = settings->GetPgHelpPath(); + break; + case HELP_SLONY: DisplayExternalHelp(helpTopic, settings->GetSlonyHelpPath(), slonyHelpCtl, (slonyInitPath != settings->GetSlonyHelpPath() ? true : false)); slonyInitPath = settings->GetSlonyHelpPath(); Index: schema/module.mk =================================================================== --- schema/module.mk (revision 7584) +++ schema/module.mk (working copy) @@ -51,7 +51,10 @@ $(subdir)/pgTrigger.cpp \ $(subdir)/pgType.cpp \ $(subdir)/pgUser.cpp \ - $(subdir)/pgView.cpp + $(subdir)/pgView.cpp \ + $(subdir)/pgExtTable.cpp \ + $(subdir)/pgResQueue.cpp \ + $(subdir)/pgPartition.cpp EXTRA_DIST += \ $(srcdir)/schema/module.mk Index: schema/pgSchema.cpp =================================================================== --- schema/pgSchema.cpp (revision 7584) +++ schema/pgSchema.cpp (working copy) @@ -29,12 +29,14 @@ #include "schema/pgOperatorFamily.h" #include "schema/pgSequence.h" #include "schema/pgTable.h" +#include "schema/pgExtTable.h" #include "schema/pgTextSearchConfiguration.h" #include "schema/pgTextSearchDictionary.h" #include "schema/pgTextSearchParser.h" #include "schema/pgTextSearchTemplate.h" #include "schema/pgType.h" #include "schema/pgView.h" +#include "schema/pgPartition.h" #include "frm/frmReport.h" #include "wx/regex.h" @@ -103,6 +105,8 @@ sequenceFactory.AppendMenu(menu); if (settings->GetDisplayOption(_("Tables"))) tableFactory.AppendMenu(menu); + if (settings->GetDisplayOption(_("Partitions"))) + partitionFactory.AppendMenu(menu); if (settings->GetDisplayOption(_("FTS Configurations"))) { if (GetConnection()->BackendMinimumVersion(8, 3)) @@ -129,6 +133,11 @@ typeFactory.AppendMenu(menu); if (settings->GetDisplayOption(_("Views"))) viewFactory.AppendMenu(menu); + if (settings->GetDisplayOption(_("External Tables"))) + { + if (GetConnection() != 0 && GetConnection()->GetIsGreenplum()) + extTableFactory.AppendMenu(menu); + } } return menu; } @@ -233,6 +242,9 @@ browser->AppendCollection(this, sequenceFactory); if (settings->GetDisplayOption(_("Tables"))) browser->AppendCollection(this, tableFactory); + if (settings->GetDisplayOption(_("External Tables"))) + if (GetConnection() != 0 && GetConnection()->GetIsGreenplum()) + browser->AppendCollection(this, extTableFactory); if (settings->GetDisplayOption(_("Trigger functions"))) browser->AppendCollection(this, triggerFunctionFactory); if (settings->GetDisplayOption(_("Types"))) @@ -464,7 +476,7 @@ // View (yeah, I know - I didn't write it :-p ). This works fine *except* for // Get CreatePrivilege() which doesn't exist in these classes so must be fixed // up at this level. This needs a major rethink in the longer term - if (GetSchema()->GetMetaType() == PGM_TABLE || GetSchema()->GetMetaType() == PGM_VIEW) + if (GetSchema()->GetMetaType() == PGM_TABLE || GetSchema()->GetMetaType() == PGM_VIEW || GetSchema()->GetMetaType() == PGM_EXTTABLE) return GetSchema()->GetSchema()->GetCreatePrivilege(); else return GetSchema()->GetCreatePrivilege(); Index: schema/pgRole.cpp =================================================================== --- schema/pgRole.cpp (revision 7584) +++ schema/pgRole.cpp (working copy) @@ -94,6 +94,8 @@ sql += wxT(" CONNECTION LIMIT ") + NumToStr(GetConnectionLimit()); if (GetAccountExpires().IsValid()) AppendIfFilled(sql, wxT(" VALID UNTIL "), qtDbString(DateToAnsiStr(GetAccountExpires()))); + if (GetRolQueueName().Length() > 0) + AppendIfFilled(sql, wxT(" RESOURCE QUEUE "), GetRolQueueName()); sql +=wxT(";\n"); if (this->GetSuperuser() && !GetUpdateCatalog()) @@ -379,6 +381,16 @@ role->iSetComment(roles->GetVal(wxT("description"))); role->iSetConnectionLimit(roles->GetLong(wxT("rolconnlimit"))); + if (collection->GetServer()->GetConnection()->GetIsGreenplum()) + { + Oid rolresqueue = roles->GetOid(wxT("rolresqueue")); + if (rolresqueue != 0) + { + role->iSetRolQueueName(collection->GetServer()->ExecuteScalar(wxT("SELECT rsqname FROM pg_resqueue WHERE pg_resqueue.oid = ") + roles->GetVal(wxT("rolresqueue")))); + } + } + + wxString cfg=roles->GetVal(wxT("rolconfig")); if (!cfg.IsEmpty()) FillArray(role->GetConfigList(), cfg.Mid(1, cfg.Length()-2)); Index: schema/pgObject.cpp =================================================================== --- schema/pgObject.cpp (revision 7584) +++ schema/pgObject.cpp (working copy) @@ -26,6 +26,7 @@ #include "schema/pgType.h" #include "schema/pgDatabase.h" #include "schema/pgTable.h" +#include "schema/pgExtTable.h" #include "schema/pgColumn.h" #include "schema/pgView.h" #include "schema/pgType.h" @@ -236,6 +237,7 @@ case 'i': depFactory=&indexFactory; break; case 'S': depFactory=&sequenceFactory; break; case 'v': depFactory=&viewFactory; break; + case 'x': depFactory=&extTableFactory; break; case 'p': depFactory=&functionFactory; break; case 'n': depFactory=&schemaFactory; break; case 'y': depFactory=&typeFactory; break; @@ -782,6 +784,7 @@ break; case 'S': ownerFactory=&sequenceFactory; break; case 'v': ownerFactory=&viewFactory; break; + case 'x': ownerFactory=&extTableFactory; break; case 'c': // composite type handled in PG_TYPE case 's': // special case 't': // toast Index: schema/pgTable.cpp =================================================================== --- schema/pgTable.cpp (revision 7584) +++ schema/pgTable.cpp (working copy) @@ -26,6 +26,7 @@ #include "schema/pgRule.h" #include "schema/pgTrigger.h" #include "schema/pgConstraints.h" +#include "schema/pgPartition.h" // App headers @@ -36,6 +37,7 @@ inheritedTableCount=0; rowsCounted = false; showExtendedStatistics = false; + distributionIsRandom = false; } pgTable::~pgTable() @@ -166,7 +168,24 @@ sql += tmp; } +void pgTable::AppendStuffNoSql(wxString &sql, ctlTree *browser, pgaFactory &factory) +{ + pgCollection *collection=browser->FindCollection(factory, GetId()); + if (collection) + { + collection->ShowTreeDetail(browser); + treeObjectIterator idxIt(browser, collection); + pgObject *obj; + while ((obj = idxIt.GetNextObject()) != 0) + { + obj->ShowTreeDetail(browser); + } + } +} + + + wxString pgTable::GetSql(ctlTree *browser) { wxString colDetails, conDetails; @@ -309,6 +328,10 @@ sql += wxT("\nWITH ("); if (GetFillFactor().Length() > 0) sql += wxT("FILLFACTOR=") + GetFillFactor() + wxT(", "); + if (GetAppendOnly().Length() > 0) + sql += wxT("APPENDONLY=") + GetAppendOnly() + wxT(", "); + if (GetCompressLevel().Length() > 0) + sql += wxT("COMPRESSLEVEL=") + GetCompressLevel() + wxT(", "); if (GetHasOids()) sql += wxT("OIDS=TRUE"); else @@ -326,6 +349,67 @@ if (GetConnection()->BackendMinimumVersion(8, 0) && tablespace != GetDatabase()->GetDefaultTablespace()) sql += wxT("\nTABLESPACE ") + qtIdent(tablespace); + if (GetConnection()->GetIsGreenplum()) + { + // Add Greenplum DISTRIBUTED BY + if (distributionIsRandom) + { + sql += wxT("\nDISTRIBUTED RANDOMLY"); + } + else if (GetDistributionColNumbers().Length()==0) + { + // catalog table or other non-distributed table + } + else + { + // convert list of columns numbers to column names + wxStringTokenizer collist(GetDistributionColNumbers(), wxT(",")); + wxString cn; + wxString distributionColumns; + while (collist.HasMoreTokens()) + { + cn=collist.GetNextToken(); + pgSet *set=ExecuteSet( + wxT("SELECT attname\n") + wxT(" FROM pg_attribute\n") + wxT(" WHERE attrelid=") + GetOidStr() + wxT(" AND attnum IN (") + cn + wxT(")")); + if (set) + { + if (!distributionColumns.IsNull()) + { + distributionColumns += wxT(", "); + } + distributionColumns += qtIdent(set->GetVal(0)); + delete set; + } + } + + sql += wxT("\nDISTRIBUTED BY ("); + sql += distributionColumns; + + sql += wxT(")"); + } + + if (GetIsPartitioned()) + if (GetConnection()->BackendMinimumVersion(8,2,9) && GetConnection()->GetIsGreenplum()) + if (GetPartitionDef().Length() == 0) + { + wxString query = wxT("SELECT pg_get_partition_def("); + query += GetOidStr(); + query += wxT(", true) "); + wxString partition_def = GetDatabase()->ExecuteScalar(query); + iSetPartitionDef(partition_def); + // pg_get_partition_def() doesn't work on partitions + if (GetPartitionDef().Length() == 0) + iSetPartitionDef(wxT("-- This partition has subpartitions")); + } + if (partitionDef.Length() > 0) + sql += wxT("\n") + partitionDef + wxT("\n"); + + + } + + sql += wxT(";\n") + GetOwnerSql(7, 3); @@ -351,6 +435,10 @@ AppendStuff(sql, browser, indexFactory); AppendStuff(sql, browser, ruleFactory); AppendStuff(sql, browser, triggerFactory); + if (partitionDef.Length() > 0) + { + AppendStuffNoSql(sql, browser, partitionFactory); + } } return sql; } @@ -571,7 +659,10 @@ browser->AppendCollection(this, indexFactory); browser->AppendCollection(this, ruleFactory); browser->AppendCollection(this, triggerFactory); + if (GetIsPartitioned()) + browser->AppendCollection(this, partitionFactory); + // convert list of columns numbers to column names wxStringTokenizer collist(GetPrimaryKeyColNumbers(), wxT(",")); wxString cn; @@ -939,12 +1030,29 @@ wxT(" WHERE tgrelid=rel.oid) AS isrepl\n"); if (collection->GetConnection()->BackendMinimumVersion(8, 2)) query += wxT(", substring(array_to_string(reloptions, ',') from 'fillfactor=([0-9]*)') AS fillfactor \n"); + if (collection->GetConnection()->GetIsGreenplum()) + { + query += wxT(", gpd.localoid, gpd.attrnums \n"); + query += wxT(", substring(array_to_string(reloptions, ',') from 'appendonly=([a-z]*)') AS appendonly \n"); + query += wxT(", substring(array_to_string(reloptions, ',') from 'compresslevel=([0-9]*)') AS compresslevel \n"); + if (collection->GetConnection()->GetIsGreenplum() && collection->GetConnection()->BackendMinimumVersion(8, 2, 9)) + query += wxT(", rel.oid in (select parrelid from pg_partition) as ispartitioned\n"); + } query += wxT(" FROM pg_class rel\n") wxT(" LEFT OUTER JOIN pg_tablespace ta on ta.oid=rel.reltablespace\n") wxT(" LEFT OUTER JOIN pg_description des ON (des.objoid=rel.oid AND des.objsubid=0)\n") - wxT(" LEFT OUTER JOIN pg_constraint c ON c.conrelid=rel.oid AND c.contype='p'\n") - wxT(" WHERE relkind IN ('r','s','t') AND relnamespace = ") + collection->GetSchema()->GetOidStr() + wxT("\n") - + restriction + + wxT(" LEFT OUTER JOIN pg_constraint c ON c.conrelid=rel.oid AND c.contype='p'\n"); + if (collection->GetConnection()->GetIsGreenplum()) + { + query += wxT(" LEFT OUTER JOIN gp_distribution_policy gpd ON gpd.localoid=rel.oid\n"); + //if (collection->GetConnection()->GetIsGreenplum() && collection->GetConnection()->BackendMinimumVersion(8, 2, 9)) + // query += wxT(" LEFT OUTER JOIN pg_partition ON rel.oid = parrelid\n"); + } + query += wxT(" WHERE relkind IN ('r','s','t') AND relnamespace = ") + collection->GetSchema()->GetOidStr() + wxT("\n"); + // Greenplum: Eliminate (sub)partitions from the display, only show the parent partitioned table + if (collection->GetConnection()->GetIsGreenplum() && collection->GetConnection()->BackendMinimumVersion(8, 2, 9)) + query += wxT("AND rel.oid NOT IN (select parchildrelid from pg_partition_rule)"); + query += restriction + wxT(" ORDER BY relname"); } else @@ -997,6 +1105,27 @@ cn=cn.Mid(1, cn.Length()-2); table->iSetPrimaryKeyColNumbers(cn); + if (collection->GetConnection()->GetIsGreenplum()) + { + Oid lo=tables->GetOid(wxT("localoid")); + wxString db=tables->GetVal(wxT("attrnums")); + db=db.Mid(1, db.Length()-2); + table->iSetDistributionColNumbers(db); + if (lo > 0 && db.Length() == 0) + table->iSetDistributionIsRandom(); + table->iSetAppendOnly(tables->GetVal(wxT("appendonly"))); + table->iSetCompressLevel(tables->GetVal(wxT("compresslevel"))); + + table->iSetPartitionDef(wxT("")); + table->iSetIsPartitioned(false); + + if (collection->GetConnection()->BackendMinimumVersion(8,2,9)) + { + table->iSetIsPartitioned(tables->GetBool(wxT("ispartitioned"))); + } + + } + if (browser) { browser->AppendObject(collection, table); Index: schema/pgColumn.cpp =================================================================== --- schema/pgColumn.cpp (revision 7584) +++ schema/pgColumn.cpp (working copy) @@ -296,7 +296,7 @@ if (GetTable()->GetMetaType() != PGM_CATALOGOBJECT) { properties->AppendItem(_("Default"), GetDefault()); - if (GetTable()->GetMetaType() != PGM_VIEW) + if (GetTable()->GetMetaType() != PGM_VIEW && GetTable()->GetMetaType() != PGM_EXTTABLE) { properties->AppendItem(_("Sequence"), database->GetSchemaPrefix(GetSerialSchema()) + GetSerialSequence()); Index: schema/pgServer.cpp =================================================================== --- schema/pgServer.cpp (revision 7584) +++ schema/pgServer.cpp (working copy) @@ -30,6 +30,7 @@ #include "schema/pgGroup.h" #include "schema/pgUser.h" #include "schema/pgRole.h" +#include "schema/pgResQueue.h" #include "agent/pgaJob.h" #include "utils/utffile.h" #include "utils/pgfeatures.h" @@ -101,6 +102,9 @@ groupRoleFactory.AppendMenu(menu); if (settings->GetDisplayOption(_("Users/login roles"))) loginRoleFactory.AppendMenu(menu); + if (GetConnection()->GetIsGreenplum()) + if (settings->GetDisplayOption(_("ResQueues/resource queues"))) + resQueueFactory.AppendMenu(menu); } else { @@ -850,7 +854,10 @@ if (settings->GetDisplayOption(_("Groups/group roles"))) browser->AppendCollection(this, groupRoleFactory); if (settings->GetDisplayOption(_("Users/login roles"))) - browser->AppendCollection(this, loginRoleFactory); + browser->AppendCollection(this, loginRoleFactory); + if (GetConnection()->GetIsGreenplum()) + if (settings->GetDisplayOption(_("ResQueues/resource queues"))) + browser->AppendCollection(this, resQueueFactory); } else { Index: pgAdmin3.vcproj =================================================================== --- pgAdmin3.vcproj (revision 7584) +++ pgAdmin3.vcproj (working copy) @@ -1,10 +1,11 @@ - @@ -197,6 +200,8 @@ MapFileName=".\Debug/pgAdmin3.map" SubSystem="2" ResourceOnlyDLL="false" + RandomizedBaseAddress="1" + DataExecutionPrevention="0" TargetMachine="1" /> - @@ -575,6 +577,10 @@ > + + @@ -1186,6 +1192,14 @@ > + + + + @@ -1218,6 +1232,10 @@ > + + @@ -1254,6 +1272,18 @@ > + + + + + + @@ -1890,6 +1920,10 @@ > + + @@ -2194,6 +2228,10 @@ > + + @@ -2234,6 +2272,14 @@ > + + + + @@ -2426,11 +2472,11 @@ > + + @@ -3019,6 +3069,14 @@ > + + + + @@ -3199,6 +3257,10 @@ > + + @@ -3603,11 +3665,11 @@ > GetIsEdb()) DisplayHelp(page.Mid(3), HELP_ENTERPRISEDB); + else if (connection->GetIsGreenplum()) + DisplayHelp(page.Mid(3), HELP_GREENPLUM); else DisplayHelp(page.Mid(3), HELP_POSTGRESQL); } Index: dlg/dlgColumn.cpp =================================================================== --- dlg/dlgColumn.cpp (revision 7584) +++ dlg/dlgColumn.cpp (working copy) @@ -59,7 +59,7 @@ { column=node; table=parentNode; - wxASSERT(!table || (table->GetMetaType() == PGM_TABLE || table->GetMetaType() == PGM_VIEW)); + wxASSERT(!table || (table->GetMetaType() == PGM_TABLE || table->GetMetaType() == PGM_VIEW || table->GetMetaType() == PGM_EXTTABLE)); txtAttstattarget->SetValidator(numericValidator); @@ -262,6 +262,14 @@ cbDatatype->Disable(); txtAttstattarget->Disable(); } + else if (column->GetTable()->GetMetaType() == PGM_EXTTABLE) // Disable controls not valid for external table columns + { + txtName->Disable(); + chkNotNull->Disable(); + txtLength->Disable(); + cbDatatype->Disable(); + txtAttstattarget->Disable(); + } } else { Index: gqb/gqbBrowser.cpp =================================================================== --- gqb/gqbBrowser.cpp (revision 7584) +++ gqb/gqbBrowser.cpp (working copy) @@ -32,6 +32,7 @@ #include "images/catalog-sm.xpm" #include "images/catalogs.xpm" #include "images/catalogobject-sm.xpm" +#include "images/exttable-sm.xpm" // Greenplum external tables BEGIN_EVENT_TABLE(gqbBrowser, wxTreeCtrl) EVT_TREE_ITEM_ACTIVATED(GQB_BROWSER, gqbBrowser::OnItemActivated) @@ -54,6 +55,7 @@ imageList->Add(wxIcon(catalog_sm_xpm)); imageList->Add(wxIcon(catalogobject_sm_xpm)); imageList->Add(wxIcon(view_sm_xpm)); + imageList->Add(wxIcon(exttable_sm_xpm)); this->AssignImageList(imageList); } Index: gqb/gqbSchema.cpp =================================================================== --- gqb/gqbSchema.cpp (revision 7584) +++ gqb/gqbSchema.cpp (working copy) @@ -113,7 +113,7 @@ wxT(" WHERE ((c.relhasrules AND (EXISTS (\n") wxT(" SELECT r.rulename FROM pg_rewrite r\n") wxT(" WHERE ((r.ev_class = c.oid)\n") - wxT(" AND (bpchar(r.ev_type) = '1'::bpchar)) ))) OR (c.relkind = 'v'::char))\n") + wxT(" AND (bpchar(r.ev_type) = '1'::bpchar)) ))) OR (c.relkind = 'v'::char))\n") wxT(" AND relnamespace = ") + NumToStr(oidVal) + wxT("\n") + restriction + wxT(" ORDER BY relname"); @@ -134,5 +134,34 @@ } } + + // And Greenplum External Tables; + if (conn->GetIsGreenplum()) + { + query=wxT("SELECT c.oid, c.xmin, c.relname, pg_get_userbyid(c.relowner) AS viewowner, c.relacl, description") + wxT(" FROM pg_class c\n") + wxT(" LEFT OUTER JOIN pg_description des ON (des.objoid=c.oid and des.objsubid=0)\n") + wxT(" WHERE (c.relkind = 'x'::char)\n") + wxT(" AND relnamespace = ") + NumToStr(oidVal) + wxT("\n") + + restriction + + wxT(" ORDER BY relname"); + + pgSet *exttables = conn->ExecuteSet(query); + if (exttables) + { + while (!exttables->Eof()) + { + wxString tmpname = wxString(exttables->GetVal(wxT("relname"))); + gqbTable *table = new gqbTable(this, tmpname, GQB_VIEW); + parent=tablesBrowser->AppendItem(parentNode, exttables->GetVal(wxT("relname")) , 8, 8, table); + + // Create columns inside this view. + table->createObjects(tablesBrowser,conn,exttables->GetOid(wxT("oid")),parent); + + exttables->MoveNext(); + } + } + } + tablesBrowser->SortChildren(parentNode); } Index: ui/module.mk =================================================================== --- ui/module.mk (revision 7584) +++ ui/module.mk (working copy) @@ -24,6 +24,7 @@ $(srcdir)/ui/dlgDirectDbg.xrc \ $(srcdir)/ui/dlgDomain.xrc \ $(srcdir)/ui/dlgEditGridOptions.xrc \ + $(srcdir)/ui/dlgExtTable.xrc \ $(srcdir)/ui/dlgFindReplace.xrc \ $(srcdir)/ui/dlgForeignKey.xrc \ $(srcdir)/ui/dlgFunction.xrc \ Index: ui/embed-xrc.bat ===================================================================