From c2c44c18f1fe9a0ad98df4e43883086b8d7d84c2 Mon Sep 17 00:00:00 2001 From: lsv Date: Mon, 16 Jun 2025 16:57:03 +0500 Subject: [PATCH] Using Pk to self-intersrc tables. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Для автоподстановки PK используется для соединения таблиц самих с собой. --- include/utils/TableColsMap.h | 3 ++- utils/TableColsMap.cpp | 42 ++++++++++++++++++++++++++---------- 2 files changed, 33 insertions(+), 12 deletions(-) diff --git a/include/utils/TableColsMap.h b/include/utils/TableColsMap.h index 7f1b95d..5eccf95 100644 --- a/include/utils/TableColsMap.h +++ b/include/utils/TableColsMap.h @@ -149,7 +149,8 @@ public: } #endif // DEBUG - + // Рекурсивное поисковое выражения для разбора внутреннего представления view + // Получаем ссылку на таблицу и колонку связанную со столбцом view. TableColsMap() { regaction.Compile( R"((?x) \{TARGETENTRY.*? diff --git a/utils/TableColsMap.cpp b/utils/TableColsMap.cpp index c024aa3..c253ed5 100644 --- a/utils/TableColsMap.cpp +++ b/utils/TableColsMap.cpp @@ -67,6 +67,12 @@ void TableColsMap::checkDBconn(pgConn* dbconn) { } //alias.clear(); } +/// +/// map заполняется проброшенными через вьюхи связанными таблицами и колонками +/// +/// +/// +/// void TableColsMap::BuildMapTableColumnsToSQLexp(Table *reltab, const wxString &alias, std::map &map) { if (reltab != NULL) { Table tmp = *reltab; @@ -110,7 +116,7 @@ wxString TableColsMap::AddTableList(pgConn* dbconn, const wxArrayString& tables, MapViewColToRelCol(flag); wxString rezstr; - if (CHKFLAG(flag, TableColsMap::Flag::SEQUENCE_LIST_TABLE)) { + if (CHKFLAG(flag, TableColsMap::Flag::SEQUENCE_LIST_TABLE) || true) { std::vector> all_maps; std::vector all_tables; for (int i = tables.GetCount()-1; i >=0; i--) { @@ -134,7 +140,9 @@ wxString TableColsMap::AddTableList(pgConn* dbconn, const wxArrayString& tables, std::unordered_set full; for (int i = 0; i < all_maps.size(); i++) { //Table* r = all_tables[i]; - for (int j = i + 1; j < all_maps.size(); j++) { + int position = i + 1; + if (CHKFLAG(flag, TableColsMap::Flag::ALL_LEFT_TO_RIGHT) && ((i+1)!= all_maps.size())) position = all_maps.size() - 1; // only right table + for (int j = position; j < all_maps.size(); j++) { wxString tmp= MapTableToTable(all_maps[i], all_maps[j],flag,leftexp); if (tmp.length() > 0) { if (tmp.Find('\t') == -1) { @@ -243,6 +251,13 @@ Table* TableColsMap::GetTablebyOID(const wxString oid) { } return NULL; } +/// +/// Рекурсивный спуск по view до таблицы и возврат таблицы и реальной колонки +/// +/// +/// +/// +/// Table* TableColsMap::GetRelTableForViewCol(const wxString oid, int ncolview, int& outrelcol) { Table *tt = GetTablebyOID(oid); if (tt != NULL) { @@ -285,7 +300,7 @@ void TableColsMap::MapViewColToRelCol(const TableColsMap::Flag flag) { if (rel != NULL) { cl.relTable = rel; } - t->SetCol(c, cl); + t->SetCol(c, cl); // save cl } } @@ -441,12 +456,12 @@ select cv.oid,cv.relname,cv.relnamespace::regnamespace, cv.relkind, a.attnum,a.a } else { // first table + // сохраним oid для получения FK onlyoid = onlyoid + ((onlyoid.length() > 0 ? "," : "") + wxString::Format("'%s'", oid)); t = new Table(); t->Set(kind, sc, oid, tn); oids.insert({ oid, t }); } - } t->AddColumn(ncol, colname, "", ""); } @@ -494,6 +509,12 @@ and rel.oid in ()" + onlyoid+") order by oid,foid"; //if (all_fk_table.size()>0) tablechild_fk[tf] = fk; } t = it->second; + bool flag_pk = false; + if (foid.IsEmpty()) { + flag_pk = true; + foid = oid; // PK = self FK + colflist = collist; + } wxArrayString ar = wxSplit(collist, ','); wxArrayString arf = wxSplit(colflist, ','); Table tmp = *t; @@ -505,9 +526,8 @@ and rel.oid in ()" + onlyoid+") order by oid,foid"; for (int k = 0; k < ar.GetCount(); k++) { int i = (int)StrToLong(ar[k]); fk.colsp.push_back(i); - if (foid.IsEmpty()) { + if (flag_pk) { tmp[i - 1].pk = true; - continue; } int fi = (int)StrToLong(arf[k]); fk.colsc.push_back(fi); @@ -522,8 +542,8 @@ and rel.oid in ()" + onlyoid+") order by oid,foid"; wxString key = foid +','+ arf[k]; if (auto it2 = forein_unknown_tab.find(key); it2 != forein_unknown_tab.end()) { - // . . - // . . + // Уже была эта таблица и колонка. Свяжем две наши таблицы через третью. + // можно связать наши таблицы через неизвестную .Увы только один уровень вложенности. tab_col_struct parent= it2->second; tf = parent.t; tmp[i - 1].linkTable = tf; @@ -531,7 +551,7 @@ and rel.oid in ()" + onlyoid+") order by oid,foid"; if (fk.child == NULL) fk.child = tf; } else { - // + // ссылка на не известную таблицу запомним её и Нашу таблицу tab_col_struct parent = { t,i }; forein_unknown_tab.insert({ key,parent }); } @@ -540,7 +560,7 @@ and rel.oid in ()" + onlyoid+") order by oid,foid"; if (fk.child != NULL) { tab_col_struct parent = { t,i }, child = {tf,fi}; all_fk_index.insert({ parent,child }); - all_fk_index.insert({ child,parent }); // a=b , b=a + all_fk_index.insert({ child,parent }); // учтем комутативность a=b , то b=a // uniq index uniq_fk_index.insert({ parent,child }); uniq_fk_index.insert({ child,parent }); @@ -561,7 +581,7 @@ and rel.oid in ()" + onlyoid+") order by oid,foid"; } if (CHKFLAG(flag, TableColsMap::Flag::USE_TRANSIT_FK)) { - // a=b b=c , a=c + // добавим транзитивности a=b b=c , то a=c std::set transit; int lvl = 0; for (auto e: all_fk_index) {