diff --git a/pglab/ColumnTableModel.cpp b/pglab/ColumnTableModel.cpp index 1257291..33941a2 100644 --- a/pglab/ColumnTableModel.cpp +++ b/pglab/ColumnTableModel.cpp @@ -3,6 +3,7 @@ #include "PgAttribute.h" #include "PgAttributeContainer.h" #include "PgClassContainer.h" +#include "PgConstraintContainer.h" #include "PgType.h" #include "PgTypeContainer.h" #include "PgIndexContainer.h" @@ -69,6 +70,9 @@ QVariant ColumnTableModel::headerData(int section, Qt::Orientation orientation, case DefaultCol: c = tr("Default"); break; + case ForeignKeyCol: + c = tr("Refs"); + break; case CollationCol: c = tr("Collation"); break; @@ -104,6 +108,9 @@ QVariant ColumnTableModel::headerData(int section, Qt::Orientation orientation, case DefaultCol: v = tr("Default value for the columns"); break; + case ForeignKeyCol: + v = tr("Foreign key constraint for this column"); + break; // case CollationCol: // c = tr("Collation"); // break; @@ -178,6 +185,9 @@ QVariant ColumnTableModel::getData(const QModelIndex &index) const case DefaultCol: s = t.defaultValue; break; + case ForeignKeyCol: + s = getFKey(t); + break; case CollationCol: s = ""; //t.collation; break; @@ -188,6 +198,16 @@ QVariant ColumnTableModel::getData(const QModelIndex &index) const return v; } +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; + } + return result; +} + QVariant ColumnTableModel::data(const QModelIndex &index, int role) const { if (role == Qt::ForegroundRole && index.column() == TypeCol) { diff --git a/pglab/ColumnTableModel.h b/pglab/ColumnTableModel.h index cae0786..4cab6a0 100644 --- a/pglab/ColumnTableModel.h +++ b/pglab/ColumnTableModel.h @@ -17,6 +17,7 @@ public: TypeCol, NullCol, DefaultCol, + ForeignKeyCol, CollationCol, colCount }; @@ -44,6 +45,8 @@ protected: t_Columns m_columns; std::vector m_indexes; + QString getFKey(const PgAttribute &column) const; + }; #endif // COLUMNTABLEMODEL_H diff --git a/pglab/MainWindow.h b/pglab/MainWindow.h index 0d4c4d9..28fc99d 100644 --- a/pglab/MainWindow.h +++ b/pglab/MainWindow.h @@ -35,13 +35,13 @@ public: void setConfig(const ConnectionConfig &config); - OpenDatabase* getDatabase() { return m_database; } + std::shared_ptr getDatabase() { return m_database; } private: Ui::MainWindow *ui; ConnectionConfig m_config; - OpenDatabase *m_database = nullptr; + std::shared_ptr m_database; MasterController *m_masterController; diff --git a/pglab/OpenDatabase.cpp b/pglab/OpenDatabase.cpp index 30dc611..e878c91 100644 --- a/pglab/OpenDatabase.cpp +++ b/pglab/OpenDatabase.cpp @@ -3,22 +3,21 @@ #include "Pgsql_Connection.h" #include "TypeSelectionItemModel.h" -Expected OpenDatabase::createOpenDatabase(const ConnectionConfig &cfg) +Expected OpenDatabase::createOpenDatabase(const ConnectionConfig &cfg) { - OpenDatabase *odb = new OpenDatabase(cfg, nullptr); + OpenDatabaseSPtr odb(new OpenDatabase(cfg)); if (odb->Init()) { return odb; } //return Expected::fromException(std::out_of_range("Invalid row")); - return Expected::fromException( + return Expected::fromException( std::runtime_error("Failed to get database information")); } -OpenDatabase::OpenDatabase(const ConnectionConfig& cfg, QObject *parent) - : QObject(parent) - , m_config(cfg) +OpenDatabase::OpenDatabase(const ConnectionConfig& cfg) + : m_config(cfg) , m_catalogue(std::make_shared()) { } diff --git a/pglab/OpenDatabase.h b/pglab/OpenDatabase.h index d2b43db..7c8735b 100644 --- a/pglab/OpenDatabase.h +++ b/pglab/OpenDatabase.h @@ -1,7 +1,6 @@ #ifndef OPENDATABASE_H #define OPENDATABASE_H -#include #include "ConnectionConfig.h" #include "Expected.h" #include @@ -12,11 +11,13 @@ class TypeSelectionItemModel; /** Instances of this class represent a single database on which atleast one * window is opened. This class is used to track details about that database. */ -class OpenDatabase : public QObject -{ - Q_OBJECT +class OpenDatabase { public: - static Expected createOpenDatabase(const ConnectionConfig &cfg); + using OpenDatabaseSPtr = std::shared_ptr; + static Expected createOpenDatabase(const ConnectionConfig &cfg); + +// using on_createResult_callback = std::function>, qint64)>; +// void asyncCreateOpenDatabase(const ConnectionConfig &cfg, ); OpenDatabase(const OpenDatabase &) = delete; OpenDatabase& operator=(const OpenDatabase &) = delete; @@ -24,9 +25,6 @@ public: std::shared_ptr catalogue(); TypeSelectionItemModel* typeSelectionModel(); -signals: - -public slots: private: ConnectionConfig m_config; @@ -34,7 +32,7 @@ private: TypeSelectionItemModel *m_typeSelectionModel = nullptr; - OpenDatabase(const ConnectionConfig& cfg, QObject *parent = 0); + OpenDatabase(const ConnectionConfig& cfg); bool Init(); }; diff --git a/pglab/PgClass.h b/pglab/PgClass.h index 5c4c9e4..3dc4077 100644 --- a/pglab/PgClass.h +++ b/pglab/PgClass.h @@ -38,7 +38,7 @@ public: Oid am = InvalidOid; Oid filenode = InvalidOid; Oid tablespace = InvalidOid; - int pages_est = 0; + int32_t pages_est = 0; float tuples_est = 0.0f; Oid toastrelid = InvalidOid; bool isshared = false; diff --git a/pglab/PgConstraintContainer.cpp b/pglab/PgConstraintContainer.cpp index 275a93c..e753654 100644 --- a/pglab/PgConstraintContainer.cpp +++ b/pglab/PgConstraintContainer.cpp @@ -1,5 +1,6 @@ #include "PgConstraintContainer.h" #include "Pgsql_Col.h" +#include std::string PgConstraintContainer::getLoadQuery() const { @@ -30,6 +31,8 @@ FROM pg_constraint)__"; //} + + PgConstraint PgConstraintContainer::loadElem(const Pgsql::Row &row) { Pgsql::Col col(row); @@ -47,3 +50,16 @@ PgConstraint PgConstraintContainer::loadElem(const Pgsql::Row &row) col >> v.bin >> v.src >> v.definition; return v; } + +const PgConstraint* PgConstraintContainer::getFKeyForTableColumn(Oid relid, int16_t attnum) const +{ + const PgConstraint *result = nullptr; + // 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()); +// }); + return result; +} diff --git a/pglab/PgConstraintContainer.h b/pglab/PgConstraintContainer.h index 6dc8a00..89eb0cc 100644 --- a/pglab/PgConstraintContainer.h +++ b/pglab/PgConstraintContainer.h @@ -12,6 +12,7 @@ public: virtual std::string getLoadQuery() const override; //std::vector getIndexesForTable(Oid table_oid) const; + const PgConstraint* getFKeyForTableColumn(Oid relid, int16_t attnum) const; protected: virtual PgConstraint loadElem(const Pgsql::Row &row) override; }; diff --git a/pglab/PgDatabaseCatalog.cpp b/pglab/PgDatabaseCatalog.cpp index 10f0375..64a7cde 100644 --- a/pglab/PgDatabaseCatalog.cpp +++ b/pglab/PgDatabaseCatalog.cpp @@ -3,6 +3,7 @@ #include "PgAttributeContainer.h" #include "PgAuthIdContainer.h" #include "PgClassContainer.h" +#include "PgConstraintContainer.h" #include "PgDatabaseContainer.h" #include "PgIndexContainer.h" #include "PgNamespaceContainer.h" @@ -102,13 +103,14 @@ PgDatabaseCatalog::~PgDatabaseCatalog() void PgDatabaseCatalog::loadAll(Pgsql::Connection &conn) { loadInfo(conn); - loadAttributes(conn); - loadAuthIds(conn); - loadClasses(conn); - loadDatabases(conn); - loadIndexes(conn); - loadNamespaces(conn); - loadTypes(conn); + load2(m_attributes, conn); + load2(m_authIds, conn); + load2(m_classes, conn); + load2(m_constraints, conn); + load2(m_databases, conn); + load2(m_indexes, conn); + load2(m_namespaces, conn); + load2(m_types, conn); } void PgDatabaseCatalog::loadInfo(Pgsql::Connection &conn) @@ -138,63 +140,6 @@ void load(Pgsql::Connection &conn, IPgContainter &pg_cont) } -void PgDatabaseCatalog::loadAttributes(Pgsql::Connection &conn) -{ - if (!m_attributes) - m_attributes = std::make_shared(shared_from_this()); - - load(conn, *m_attributes); -} - -void PgDatabaseCatalog::loadAuthIds(Pgsql::Connection &conn) -{ - if (!m_authIds) - m_authIds = std::make_shared(shared_from_this()); - - load(conn, *m_authIds); -} - -void PgDatabaseCatalog::loadClasses(Pgsql::Connection &conn) -{ - if (!m_classes) - m_classes = std::make_shared(shared_from_this()); - - load(conn, *m_classes); -} - -void PgDatabaseCatalog::loadDatabases(Pgsql::Connection &conn) -{ - if (!m_databases) - m_databases = std::make_shared(shared_from_this()); - - load(conn, *m_databases); -} - -void PgDatabaseCatalog::loadIndexes(Pgsql::Connection &conn) -{ - if (!m_indexes) - m_indexes = std::make_shared(shared_from_this()); - - load(conn, *m_indexes); -} - -void PgDatabaseCatalog::loadNamespaces(Pgsql::Connection &conn) -{ - if (!m_namespaces) - m_namespaces = std::make_shared(shared_from_this()); - - load(conn, *m_namespaces); -} - -void PgDatabaseCatalog::loadTypes(Pgsql::Connection &conn) -{ - if (!m_types) - m_types = std::make_shared(shared_from_this()); - - load(conn, *m_types); -} - - const QString& PgDatabaseCatalog::serverVersionString() const { return m_serverVersionString; @@ -220,6 +165,11 @@ std::shared_ptr PgDatabaseCatalog::classes() const return m_classes; } +std::shared_ptr PgDatabaseCatalog::constraints() const +{ + return m_constraints; +} + std::shared_ptr PgDatabaseCatalog::databases() const { return m_databases; diff --git a/pglab/PgDatabaseCatalog.h b/pglab/PgDatabaseCatalog.h index 1c93cd0..4781371 100644 --- a/pglab/PgDatabaseCatalog.h +++ b/pglab/PgDatabaseCatalog.h @@ -15,6 +15,7 @@ namespace Pgsql { class PgAttributeContainer; class PgAuthIdContainer; class PgClassContainer; +class PgConstraintContainer; class PgDatabaseContainer; class PgIndexContainer; class PgNamespaceContainer; @@ -32,13 +33,14 @@ public: void loadAll(Pgsql::Connection &conn); void loadInfo(Pgsql::Connection &conn); - void loadAttributes(Pgsql::Connection &conn); - void loadAuthIds(Pgsql::Connection &conn); - void loadClasses(Pgsql::Connection &conn); - void loadDatabases(Pgsql::Connection &conn); - void loadIndexes(Pgsql::Connection &conn); - void loadNamespaces(Pgsql::Connection &conn); - void loadTypes(Pgsql::Connection &conn); + //void loadAttributes(Pgsql::Connection &conn); +// void loadAuthIds(Pgsql::Connection &conn); +// void loadClasses(Pgsql::Connection &conn); +// void loadConstraints(Pgsql::Connection &conn); +// void loadDatabases(Pgsql::Connection &conn); +// void loadIndexes(Pgsql::Connection &conn); +// void loadNamespaces(Pgsql::Connection &conn); +// void loadTypes(Pgsql::Connection &conn); const QString& serverVersionString() const; int serverVersion() const; @@ -46,6 +48,7 @@ public: std::shared_ptr attributes() const; std::shared_ptr authIds() const; std::shared_ptr classes() const; + std::shared_ptr constraints() const; std::shared_ptr databases() const; std::shared_ptr indexes() const; std::shared_ptr namespaces() const; @@ -57,10 +60,21 @@ private: std::shared_ptr m_attributes; std::shared_ptr m_authIds; std::shared_ptr m_classes; + std::shared_ptr m_constraints; std::shared_ptr m_databases; std::shared_ptr m_indexes; std::shared_ptr m_namespaces; std::shared_ptr m_types; + + template + void load2(std::shared_ptr &ptr, Pgsql::Connection &conn) + { + if (!ptr) + ptr = std::make_shared(shared_from_this()); + + load(conn, *ptr); + } + }; QString getRoleNameFromOid(const PgDatabaseCatalog &cat, Oid oid); diff --git a/pglab/QueryParamListController.cpp b/pglab/QueryParamListController.cpp index e3a0263..d4b0872 100644 --- a/pglab/QueryParamListController.cpp +++ b/pglab/QueryParamListController.cpp @@ -6,7 +6,7 @@ QueryParamListController::QueryParamListController(QTableView *tv, - OpenDatabase *opendb, QWidget *parent) + std::shared_ptr opendb, QWidget *parent) : QObject(parent) , paramTableView(tv) , m_openDatabase(opendb) diff --git a/pglab/QueryParamListController.h b/pglab/QueryParamListController.h index aee93d2..810a4d9 100644 --- a/pglab/QueryParamListController.h +++ b/pglab/QueryParamListController.h @@ -5,6 +5,7 @@ #include "ParamListModel.h" #include "ParamTypeDelegate.h" #include "Pgsql_Params.h" +#include class QTableView; class OpenDatabase; @@ -12,7 +13,7 @@ class OpenDatabase; class QueryParamListController : public QObject { Q_OBJECT public: - QueryParamListController(QTableView *tv, OpenDatabase *opendb, QWidget *parent); + QueryParamListController(QTableView *tv, std::shared_ptr opendb, QWidget *parent); Pgsql::Params params() const; bool empty() const; @@ -21,7 +22,7 @@ public slots: void on_removeParam(); private: QTableView *paramTableView; - OpenDatabase *m_openDatabase; + std::shared_ptr m_openDatabase; ParamListModel m_paramList; ParamTypeDelegate m_typeDelegate; }; diff --git a/pglab/QueryTab.cpp b/pglab/QueryTab.cpp index 0a87a6c..4df3363 100644 --- a/pglab/QueryTab.cpp +++ b/pglab/QueryTab.cpp @@ -41,7 +41,7 @@ QueryTab::QueryTab(MainWindow *win, QWidget *parent) : ui->queryEdit->setFont(font); highlighter = new SqlSyntaxHighlighter(ui->queryEdit->document()); - OpenDatabase* open_database = m_win->getDatabase(); + auto open_database = m_win->getDatabase(); if (open_database) { auto cat = open_database->catalogue(); highlighter->setTypes(*cat->types()); diff --git a/pglab/ServerWindow.h b/pglab/ServerWindow.h index 038315b..9d90e28 100644 --- a/pglab/ServerWindow.h +++ b/pglab/ServerWindow.h @@ -3,6 +3,7 @@ #include "ASyncWindow.h" #include "ConnectionConfig.h" +#include namespace Ui { class ServerWindow; @@ -25,7 +26,7 @@ private: MasterController *m_masterController = nullptr; ConnectionConfig m_config; - OpenDatabase *m_database = nullptr; + std::shared_ptr m_database; DatabasesTableModel *m_databasesModel = nullptr; RolesTableModel *m_rolesModel = nullptr; };