From 634345b38f7dce9fe68b8070369d4f4aff812696 Mon Sep 17 00:00:00 2001 From: eelke Date: Sat, 10 Nov 2018 13:36:36 +0100 Subject: [PATCH] In the column list show foreign key constraint --- pglab/ColumnTableModel.cpp | 10 ++++--- pglablib/PgConstraintContainer.cpp | 17 ++++++------ pglablib/PgConstraintContainer.h | 2 +- pglablib/SqlFormattingUtils.cpp | 43 ++++++++++++++++++++++++++++++ pglablib/SqlFormattingUtils.h | 5 ++++ 5 files changed, 65 insertions(+), 12 deletions(-) diff --git a/pglab/ColumnTableModel.cpp b/pglab/ColumnTableModel.cpp index 5a63f95..1ca82b0 100644 --- a/pglab/ColumnTableModel.cpp +++ b/pglab/ColumnTableModel.cpp @@ -8,6 +8,7 @@ #include "PgTypeContainer.h" #include "PgIndexContainer.h" #include "ScopeGuard.h" +#include "SqlFormattingUtils.h" #include void ColumnTableModel::setData(std::shared_ptr cat, const PgClass &table) @@ -208,9 +209,12 @@ QVariant ColumnTableModel::getData(const QModelIndex &index) const QString ColumnTableModel::getFKey(const PgAttribute &column) const { QString result; - const PgConstraint *c = m_catalog->constraints()->getFKeyForTableColumn(column.relid, column.num); - if (c) { - result = c->name; + auto&& list = m_catalog->constraints()->getFKeyForTableColumn(column.relid, column.num); + for (auto&& elem : list) { + if (elem.key[0] == column.num) { + //result = elem.name; + result = getForeignKeyConstraintReferencesShort(*m_catalog, elem); + } } return result; } diff --git a/pglablib/PgConstraintContainer.cpp b/pglablib/PgConstraintContainer.cpp index ae59f4a..45df803 100644 --- a/pglablib/PgConstraintContainer.cpp +++ b/pglablib/PgConstraintContainer.cpp @@ -52,16 +52,17 @@ PgConstraint PgConstraintContainer::loadElem(const Pgsql::Row &row) return v; } -const PgConstraint* PgConstraintContainer::getFKeyForTableColumn(Oid relid, int16_t attnum) const +std::vector PgConstraintContainer::getFKeyForTableColumn(Oid relid, int16_t attnum) const { - const PgConstraint *result = nullptr; + //const PgConstraint *result = nullptr; + std::vector result; // WHat do we want to find here? On ly single column constraints or all contstraints. -// auto res = std::find_if(m_container.begin(), m_container.end(), -// [relid, attnum] (const auto &c) { -// // the find on v.key may not look super efficient but remember it in general only has one or two elements. -// return relid == c.relid && -// (std::find(attnum.begin(), attnum.end(), v.key) != attnum.end()); -// }); + auto res = std::copy_if(m_container.begin(), m_container.end(), std::back_inserter(result), + [relid, attnum] (const auto &c) { + // the find on v.key may not look super efficient but remember it in general only has one or two elements. + return c.type == ConstraintType::ForeignKey && relid == c.relid && + (std::find(c.key.begin(), c.key.end(), attnum) != c.key.end()); + }); return result; } diff --git a/pglablib/PgConstraintContainer.h b/pglablib/PgConstraintContainer.h index 2b87350..ca8f752 100644 --- a/pglablib/PgConstraintContainer.h +++ b/pglablib/PgConstraintContainer.h @@ -13,7 +13,7 @@ public: virtual std::string getLoadQuery() const override; //std::vector getIndexesForTable(Oid table_oid) const; - const PgConstraint* getFKeyForTableColumn(Oid relid, int16_t attnum) const; + std::vector getFKeyForTableColumn(Oid relid, int16_t attnum) const; std::vector getConstraintsForRelation(Oid relid) const; std::optional getPrimaryForRelation(Oid relid) const; diff --git a/pglablib/SqlFormattingUtils.cpp b/pglablib/SqlFormattingUtils.cpp index 6e26c88..ab93ac8 100644 --- a/pglablib/SqlFormattingUtils.cpp +++ b/pglablib/SqlFormattingUtils.cpp @@ -126,7 +126,50 @@ QString getForeignKeyConstraintDefinition(const PgDatabaseCatalog &catalog, cons % " ON UPDATE " % ForeignKeyActionToString(constraint.fupdtype) % " ON DELETE " % ForeignKeyActionToString(constraint.fdeltype) % deferrable % validated % ";"; +} +QString getForeignKeyConstraintReferences(const PgDatabaseCatalog &catalog, const PgConstraint &constraint) +{ + PgClass fcls = catalog.classes()->getByKey(constraint.frelid); + QString deferrable; + QString validated; + if (!constraint.validated) + validated += " NOT VALID"; + if (constraint.deferrable) { + deferrable = QLatin1String(" DEFERRABLE INITIALLY ") % (constraint.deferred ? "DEFERRED" : "IMMEDIATE"); + } + + return "REFERENCES " + % genFQTableName(catalog, fcls) % " (" + % getColumnNameList(catalog, constraint.frelid, constraint.fkey) % ") MATCH " + % ForeignKeyMatchToString(constraint.fmatchtype) + % " ON UPDATE " % ForeignKeyActionToString(constraint.fupdtype) + % " ON DELETE " % ForeignKeyActionToString(constraint.fdeltype) + % deferrable % validated; + +} + + +QString getForeignKeyConstraintReferencesShort(const PgDatabaseCatalog &catalog, const PgConstraint &constraint) +{ + PgClass fcls = catalog.classes()->getByKey(constraint.frelid); + QString deferrable; + QString validated; + if (!constraint.validated) + validated += " NOT VALID"; + if (constraint.deferrable) { + deferrable = QLatin1String(" DEFERRABLE") % (constraint.deferred ? " INITIALLY DEFERRED" : ""); + } + QString on_update = constraint.fupdtype == ForeignKeyAction::NoAction ? QString() : " ON UPDATE " % ForeignKeyActionToString(constraint.fupdtype); + QString on_delete = constraint.fdeltype == ForeignKeyAction::NoAction ? QString() : " ON DELETE " % ForeignKeyActionToString(constraint.fdeltype); + QString match_type = constraint.fmatchtype == ForeignKeyMatch::Simple ? QString() : " MATCH " % ForeignKeyMatchToString(constraint.fmatchtype); + + return genFQTableName(catalog, fcls) % " (" + % getColumnNameList(catalog, constraint.frelid, constraint.fkey) % ")" + % match_type + % on_update + % on_delete + % deferrable % validated; } diff --git a/pglablib/SqlFormattingUtils.h b/pglablib/SqlFormattingUtils.h index d485dba..e3d1bec 100644 --- a/pglablib/SqlFormattingUtils.h +++ b/pglablib/SqlFormattingUtils.h @@ -16,6 +16,11 @@ QString getDropConstraintDefinition(const PgDatabaseCatalog &catalog, const PgCo QString getConstraintDefinition(const PgDatabaseCatalog &catalog, const PgConstraint &constraint); QString getIndexDefinition(const PgDatabaseCatalog &catalog, const PgIndex &index); QString getDropIndexDefinition(const PgDatabaseCatalog &catalog, const PgIndex &index); +/// Returns the foreignKey specific part of the constraint definition QString getForeignKeyConstraintDefinition(const PgDatabaseCatalog &catalog, const PgConstraint &constraint); +/// Returns the REFERENCES construct as used directly after a column in the create table statement +QString getForeignKeyConstraintReferences(const PgDatabaseCatalog &catalog, const PgConstraint &constraint); +/// Same as above but shortened as much as possible by leaving out defaults +QString getForeignKeyConstraintReferencesShort(const PgDatabaseCatalog &catalog, const PgConstraint &constraint); #endif // SQLFORMATTINGUTILS_H