From 50cb21b6f9beab617a4f441c3c8fe5829e9a358c Mon Sep 17 00:00:00 2001 From: eelke Date: Sat, 25 Aug 2018 18:11:12 +0200 Subject: [PATCH] The list of indexes on a table now also shows the access method (ie btree) --- pglab/CrudModel.h | 25 +++++++++++++++++++++++++ pglab/IndexModel.cpp | 9 ++++++++- pglab/IndexModel.h | 13 +++++++++++++ pglab/QueryTab.cpp | 18 +++++++++--------- pglablib/PgAm.cpp | 6 ++++++ pglablib/PgAm.h | 19 +++++++++++++++++++ pglablib/PgAmContainer.cpp | 17 +++++++++++++++++ pglablib/PgAmContainer.h | 18 ++++++++++++++++++ pglablib/PgContainer.h | 2 +- pglablib/PgDatabaseCatalog.cpp | 28 +++++++++++++++++++--------- pglablib/PgDatabaseCatalog.h | 3 +++ pglablib/PgIndex.cpp | 19 +++++++++++++++++++ pglablib/PgIndex.h | 10 +++++++--- pglablib/PgIndexContainer.cpp | 2 +- pglablib/PgObject.cpp | 6 ++++++ pglablib/PgObject.h | 19 +++++++++++++++++++ pglablib/pglablib.pro | 10 ++++++++-- 17 files changed, 198 insertions(+), 26 deletions(-) create mode 100644 pglablib/PgAm.cpp create mode 100644 pglablib/PgAm.h create mode 100644 pglablib/PgAmContainer.cpp create mode 100644 pglablib/PgAmContainer.h create mode 100644 pglablib/PgObject.cpp create mode 100644 pglablib/PgObject.h diff --git a/pglab/CrudModel.h b/pglab/CrudModel.h index 8851a16..277b49d 100644 --- a/pglab/CrudModel.h +++ b/pglab/CrudModel.h @@ -84,6 +84,31 @@ private: using PKeyValues = std::vector; + class ColumnSort { + public: + enum Direction { Ascending, Descending }; + enum NullSorting { + Default, ///< Behaves like NULL values are larger then non NULL values ASC NULLS LAST or DESC NULLS FIRST + First, + Last }; + + std::string columnName; + Direction direction = Direction::Ascending; + NullSorting nulls = NullSorting::Default; + + std::string toSql() const + { + std::string res = columnName; + if (direction == Direction::Descending) + res += " DESC"; + if (nulls == NullSorting::First) + res += " NULLS FIRST"; + else if (nulls == NullSorting::Last) + res += " NULLS LAST"; + } + + }; + // using RowData = std::vector; // using RowDataPtr = std::unique_ptr; diff --git a/pglab/IndexModel.cpp b/pglab/IndexModel.cpp index f61b9dc..93adc16 100644 --- a/pglab/IndexModel.cpp +++ b/pglab/IndexModel.cpp @@ -17,7 +17,7 @@ void IndexModel::setData(std::shared_ptr cat, const PgC int IndexModel::rowCount(const QModelIndex &/*parent*/) const { - return m_indexes.size(); + return (int)m_indexes.size(); } int IndexModel::columnCount(const QModelIndex &/*parent*/) const @@ -43,6 +43,9 @@ QVariant IndexModel::headerData(int section, Qt::Orientation orientation, int ro case NameCol: c = tr("Name"); break; + case AmCol: + c = tr("AM"); + break; case ColumnsCol: c = tr("On"); break; @@ -75,6 +78,10 @@ QVariant IndexModel::getData(const QModelIndex &index) const v = getIndexDisplayString(*m_catalog, dat.indexrelid); break; + case AmCol: + v = dat.getAm(); + break; + case ColumnsCol: break; diff --git a/pglab/IndexModel.h b/pglab/IndexModel.h index ec7b4e3..64cbe2c 100644 --- a/pglab/IndexModel.h +++ b/pglab/IndexModel.h @@ -18,10 +18,23 @@ public: enum e_Columns : int { TypeCol, /// primary/unique/normal NameCol, /// + AmCol, ///< Access Method ColumnsCol, /// ConditionCol, colCount }; +// oid +// tablespace +// operator class +// unique +// primary +// clustered +// valid +// constraint +// system index +// fill factor +// comment + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; void setData(std::shared_ptr cat, const PgClass &table); diff --git a/pglab/QueryTab.cpp b/pglab/QueryTab.cpp index 0486ec2..f55fb35 100644 --- a/pglab/QueryTab.cpp +++ b/pglab/QueryTab.cpp @@ -542,18 +542,18 @@ void QueryTab::markError(const Pgsql::ErrorDetails &details) if (details.state == "42703") { std::size_t pos = details.messagePrimary.find('"'); if (pos != std::string::npos) { - int pos2 = details.messagePrimary.find('"', pos+1); + std::size_t pos2 = details.messagePrimary.find('"', pos+1); if (pos2 != std::string::npos) { - length = pos2 - pos; + length = static_cast(pos2 - pos); } } } else if (details.state == "42P01") { std::size_t pos = details.messagePrimary.find('"'); if (pos != std::string::npos) { - int pos2 = details.messagePrimary.find('"', pos+1); + std::size_t pos2 = details.messagePrimary.find('"', pos+1); if (pos2 != std::string::npos) { - length = pos2 - pos; + length = static_cast(pos2 - pos); } } } @@ -623,11 +623,11 @@ std::vector QueryTab::getToolbarActions() action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_S)); connect(action, &QAction::triggered, this, &QueryTab::save); actions.push_back(action); - // Save as - action = new QAction(QIcon(":/icons/script_go.png"), tr("Save SQL as"), this); - //action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_S)); - connect(action, &QAction::triggered, this, &QueryTab::saveAs); - actions.push_back(action); + // Save as (menu only) +// action = new QAction(QIcon(":/icons/script_save.png"), tr("Save SQL as"), this); +// //action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_S)); +// connect(action, &QAction::triggered, this, &QueryTab::saveAs); +// actions.push_back(action); // Save copy as // Copy // Copy as C-string diff --git a/pglablib/PgAm.cpp b/pglablib/PgAm.cpp new file mode 100644 index 0000000..185600e --- /dev/null +++ b/pglablib/PgAm.cpp @@ -0,0 +1,6 @@ +#include "PgAm.h" + +PgAm::PgAm() +{ + +} diff --git a/pglablib/PgAm.h b/pglablib/PgAm.h new file mode 100644 index 0000000..1eadad9 --- /dev/null +++ b/pglablib/PgAm.h @@ -0,0 +1,19 @@ +#ifndef PGAM_H +#define PGAM_H + +#include "Pgsql_declare.h" +#include + +class PgAm { +public: + Oid oid; + QString name; + + PgAm(); + + bool operator==(Oid rhs) const { return oid == rhs; } + bool operator<(Oid rhs) const { return oid < rhs; } + bool operator<(const PgAm &rhs) const { return oid < rhs.oid; } +}; + +#endif // PGAM_H diff --git a/pglablib/PgAmContainer.cpp b/pglablib/PgAmContainer.cpp new file mode 100644 index 0000000..4eb75a5 --- /dev/null +++ b/pglablib/PgAmContainer.cpp @@ -0,0 +1,17 @@ +#include "PgAmContainer.h" +#include "Pgsql_Col.h" + +std::string PgAmContainer::getLoadQuery() const +{ + std::string q = "SELECT oid, amname FROM pg_am"; + return q; +} + +PgAm PgAmContainer::loadElem(const Pgsql::Row &row) +{ + Pgsql::Col col(row); + PgAm v; + col >> v.oid >> v.name; + + return v; +} diff --git a/pglablib/PgAmContainer.h b/pglablib/PgAmContainer.h new file mode 100644 index 0000000..7235724 --- /dev/null +++ b/pglablib/PgAmContainer.h @@ -0,0 +1,18 @@ +#ifndef PGAMCONTAINER_H +#define PGAMCONTAINER_H + +#include "PgContainer.h" +#include "PgAm.h" +#include "Pgsql_declare.h" +#include + +class PgAmContainer : public PgContainer { +public: + using PgContainer::PgContainer; + + virtual std::string getLoadQuery() const override; +protected: + virtual PgAm loadElem(const Pgsql::Row &row) override; +}; + +#endif // PGAMCONTAINER_H diff --git a/pglablib/PgContainer.h b/pglablib/PgContainer.h index b234296..5c0d6a7 100644 --- a/pglablib/PgContainer.h +++ b/pglablib/PgContainer.h @@ -95,7 +95,7 @@ protected: * * When overriding this function there is no need to override load. */ - virtual T loadElem(const Pgsql::Row &) { return T(); } + virtual T loadElem(const Pgsql::Row &) { return m_invalidInstance; } private: T m_invalidInstance; diff --git a/pglablib/PgDatabaseCatalog.cpp b/pglablib/PgDatabaseCatalog.cpp index 53e0d5d..e2eff8b 100644 --- a/pglablib/PgDatabaseCatalog.cpp +++ b/pglablib/PgDatabaseCatalog.cpp @@ -1,6 +1,7 @@ #include "PgDatabaseCatalog.h" #include "ASyncDBConnection.h" +#include "PgAmContainer.h" #include "PgAttributeContainer.h" #include "PgAuthIdContainer.h" #include "PgClassContainer.h" @@ -128,32 +129,36 @@ void PgDatabaseCatalog::loadAll(Pgsql::Connection &conn, std::function progress_callback) { loadInfo(conn); + const int count = 10; int n = 0; - if (progress_callback && !progress_callback(++n, 9)) + if (progress_callback && !progress_callback(++n, count)) return; load2(m_namespaces, conn); - if (progress_callback && !progress_callback(++n, 9)) + if (progress_callback && !progress_callback(++n, count)) return; load2(m_classes, conn); // needs namespaces - if (progress_callback && !progress_callback(++n, 9)) + if (progress_callback && !progress_callback(++n, count)) return; load2(m_attributes, conn); - if (progress_callback && !progress_callback(++n, 9)) + if (progress_callback && !progress_callback(++n, count)) return; load2(m_authIds, conn); - if (progress_callback && !progress_callback(++n, 9)) + if (progress_callback && !progress_callback(++n, count)) return; load2(m_constraints, conn); - if (progress_callback && !progress_callback(++n, 9)) + if (progress_callback && !progress_callback(++n, count)) return; load2(m_databases, conn); - if (progress_callback && !progress_callback(++n, 9)) + if (progress_callback && !progress_callback(++n, count)) return; load2(m_indexes, conn); - if (progress_callback && !progress_callback(++n, 9)) + if (progress_callback && !progress_callback(++n, count)) + return; + load2(m_ams, conn); + if (progress_callback && !progress_callback(++n, count)) return; load2(m_types, conn); - progress_callback && progress_callback(++n, 9); + progress_callback && progress_callback(++n, count); } void PgDatabaseCatalog::loadInfo(Pgsql::Connection &conn) @@ -230,6 +235,11 @@ std::shared_ptr PgDatabaseCatalog::indexes() const return m_indexes; } +std::shared_ptr PgDatabaseCatalog::ams() const +{ + return m_ams; +} + std::shared_ptr PgDatabaseCatalog::namespaces() const { return m_namespaces; diff --git a/pglablib/PgDatabaseCatalog.h b/pglablib/PgDatabaseCatalog.h index 3818bb3..1389322 100644 --- a/pglablib/PgDatabaseCatalog.h +++ b/pglablib/PgDatabaseCatalog.h @@ -20,6 +20,7 @@ class PgConstraintContainer; class PgDatabaseContainer; class PgIndexContainer; class PgNamespaceContainer; +class PgAmContainer; class PgTypeContainer; class PgDatabaseCatalog: public std::enable_shared_from_this { @@ -43,6 +44,7 @@ public: std::shared_ptr constraints() const; std::shared_ptr databases() const; std::shared_ptr indexes() const; + std::shared_ptr ams() const; std::shared_ptr namespaces() const; std::shared_ptr types() const; private: @@ -55,6 +57,7 @@ private: std::shared_ptr m_constraints; std::shared_ptr m_databases; std::shared_ptr m_indexes; + std::shared_ptr m_ams; std::shared_ptr m_namespaces; std::shared_ptr m_types; diff --git a/pglablib/PgIndex.cpp b/pglablib/PgIndex.cpp index 1b28fb0..11d5d7b 100644 --- a/pglablib/PgIndex.cpp +++ b/pglablib/PgIndex.cpp @@ -1,3 +1,22 @@ #include "PgIndex.h" +#include "PgDatabaseCatalog.h" +#include "PgClassContainer.h" +#include "PgAmContainer.h" PgIndex::PgIndex() = default; + +PgIndex::PgIndex(std::weak_ptr cat) + : PgObject(cat) +{} + +QString PgIndex::getAm() const +{ + auto cat = catalog.lock(); + QString result; + if (cat) { + auto idxcls = cat->classes()->getByKey(indexrelid); + auto am = cat->ams()->getByKey(idxcls.am); + result = am.name; + } + return result; +} diff --git a/pglablib/PgIndex.h b/pglablib/PgIndex.h index f17f675..b7edf53 100644 --- a/pglablib/PgIndex.h +++ b/pglablib/PgIndex.h @@ -1,15 +1,16 @@ #ifndef PGINDEX_H #define PGINDEX_H +#include "PgObject.h" #include "Pgsql_declare.h" #include #include -class PgIndex { +class PgIndex : public PgObject { public: - Oid indexrelid = InvalidOid; - Oid relid = InvalidOid; + Oid indexrelid = InvalidOid; // oid of pg_class for this index + Oid relid = InvalidOid; // oid of table (pg_class) where this is an index on int16_t natts = 0; bool isunique = false; bool isprimary = false; @@ -30,6 +31,9 @@ public: QString definition; PgIndex(); + explicit PgIndex(std::weak_ptr cat); + + QString getAm() const; bool operator==(Oid _oid) const { return indexrelid == _oid; } //bool operator==(const QString &n) const { return name == n; } diff --git a/pglablib/PgIndexContainer.cpp b/pglablib/PgIndexContainer.cpp index 3f98f37..52c5075 100644 --- a/pglablib/PgIndexContainer.cpp +++ b/pglablib/PgIndexContainer.cpp @@ -22,7 +22,7 @@ SELECT indexrelid, indrelid, indnatts, indisunique, indisprimary, PgIndex PgIndexContainer::loadElem(const Pgsql::Row &row) { Pgsql::Col col(row); - PgIndex v; + PgIndex v(m_catalogue); col >> v.indexrelid >> v.relid >> v.natts >> v.isunique >> v.isprimary >> v.isexclusion >> v.immediate >> v.isclustered >> v.isvalid >> v.checkxmin >> v.isready >> v.islive; diff --git a/pglablib/PgObject.cpp b/pglablib/PgObject.cpp new file mode 100644 index 0000000..6aa845b --- /dev/null +++ b/pglablib/PgObject.cpp @@ -0,0 +1,6 @@ +#include "PgObject.h" + +PgObject::PgObject() +{ + +} diff --git a/pglablib/PgObject.h b/pglablib/PgObject.h new file mode 100644 index 0000000..cb76931 --- /dev/null +++ b/pglablib/PgObject.h @@ -0,0 +1,19 @@ +#ifndef PGOBJECT_H +#define PGOBJECT_H + +#include + +class PgDatabaseCatalog; + +class PgObject +{ +public: + PgObject(); + explicit PgObject(std::weak_ptr cat) + : catalog(cat) + {} +protected: + std::weak_ptr catalog; +}; + +#endif // PGOBJECT_H diff --git a/pglablib/pglablib.pro b/pglablib/pglablib.pro index 093c0f8..3e33c70 100644 --- a/pglablib/pglablib.pro +++ b/pglablib/pglablib.pro @@ -52,7 +52,10 @@ SOURCES += \ util.cpp \ SqlFormattingUtils.cpp \ PgKeywordList.cpp \ - QueryGenerator.cpp + QueryGenerator.cpp \ + PgAm.cpp \ + PgAmContainer.cpp \ + PgObject.cpp HEADERS += \ Pglablib.h \ @@ -82,7 +85,10 @@ HEADERS += \ SqlFormattingUtils.h \ PgCatalogTypes.h \ PgKeywordList.h \ - QueryGenerator.h + QueryGenerator.h \ + PgAm.h \ + PgAmContainer.h \ + PgObject.h unix { target.path = /usr/lib