diff --git a/Release/pgAdmin3.exe b/Release/pgAdmin3.exe index e0b9143..d0d1d34 100644 Binary files a/Release/pgAdmin3.exe and b/Release/pgAdmin3.exe differ diff --git a/frm/frmOptions.cpp b/frm/frmOptions.cpp index 16df9e7..d35756f 100644 --- a/frm/frmOptions.cpp +++ b/frm/frmOptions.cpp @@ -394,6 +394,7 @@ frmOptions::frmOptions(frmMain *parent) lstDisplay->Append(_("Event Triggers")); lstDisplay->Append(_("Extensions")); lstDisplay->Append(_("Publications")); + lstDisplay->Append(_("Subscriptions")); lstDisplay->Append(_("Foreign Data Wrappers")); lstDisplay->Append(_("Foreign Servers")); lstDisplay->Append(_("User Mappings")); diff --git a/include/schema/pgSubscription.h b/include/schema/pgSubscription.h new file mode 100644 index 0000000..a5d250c --- /dev/null +++ b/include/schema/pgSubscription.h @@ -0,0 +1,121 @@ +////////////////////////////////////////////////////////////////////////// +// +// pgAdmin III - PostgreSQL Tools +// +// Copyright (C) 2002 - 2016, The pgAdmin Development Team +// This software is released under the PostgreSQL Licence +// +// pgExtension.h PostgreSQL Extension +// +////////////////////////////////////////////////////////////////////////// + +#ifndef PGSUBSCRIPTION_H +#define PGSUBSCRIPTION_H + +#include "pgDatabase.h" + +class pgCollection; +class pgSubscriptionFactory : public pgDatabaseObjFactory +{ +public: + pgSubscriptionFactory(); + virtual dlgProperty *CreateDialog(frmMain *frame, pgObject *node, pgObject *parent); + virtual pgObject *CreateObjects(pgCollection *obj, ctlTree *browser, const wxString &restr = wxEmptyString); + virtual pgCollection *CreateCollection(pgObject *obj); +}; +extern pgSubscriptionFactory subscriptionFactory; + +class pgSubscription : public pgDatabaseObject +{ +public: + pgSubscription(const wxString &newName = wxT("")); + + wxString GetTranslatedMessage(int kindOfMessage) const; + void ShowTreeDetail(ctlTree *browser, frmMain *form = 0, ctlListView *properties = 0, ctlSQLBox *sqlPane = 0); + bool CanDropCascaded() + { + return true; + } + + wxString GetPubStr() const + { + return publications; + } + void iSetPubStr(const wxString &s) + { + publications = s; + } + wxString GetConnInfo() const + { + return conninfo; + } + void iSetSlotName(const wxString &s) { + slotname = s; + } + wxString GetSlotName() const + { + return slotname; + } + void iSetConnInfo(const wxString &s) + { + conninfo = s; + } + bool GetIsEnabled() const + { + return enabled; + } + void iSetIsEnabled(const bool b) + { + enabled = b; + } + wxString GetIsSyncCommit() const + { + return subsynccommit; + } + void iSetIsSyncCommit(const wxString &s) + { + subsynccommit = s; + } + wxString GetStrOper() const + { + wxString s = wxT(""); + s += wxT("enabled = ")+BoolToStr(GetIsEnabled()); + s += wxT(", synchronous_commit = ")+ subsynccommit; + s += wxT(", slot_name = "); + if (slotname.IsEmpty()) s += wxT("NONE"); + else s += wxT("'")+slotname+wxT("'"); + + //s += wxT(", slot_name = ")+ !slotname.IsEmpty() ? wxT("'")+slotname+wxT("'") : wxT("NONE"); + return s; + } + + bool DropObject(wxFrame *frame, ctlTree *browser, bool cascaded); + wxString GetSql(ctlTree *browser); + pgObject *Refresh(ctlTree *browser, const wxTreeItemId item); + + bool HasStats() + { + return false; + } + bool HasDepends() + { + return false; + } + bool HasReferences() + { + return false; + } + +private: + wxString conninfo,publications,slotname,subname,subsynccommit; + bool enabled; +}; + +class pgSubscriptionCollection : public pgDatabaseObjCollection +{ +public: + pgSubscriptionCollection(pgaFactory *factory, pgDatabase *db); + wxString GetTranslatedMessage(int kindOfMessage) const; +}; + +#endif diff --git a/include/slony/slSubscription.h b/include/slony/slSubscription.h index ca1cfa9..4784f5c 100644 --- a/include/slony/slSubscription.h +++ b/include/slony/slSubscription.h @@ -30,7 +30,7 @@ public: protected: int exportedIconId; }; -extern slSubscriptionFactory subscriptionFactory; +extern slSubscriptionFactory slsubscriptionFactory; class slSubscription : public slSetObject diff --git a/schema/pgDatabase.cpp b/schema/pgDatabase.cpp index ce74621..89502ee 100644 --- a/schema/pgDatabase.cpp +++ b/schema/pgDatabase.cpp @@ -21,6 +21,7 @@ #include "schema/pgCast.h" #include "schema/pgExtension.h" #include "schema/pgPublication.h" +#include "schema/pgSubscription.h" #include "schema/pgForeignDataWrapper.h" #include "schema/pgLanguage.h" #include "schema/pgSchema.h" @@ -147,6 +148,8 @@ wxMenu *pgDatabase::GetNewMenu() extensionFactory.AppendMenu(menu); if (settings->GetDisplayOption(_("Publications")) && GetConnection()->BackendMinimumVersion(10, 0)) publicationFactory.AppendMenu(menu); + if (settings->GetDisplayOption(_("Subscriptions")) && GetConnection()->BackendMinimumVersion(10, 0)) + subscriptionFactory.AppendMenu(menu); if (settings->GetDisplayOption(_("Foreign Data Wrappers")) && GetConnection()->BackendMinimumVersion(8, 4)) foreignDataWrapperFactory.AppendMenu(menu); if (settings->GetDisplayOption(_("Languages"))) @@ -627,6 +630,8 @@ void pgDatabase::ShowTreeDetail(ctlTree *browser, frmMain *form, ctlListView *pr browser->AppendCollection(this, extensionFactory); if (settings->GetDisplayOption(_("Publications")) && GetConnection()->BackendMinimumVersion(10, 0)) browser->AppendCollection(this, publicationFactory); + if (settings->GetDisplayOption(_("Subscriptions")) && GetConnection()->BackendMinimumVersion(10, 0)) + browser->AppendCollection(this, subscriptionFactory); if (settings->GetDisplayOption(_("Foreign Data Wrappers")) && GetConnection()->BackendMinimumVersion(8, 4)) browser->AppendCollection(this, foreignDataWrapperFactory); if (settings->GetDisplayOption(_("Languages"))) diff --git a/schema/pgSubscription.cpp b/schema/pgSubscription.cpp new file mode 100644 index 0000000..ed107ff --- /dev/null +++ b/schema/pgSubscription.cpp @@ -0,0 +1,244 @@ +////////////////////////////////////////////////////////////////////////// +// +// pgAdmin III - PostgreSQL Tools +// +// Copyright (C) 2002 - 2016, The pgAdmin Development Team +// This software is released under the PostgreSQL Licence +// +// pgPublication.cpp - Subscription class +// +////////////////////////////////////////////////////////////////////////// + +// wxWindows headers +#include + +// App headers +#include "pgAdmin3.h" +#include "utils/misc.h" +#include "schema/pgSubscription.h" + + +pgSubscription::pgSubscription(const wxString &newName) + : pgDatabaseObject(subscriptionFactory, newName) +{ +} + +wxString pgSubscription::GetTranslatedMessage(int kindOfMessage) const +{ + wxString message = wxEmptyString; + + switch (kindOfMessage) + { + case RETRIEVINGDETAILS: + message = _("Retrieving details on subscription"); + message += wxT(" ") + GetName(); + break; + case REFRESHINGDETAILS: + message = _("Refreshing subscription"); + message += wxT(" ") + GetName(); + break; + case DROPINCLUDINGDEPS: + message = wxString::Format(_("Are you sure you wish to drop subscription \"%s\" including all objects that depend on it?"), + GetFullIdentifier().c_str()); + break; + case DROPEXCLUDINGDEPS: + message = wxString::Format(_("Are you sure you wish to drop subscription \"%s\"?"), + GetFullIdentifier().c_str()); + break; + case DROPCASCADETITLE: + message = _("Drop subscription cascaded?"); + break; + case DROPTITLE: + message = _("Drop subscription?"); + break; + case PROPERTIESREPORT: + message = _("Subscription properties report"); + message += wxT(" - ") + GetName(); + break; + case PROPERTIES: + message = _("Subscription properties"); + break; + case DDLREPORT: + message = _("Subscription DDL report"); + message += wxT(" - ") + GetName(); + break; + case DDL: + message = _("Subscription DDL"); + break; + case DEPENDENCIESREPORT: + message = _("Subscription dependencies report"); + message += wxT(" - ") + GetName(); + break; + case DEPENDENCIES: + message = _("Subscription dependencies"); + break; + case DEPENDENTSREPORT: + message = _("Subscription dependents report"); + message += wxT(" - ") + GetName(); + break; + case DEPENDENTS: + message = _("Subscription dependents"); + break; + } + + return message; +} + +bool pgSubscription::DropObject(wxFrame *frame, ctlTree *browser, bool cascaded) +{ + wxString sql = wxT("DROP SUBSCRIPTION ") + GetQuotedIdentifier(); + if (cascaded) + sql += wxT(" CASCADE"); + return GetDatabase()->ExecuteVoid(sql); +} + + +wxString pgSubscription::GetSql(ctlTree *browser) +{ + if (sql.IsNull()) + { + sql = wxT("-- Subscription: ") + GetQuotedIdentifier() + wxT("\n\n") + + wxT("-- DROP SUBSCRIPTION ") + GetQuotedIdentifier() + wxT(";") + + wxT("\n\n CREATE SUBSCRIPTION ") + GetName()+wxT("\n") + + wxT(" CONNECTION E") + qtConnString(GetConnInfo())+wxT("\n") + + wxT(" PUBLICATION ") + GetPubStr()+wxT(""); + sql += wxT("\n WITH (") + GetStrOper() + wxT(")"); + + sql += wxT(";\n"); + } + return sql; +} + + +void pgSubscription::ShowTreeDetail(ctlTree *browser, frmMain *form, ctlListView *properties, ctlSQLBox *sqlPane) +{ + if (properties) + { + CreateListColumns(properties); + + properties->AppendItem(_("Name"), GetName()); + properties->AppendItem(_("OID"), GetOid()); + properties->AppendItem(_("Owner"), GetOwner()); + properties->AppendItem(_("Publications"), GetPubStr()); + //properties->AppendYesNoItem(_("Relocatable?"), GetIsRelocatable()); + properties->AppendItem(_("Options"), GetStrOper()); + properties->AppendItem(_("Comment"), firstLineOnly(GetComment())); + } +} + + + +pgObject *pgSubscription::Refresh(ctlTree *browser, const wxTreeItemId item) +{ + pgObject *language = 0; + pgCollection *coll = browser->GetParentCollection(item); + if (coll) + language = subscriptionFactory.CreateObjects(coll, 0, wxT("\n and oid=") + GetOidStr()); + + return language; +} + + + +pgObject *pgSubscriptionFactory::CreateObjects(pgCollection *collection, ctlTree *browser, const wxString &restriction) +{ + wxString sql; + pgSubscription *subscription = 0; + bool superu=collection->GetDatabase()->GetConnection()->IsSuperuser(); + //wxString dbname=collection->GetDatabase()->GetConnection()->GetDbOid; + OID db=collection->GetDatabase()->GetConnection()->GetDbOid(); + sql = wxT("select oid,subname,pg_get_userbyid(subowner) AS \"owner\",subenabled,subconninfo,subslotname,subsynccommit,subpublications,obj_description(oid,'pg_subscription') as comment from pg_subscription where subdbid=") + +NumToStr(db)+ wxT("\n") + + restriction + wxT("\n"); + pgSet *subscriptions = collection->GetDatabase()->ExecuteSet(sql); + + if (subscriptions) + { + while (!subscriptions->Eof()) + { + wxString tmp; + tmp = subscriptions->GetVal(wxT("subpublications")); + tmp.Replace(wxT("{"), wxT("")); + tmp.Replace(wxT("}"), wxT("")); + + subscription = new pgSubscription(subscriptions->GetVal(wxT("subname"))); + subscription->iSetDatabase(collection->GetDatabase()); + subscription->iSetOid(subscriptions->GetOid(wxT("oid"))); + subscription->iSetOwner(subscriptions->GetVal(wxT("owner"))); + subscription->iSetPubStr(tmp); + subscription->iSetConnInfo(subscriptions->GetVal(wxT("subconninfo"))); + subscription->iSetSlotName(subscriptions->GetVal(wxT("subslotname"))); + //subscription->iSetName(subscriptions->GetVal(wxT("subname")); + subscription->iSetIsEnabled(subscriptions->GetBool(wxT("subenabled"))); + subscription->iSetIsSyncCommit(subscriptions->GetVal(wxT("subsynccommit"))); + subscription->iSetComment(subscriptions->GetVal(wxT("comment"))); + + if (browser) + { + browser->AppendObject(collection, subscription); + + subscriptions->MoveNext(); + } + else + break; + } + + delete subscriptions; + } + return subscription; +} + + +///////////////////////////// + +pgSubscriptionCollection::pgSubscriptionCollection(pgaFactory *factory, pgDatabase *db) + : pgDatabaseObjCollection(factory, db) +{ +} + + +wxString pgSubscriptionCollection::GetTranslatedMessage(int kindOfMessage) const +{ + wxString message = wxEmptyString; + + switch (kindOfMessage) + { + case RETRIEVINGDETAILS: + message = _("Retrieving details on subscriptions"); + break; + case REFRESHINGDETAILS: + message = _("Refreshing subscriptions"); + break; + case OBJECTSLISTREPORT: + message = _("Subscriptions list report"); + break; + } + + return message; +} + +/////////////////////////////////////////////////// + +#include "images/extension.pngc" +#include "images/extension-sm.pngc" +#include "images/extensions.pngc" +#include "images/slsubscription.pngc" +#include "images/slsubscriptions.pngc" + +pgSubscriptionFactory::pgSubscriptionFactory() + : pgDatabaseObjFactory(__("Subscription"), __("New Subscription..."), __("Create a new Subscription."), extension_png_img, extension_sm_png_img) +{ +} + + +pgCollection *pgSubscriptionFactory::CreateCollection(pgObject *obj) +{ + return new pgSubscriptionCollection(GetCollectionFactory(), (pgDatabase *)obj); +} +dlgProperty *pgSubscriptionFactory::CreateDialog(frmMain *frame, pgObject *node, pgObject *parent) +{ + return NULL; +} + +pgSubscriptionFactory subscriptionFactory; +static pgaCollectionFactory cf(&subscriptionFactory, __("Subscriptions"), slsubscriptions_png_img); diff --git a/slony/dlgRepSubscription.cpp b/slony/dlgRepSubscription.cpp index 99b7a84..8e0d565 100644 --- a/slony/dlgRepSubscription.cpp +++ b/slony/dlgRepSubscription.cpp @@ -121,7 +121,7 @@ int dlgRepSubscription::Go(bool modal) pgObject *dlgRepSubscription::CreateObject(pgCollection *collection) { - pgObject *obj = subscriptionFactory.CreateObjects(collection, 0, + pgObject *obj = slsubscriptionFactory.CreateObjects(collection, 0, wxT(" WHERE set_id = ") + NumToStr(set->GetSlId()) + wxT(" AND sub_receiver = ") + NumToStr(cluster->GetLocalNodeID())); diff --git a/slony/slSet.cpp b/slony/slSet.cpp index 4c4e66a..7dfbc45 100644 --- a/slony/slSet.cpp +++ b/slony/slSet.cpp @@ -50,7 +50,7 @@ wxMenu *slSet::GetNewMenu() slTableFactory.AppendMenu(menu); } - subscriptionFactory.AppendMenu(menu); + slsubscriptionFactory.AppendMenu(menu); return menu; } @@ -246,7 +246,7 @@ void slSet::ShowTreeDetail(ctlTree *browser, frmMain *form, ctlListView *propert browser->AppendCollection(this, slSequenceFactory); browser->AppendCollection(this, slTableFactory); } - browser->AppendCollection(this, subscriptionFactory); + browser->AppendCollection(this, slsubscriptionFactory); } diff --git a/slony/slSubscription.cpp b/slony/slSubscription.cpp index 73557b1..1abd03d 100644 --- a/slony/slSubscription.cpp +++ b/slony/slSubscription.cpp @@ -23,16 +23,16 @@ slSubscription::slSubscription(slSet *s, const wxString &newName) - : slSetObject(s, subscriptionFactory, newName) + : slSetObject(s, slsubscriptionFactory, newName) { } int slSubscription::GetIconId() { if (GetReceiverId() == GetCluster()->GetLocalNodeID()) - return subscriptionFactory.GetIconId(); + return slsubscriptionFactory.GetIconId(); else - return subscriptionFactory.GetExportedIconId(); + return slsubscriptionFactory.GetExportedIconId(); } @@ -194,7 +194,7 @@ pgObject *slSubscription::Refresh(ctlTree *browser, const wxTreeItemId item) pgObject *subscription = 0; pgCollection *coll = browser->GetParentCollection(item); if (coll) - subscription = subscriptionFactory.CreateObjects(coll, 0, wxT(" WHERE sub_set=") + NumToStr(GetSet()->GetSlId()) + subscription = slsubscriptionFactory.CreateObjects(coll, 0, wxT(" WHERE sub_set=") + NumToStr(GetSet()->GetSlId()) + wxT(" AND sub_receiver = ") + NumToStr(GetReceiverId()) + wxT("\n")); return subscription; } @@ -290,5 +290,5 @@ pgCollection *slSubscriptionFactory::CreateCollection(pgObject *obj) } -slSubscriptionFactory subscriptionFactory; -static pgaCollectionFactory cf(&subscriptionFactory, __("Subscriptions"), slsubscriptions_png_img); +slSubscriptionFactory slsubscriptionFactory; +static pgaCollectionFactory cf(&slsubscriptionFactory, __("Subscriptions"), slsubscriptions_png_img); diff --git a/utils/sysSettings.cpp b/utils/sysSettings.cpp index 5526912..e0276e0 100644 --- a/utils/sysSettings.cpp +++ b/utils/sysSettings.cpp @@ -125,6 +125,8 @@ bool sysSettings::GetDisplayOption(const wxString &objtype, bool GetDefault) engtype = wxT("Extensions"); else if (objtype == _("Publications")) engtype = wxT("Publications"); + else if (objtype == _("Subscriptions")) + engtype = wxT("Subscriptions"); else if (objtype == _("Synonyms")) engtype = wxT("Synonyms"); else if (objtype == _("Schemas")) @@ -220,6 +222,7 @@ void sysSettings::SetDisplayOption(const wxString &objtype, bool display) else if (objtype == _("Event Triggers")) engtype = wxT("Event Triggers"); else if (objtype == _("Extensions")) engtype = wxT("Extensions"); else if (objtype == _("Publications")) engtype = wxT("Publications"); + else if (objtype == _("Subscriptions")) engtype = wxT("Subscriptions"); else if (objtype == _("Synonyms")) engtype = wxT("Synonyms"); else if (objtype == _("Schemas")) engtype = wxT("Schemas"); else if (objtype == _("Slony-I Clusters")) engtype = wxT("Slony-I Clusters");