From 20ff51db29cbe239acc3b376f88fc1cee058232c Mon Sep 17 00:00:00 2001 From: lsv Date: Thu, 14 Aug 2025 15:10:44 +0500 Subject: [PATCH] fix publication MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Исправлен вывод SQL команд создания публикаций. --- include/schema/pgPublication.h | 39 +++++++++- schema/pgPublication.cpp | 137 +++++++++++++++++++++++---------- 2 files changed, 136 insertions(+), 40 deletions(-) diff --git a/include/schema/pgPublication.h b/include/schema/pgPublication.h index 4f6bf9b..b1182f3 100644 --- a/include/schema/pgPublication.h +++ b/include/schema/pgPublication.h @@ -45,6 +45,14 @@ public: { tables = s; } + wxString GetiSchemasList() const + { + return schemas; + } + void iSetSchemasList(const wxString& s) + { + schemas = s; + } wxString GetVersion() const { return version; @@ -89,7 +97,35 @@ public: { publish_via_partition_root = b; } + wxString GetTableColumns(const wxString& table) { + auto it = tablesdetail.find(table); + wxString v; + if (it != tablesdetail.end()) { + v = it->second; + } + return v; + } + wxString GetTableFilter(const wxString& table) { + wxString key = " where table filter for " + table; + return GetTableColumns(key); + } + void iAppendTable(const wxString& table, const wxString& listcolumns) { + auto it = tablesdetail.find(table); + wxString v; + if (it != tablesdetail.end()) { + v = it->second; + wxASSERT("failure uniq keymap columns"); + wxTrap(); + } + else { + tablesdetail.insert({ table,listcolumns }); + } + } + void iAppendTableFilter(const wxString& table, const wxString& listcolumns) { + wxString key = " where table filter for " + table; + iAppendTable(key,listcolumns); + } wxString GetStrOper() const { wxString s = wxT(""); @@ -123,8 +159,9 @@ public: } private: - wxString tables, version; + wxString tables, schemas, version; bool all,ins,upd,del, publish_via_partition_root; + std::map tablesdetail; }; class pgPublicationCollection : public pgDatabaseObjCollection diff --git a/schema/pgPublication.cpp b/schema/pgPublication.cpp index e60e101..fdce219 100644 --- a/schema/pgPublication.cpp +++ b/schema/pgPublication.cpp @@ -101,20 +101,42 @@ wxString pgPublication::GetSql(ctlTree *browser) + wxT("-- DROP PUBLICATION ") + GetQuotedIdentifier() + wxT(";") + wxT("\n\n CREATE PUBLICATION ") + GetName(); - if (GetIsAll()) - { - sql += wxT("\n FOR ALL TABLES "); - } else - { - sql += wxT("\n FOR TABLE "); - if (!GetTablesStr().IsEmpty()) - sql += wxT("") + GetTablesStr(); + if (GetIsAll()) { + sql += wxT("\n FOR ALL TABLES"); } - if (GetIsIns()&&GetIsUpd()&&GetIsDel()&&!GetIsViaRoot()) + else + { + sql += wxT("\n FOR "); + wxString acc;; + wxString listtab= GetTablesStr(); + if (!listtab.IsEmpty()) + { + acc = "TABLE "; + wxArrayString atabs=wxSplit(listtab, ','); + for (int i = 0; i < atabs.Count(); i++) { + wxString fullname = atabs[i]; + if (i > 0 ) acc += "\n ,"; + acc += fullname; + wxString cols = GetTableColumns(fullname); + if (!cols.IsEmpty()) acc = acc + "(" + cols + ")"; + wxString filter = GetTableFilter(fullname); + if (!filter.IsEmpty()) acc = acc + " WHERE " + filter + ""; + } + //acc += "\n "; + } + wxString slist = GetiSchemasList(); + if (!slist.IsEmpty()) { + if (acc.Length() > 0) acc += "\n ,"; + acc += "TABLES IN SCHEMA "+slist; + + } + sql += wxT("") + acc; + } + if (GetIsIns()&&GetIsUpd()&&GetIsDel()&&!GetIsViaRoot()) { } - else + else { sql += wxT("\n WITH ("); wxString opts = wxEmptyString; @@ -156,7 +178,7 @@ pgObject *pgPublication::Refresh(ctlTree *browser, const wxTreeItemId item) pgObject *language = 0; pgCollection *coll = browser->GetParentCollection(item); if (coll) - language = publicationFactory.CreateObjects(coll, 0, wxT("\n WHERE x.oid=") + GetOidStr()); + language = publicationFactory.CreateObjects(coll, 0, wxT("\n WHERE oid=") + GetOidStr()); return language; } @@ -167,46 +189,83 @@ pgObject *pgPublicationFactory::CreateObjects(pgCollection *collection, ctlTree { wxString sql; pgPublication *publication = 0; - wxString pg13=""; - if (collection->GetDatabase()->BackendMinimumVersion(13, 0)) { - pg13 = ", pubviaroot"; - } - - sql = wxT("select x.oid,x.pubname, pg_get_userbyid(x.pubowner) AS owner, x.puballtables, x.pubinsert, x.pubupdate, x.pubdelete, obj_description(x.oid,'pg_publication') AS comment, t.t") - + pg13 + wxT("\n") - wxT(" FROM pg_publication x\n") - wxT(" LEFT JOIN LATERAL (select string_agg(schemaname||'.'||tablename,', ') t from pg_publication_tables where pubname=x.pubname) t on true \n") - wxT(" ") - + restriction + wxT("\n") - wxT(" ORDER BY x.pubname"); + sql=R"(with rel as ( +SELECT pr.prpubid,quote_ident(n.nspname)|| '.'||quote_ident(c.relname) fulltable, pg_get_expr(pr.prqual, c.oid) rowfilter, (CASE WHEN pr.prattrs IS NOT NULL THEN + pg_catalog.array_to_string( ARRAY(SELECT attname + FROM + pg_catalog.generate_series(0, pg_catalog.array_upper(pr.prattrs::pg_catalog.int2[], 1)) s, + pg_catalog.pg_attribute + WHERE attrelid = c.oid AND attnum = prattrs[s]), ', ') + ELSE NULL END) cols +FROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n ON c.relnamespace = n.oid + JOIN pg_catalog.pg_publication_rel pr ON c.oid = pr.prrelid +), shs as ( +select pn.pnpubid,string_agg(pn.pnnspid::regnamespace::text,',') slist from pg_catalog.pg_publication_namespace pn group by pn.pnpubid +) +select p.oid,p.pubname,pt.fulltable,pg_get_userbyid(p.pubowner) AS owner, p.puballtables, p.pubinsert, p.pubupdate, p.pubdelete, obj_description(p.oid,'pg_publication') AS comment, +p.pubviaroot,pt.rowfilter,pt.cols,pn.slist from pg_publication p + LEFT JOIN rel pt ON pt.prpubid = p.oid + LEFT JOIN shs pn ON p.oid = pn.pnpubid +)"; + sql = sql + restriction + wxT("\n") + wxT(" ORDER BY p.pubname,pt.fulltable"); pgSet *publications = collection->GetDatabase()->ExecuteSet(sql); if (publications) { + wxString prevpubname; + wxString currpubname; + wxString listtables; while (!publications->Eof()) { + currpubname = publications->GetVal(wxT("pubname")); + if (currpubname != prevpubname) { + if (browser && publication && currpubname != prevpubname) browser->AppendObject(collection, publication); + prevpubname = currpubname; + if (publication && !listtables.IsEmpty() ) publication->iSetTablesStr(listtables); + listtables = ""; + publication = NULL; - publication = new pgPublication(publications->GetVal(wxT("pubname"))); - publication->iSetDatabase(collection->GetDatabase()); - publication->iSetOid(publications->GetOid(wxT("oid"))); - publication->iSetOwner(publications->GetVal(wxT("owner"))); - publication->iSetTablesStr(publications->GetVal(wxT("t"))); - publication->iSetIsAll(publications->GetBool(wxT("puballtables"))); - publication->iSetIsIns(publications->GetBool(wxT("pubinsert"))); - publication->iSetIsUpd(publications->GetBool(wxT("pubupdate"))); - publication->iSetIsDel(publications->GetBool(wxT("pubdelete"))); - //publication->iSetVersion(publications->GetVal(wxT("extversion"))); - publication->iSetComment(publications->GetVal(wxT("comment"))); - if (!pg13.IsEmpty()) publication->iSetIsViaRoot(publications->GetBool(wxT("pubviaroot"))); + } + if (publication == NULL) { + // first rows this publuc + publication = new pgPublication(currpubname); + //if (prevpubname.IsEmpty()) prevpubname = currpubname; + publication->iSetDatabase(collection->GetDatabase()); + publication->iSetOid(publications->GetOid(wxT("oid"))); + publication->iSetOwner(publications->GetVal(wxT("owner"))); + publication->iSetIsAll(publications->GetBool(wxT("puballtables"))); + publication->iSetIsIns(publications->GetBool(wxT("pubinsert"))); + publication->iSetIsUpd(publications->GetBool(wxT("pubupdate"))); + publication->iSetIsDel(publications->GetBool(wxT("pubdelete"))); + //publication->iSetVersion(publications->GetVal(wxT("extversion"))); + publication->iSetComment(publications->GetVal(wxT("comment"))); + publication->iSetIsViaRoot(publications->GetBool(wxT("pubviaroot"))); + + publication->iSetSchemasList(publications->GetVal(wxT("slist"))); + } + wxString attnames = publications->GetVal("cols"); + wxString rowfilter = publications->GetVal("rowfilter"); + wxString fulltable = publications->GetVal(wxT("fulltable")); + if (!fulltable.IsEmpty()) { + if (!listtables.IsEmpty()) listtables += ","; + listtables += fulltable; + publication->iAppendTable(fulltable, attnames); + publication->iAppendTableFilter(fulltable, rowfilter); + } + publications->MoveNext(); + if (publications->Eof()) { + prevpubname = ""; + publication->iSetTablesStr(listtables); + } if (browser) { - browser->AppendObject(collection, publication); - - publications->MoveNext(); + if (currpubname != prevpubname) + browser->AppendObject(collection, publication); } else - break; + if ( currpubname != prevpubname) break; } delete publications;