fix publication

Исправлен вывод SQL команд создания публикаций.
This commit is contained in:
lsv 2025-08-14 15:10:44 +05:00 committed by lsv
parent 825e80fb4f
commit 20ff51db29
2 changed files with 136 additions and 40 deletions

View file

@ -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<wxString, wxString> tablesdetail;
};
class pgPublicationCollection : public pgDatabaseObjCollection

View file

@ -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;