From 57217974f4ac11597694b3590e5f72360d64e35b Mon Sep 17 00:00:00 2001 From: eelke Date: Thu, 29 Nov 2018 20:21:36 +0100 Subject: [PATCH] New column page Shows SQL for columns ALTER TABLE ... [ADD|DROP] COLUMN combines a selection of multiple columns into a single alter table. Show collation in list of columns. (order of columns isn't what is should be but that should maybe be fixed by a generic column selection and ordering mechanism that knows what the default sort should be) --- pglab/ColumnPage.cpp | 83 +++++++++++++++++++++++++++++++ pglab/ColumnPage.h | 42 ++++++++++++++++ pglab/ColumnTableModel.cpp | 30 +++++++---- pglab/ColumnTableModel.h | 2 + pglab/TablesPage.cpp | 34 +++++-------- pglab/TablesPage.h | 9 ++-- pglab/TablesPage.ui | 12 +---- pglab/pglab.pro | 6 ++- pglablib/PgAttribute.cpp | 54 ++++++++++++++++++++ pglablib/PgAttribute.h | 9 +++- pglablib/PgAttributeContainer.cpp | 16 ++++-- pglablib/PgCollation.cpp | 2 + pglablib/PgCollation.h | 25 ++++++++++ pglablib/PgCollationContainer.cpp | 28 +++++++++++ pglablib/PgCollationContainer.h | 25 ++++++++++ pglablib/PgDatabaseCatalog.cpp | 9 ++++ pglablib/PgDatabaseCatalog.h | 4 ++ pglablib/SqlFormattingUtils.cpp | 2 +- pglablib/pglablib.pro | 8 ++- 19 files changed, 345 insertions(+), 55 deletions(-) create mode 100644 pglab/ColumnPage.cpp create mode 100644 pglab/ColumnPage.h create mode 100644 pglablib/PgCollation.cpp create mode 100644 pglablib/PgCollation.h create mode 100644 pglablib/PgCollationContainer.cpp create mode 100644 pglablib/PgCollationContainer.h diff --git a/pglab/ColumnPage.cpp b/pglab/ColumnPage.cpp new file mode 100644 index 0000000..336e3a9 --- /dev/null +++ b/pglab/ColumnPage.cpp @@ -0,0 +1,83 @@ +#include "ColumnPage.h" +#include "ResultTableModelUtil.h" +#include "UserConfiguration.h" +#include +#include "PgClass.h" +#include "SqlCodePreview.h" +#include "ColumnTableModel.h" +#include "CustomFilterSortModel.h" +#include "CustomDataRole.h" +#include "PgLabItemDelegate.h" +#include +#include +#include "SqlFormattingUtils.h" + +ColumnPage::ColumnPage(QWidget *parent) + : QSplitter(Qt::Vertical, parent) +{ + m_tableView = new QTableView(this); + m_definitionView = new SqlCodePreview(this); + addWidget(m_tableView); + addWidget(m_definitionView); + + SetTableViewDefault(m_tableView); + + m_columnModel = new ColumnTableModel(this); + m_sortFilterProxy = new CustomFilterSortModel(this); + m_sortFilterProxy->setSourceModel(m_columnModel); + m_tableView->setModel(m_sortFilterProxy); + m_tableView->setSortingEnabled(true); + m_tableView->setSelectionBehavior(QAbstractItemView::SelectRows); + + // With this delegate the coloring of the datatype column doesn't work.... +// auto item_delegate = new PgLabItemDelegate(this); +// m_tableView->setItemDelegate(item_delegate); + + //auto icon_delegate = new IconColumnDelegate(this); + + connect(m_tableView->selectionModel(), &QItemSelectionModel::selectionChanged, + this, &ColumnPage::tableView_selectionChanged); +} + +void ColumnPage::setData(std::shared_ptr cat, const std::optional &cls) +{ + m_catalog = cat; + m_definitionView->setCatalog(cat); + m_columnModel->setData(cat, cls); + m_Class = cls; +} + +//void ColumnPage::setFilter(const std::optional &cls) +//{ +// m_sortFilterProxy->setOidFilterTable(cls ? cls->oid() : InvalidOid, FirstHiddenValue); +//} + +void ColumnPage::tableView_selectionChanged(const QItemSelection &/*selected*/, const QItemSelection &/*deselected*/) +{ + auto&& indexes = m_tableView->selectionModel()->selectedIndexes(); + boost::container::flat_set rijen; + for (const auto &e : indexes) + rijen.insert(m_sortFilterProxy->mapToSource(e).row()); + + + QString drops; + QString addsql; + auto iter = rijen.begin(); + if (iter != rijen.end()) { + auto && col = m_columnModel->column(*iter); + drops = "ALTER TABLE " % m_Class->fullyQualifiedQuotedObjectName() % "\n DROP COLUMN " % quoteIdent(col.name); + addsql = "ALTER TABLE " % m_Class->fullyQualifiedQuotedObjectName() % "\n ADD COLUMN " % col.columnDefinition(*m_catalog); + for (++iter; iter != rijen.end(); ++iter) { + auto && col = m_columnModel->column(*iter); + drops += ",\n DROP COLUMN " % quoteIdent(col.name); + addsql += ",\n ADD COLUMN " % col.columnDefinition(*m_catalog); + } + drops += ";"; + addsql += ";"; + m_definitionView->setPlainText(drops % "\n\n" % addsql); + } + else { + m_definitionView->setPlainText(""); + } + +} diff --git a/pglab/ColumnPage.h b/pglab/ColumnPage.h new file mode 100644 index 0000000..67bead6 --- /dev/null +++ b/pglab/ColumnPage.h @@ -0,0 +1,42 @@ +#ifndef COLUMNPAGE_H +#define COLUMNPAGE_H + +#include "PgClass.h" +#include +#include +#include + + +class QTableView; +class SqlCodePreview; +class PgDatabaseCatalog; +class ColumnTableModel; +class CustomFilterSortModel; +class QItemSelection; +class QAbstractItemModel; + +class ColumnPage : public QSplitter +{ + Q_OBJECT +public: + explicit ColumnPage(QWidget *parent = nullptr); + + void setData(std::shared_ptr cat, const std::optional &cls); + //void setFilter(const std::optional &cls); +signals: + +public slots: + +private: + QTableView *m_tableView = nullptr; + SqlCodePreview *m_definitionView = nullptr; + ColumnTableModel *m_columnModel = nullptr; + CustomFilterSortModel *m_sortFilterProxy = nullptr; + std::shared_ptr m_catalog; + std::optional m_Class; + +private slots: + void tableView_selectionChanged(const QItemSelection &selected, const QItemSelection &deselected); +}; + +#endif // COLUMNPAGE_H diff --git a/pglab/ColumnTableModel.cpp b/pglab/ColumnTableModel.cpp index ff96c93..02cbe4f 100644 --- a/pglab/ColumnTableModel.cpp +++ b/pglab/ColumnTableModel.cpp @@ -4,6 +4,8 @@ #include "PgAttributeContainer.h" #include "PgClassContainer.h" #include "PgConstraintContainer.h" +#include "PgCollation.h" +#include "PgCollationContainer.h" #include "PgType.h" #include "PgTypeContainer.h" #include "PgIndexContainer.h" @@ -197,31 +199,34 @@ QVariant ColumnTableModel::getData(const QModelIndex &index) const } } else { - QString s; switch (col) { case AttnumCol: - s = QString::asprintf("%d", (int) t.num); - break; + //s = QString::asprintf("%d", (int) t.num); + //break; + return static_cast(t.num); case NameCol: - s = t.name; + v = t.name; break; case TypeCol: - s = getTypeDisplayString(*m_catalog, t.typid, t.typmod); + v = getTypeDisplayString(*m_catalog, t.typid, t.typmod); break; case NullCol: - s = QString::fromStdU16String(t.notnull ? u"" : u"N"); + v = QString::fromStdU16String(t.notnull ? u"" : u"N"); break; case DefaultCol: - s = t.defaultValue; + v = t.defaultValue; break; case ForeignKeyCol: - s = getFKey(t); + v = getFKey(t); break; case CollationCol: - s = ""; //t.collation; + if (t.collation != InvalidOid) { + auto&& col = m_catalog->collations()->getByKey(t.collation); + if (col) + v = col->objectName(); + } break; } - v = s; } return v; @@ -290,3 +295,8 @@ QVariant ColumnTableModel::data(const QModelIndex &index, int role) const } return BaseTableModel::data(index, role); } + +const PgAttribute& ColumnTableModel::column(int row) const +{ + return m_columns.at(static_cast(row)); +} diff --git a/pglab/ColumnTableModel.h b/pglab/ColumnTableModel.h index e14bd4b..72ec87d 100644 --- a/pglab/ColumnTableModel.h +++ b/pglab/ColumnTableModel.h @@ -2,6 +2,7 @@ #define COLUMNTABLEMODEL_H #include "BaseTableModel.h" +#include "PgAttribute.h" #include "PgClass.h" #include "PgIndex.h" #include @@ -36,6 +37,7 @@ public: int columnCount(const QModelIndex &parent) const override; QVariant data(const QModelIndex &index, int role) const override; + const PgAttribute& column(int row) const; protected: virtual Oid getType(int column) const override; virtual QVariant getData(const QModelIndex &index) const override; diff --git a/pglab/TablesPage.cpp b/pglab/TablesPage.cpp index 829cd0b..d50cd36 100644 --- a/pglab/TablesPage.cpp +++ b/pglab/TablesPage.cpp @@ -3,6 +3,7 @@ #include "PgAttribute.h" #include "PgDatabaseCatalog.h" +#include "ColumnPage.h" #include "ColumnTableModel.h" #include "ConstraintModel.h" #include "IconColumnDelegate.h" @@ -34,11 +35,6 @@ TablesPage::TablesPage(MainWindow *parent) ui->tableListTable->sortByColumn(0, Qt::AscendingOrder); ui->tableListTable->setSelectionBehavior(QAbstractItemView::SelectRows); - // Columns - SetTableViewDefault(ui->columnsTable); - m_columnsModel = new ColumnTableModel(this); - ui->columnsTable->setModel(m_columnsModel); - // Constraints SetTableViewDefault(ui->constraintsTable); m_constraintModel = new ConstraintModel(this); @@ -82,16 +78,21 @@ TablesPage::TablesPage(MainWindow *parent) &TablesPage::indexesTable_modelReset); // Non designer based code + // - Columns page + m_columnsPage = new ColumnPage(this); + ui->twDetails->insertTab(0, m_columnsPage, ""); + // - Properties page m_propertiesPage = new PropertiesPage(this); m_propertiesPage->setSourceModel(m_tablesModel); - m_propertiesTab = addDetailTab(m_propertiesPage); + ui->twDetails->addTab(m_propertiesPage, ""); + connect(ui->tableListTable->selectionModel(), &QItemSelectionModel::currentRowChanged, m_propertiesPage, &PropertiesPage::setActiveRow); // - Trigger page m_triggerPage = new TriggerPage(this); - m_triggerTab = addDetailTab(m_triggerPage); + ui->twDetails->addTab(m_triggerPage, ""); retranslateUi(false); } @@ -102,18 +103,9 @@ void TablesPage::retranslateUi(bool all) if (all) ui->retranslateUi(this); - ui->twDetails->setTabText(ui->twDetails->indexOf(m_propertiesTab), QApplication::translate("TablesPage", "Properties", nullptr)); - ui->twDetails->setTabText(ui->twDetails->indexOf(m_triggerTab), QApplication::translate("TablesPage", "Triggers", nullptr)); -} - - -QWidget* TablesPage::addDetailTab(QWidget *contents) -{ - auto tab = new QWidget(); - auto verticalLayout = new QVBoxLayout(tab); - verticalLayout->addWidget(contents); - ui->twDetails->addTab(tab, ""); - return tab; + ui->twDetails->setTabText(ui->twDetails->indexOf(m_columnsPage), QApplication::translate("TablesPage", "Columns", nullptr)); + ui->twDetails->setTabText(ui->twDetails->indexOf(m_propertiesPage), QApplication::translate("TablesPage", "Properties", nullptr)); + ui->twDetails->setTabText(ui->twDetails->indexOf(m_triggerPage), QApplication::translate("TablesPage", "Triggers", nullptr)); } TablesPage::~TablesPage() @@ -163,8 +155,8 @@ void TablesPage::tableListTable_layoutChanged(const QList void TablesPage::selectedTableChanged(const std::optional &table) { - m_columnsModel->setData(m_catalog, table); - ui->columnsTable->resizeColumnsToContents(); + m_columnsPage->setData(m_catalog, table); + //ui->columnsTable->resizeColumnsToContents(); m_constraintModel->setData(m_catalog, table); ui->constraintsTable->resizeColumnsToContents(); diff --git a/pglab/TablesPage.h b/pglab/TablesPage.h index ec35106..413de8d 100644 --- a/pglab/TablesPage.h +++ b/pglab/TablesPage.h @@ -11,6 +11,7 @@ class TablesPage; } class TablesTableModel; +class ColumnPage; class ColumnTableModel; class ConstraintModel; class PgDatabaseCatalog; @@ -33,9 +34,11 @@ public: private: Ui::TablesPage *ui; MainWindow *m_window; - QWidget *m_propertiesTab; + // QWidget *m_columnsTab; + ColumnPage *m_columnsPage; +// QWidget *m_propertiesTab; PropertiesPage *m_propertiesPage; - QWidget *m_triggerTab; +// QWidget *m_triggerTab; TriggerPage *m_triggerPage; std::shared_ptr m_catalog; TablesTableModel* m_tablesModel = nullptr; @@ -45,7 +48,7 @@ private: //NamespaceFilterWidget* m_namespaceFilterWidget; void retranslateUi(bool all = true); - QWidget* addDetailTab(QWidget *contents); +// QWidget* addDetailTab(QWidget *contents, bool infront = false); void selectedTableChanged(const std::optional &table); private slots: diff --git a/pglab/TablesPage.ui b/pglab/TablesPage.ui index b562cda..65e17f7 100644 --- a/pglab/TablesPage.ui +++ b/pglab/TablesPage.ui @@ -38,18 +38,8 @@ - 2 + 0 - - - Columns - - - - - - - Constraints diff --git a/pglab/pglab.pro b/pglab/pglab.pro index 28f23c7..b388352 100644 --- a/pglab/pglab.pro +++ b/pglab/pglab.pro @@ -79,7 +79,8 @@ PropertyProxyModel.cpp \ PropertiesPage.cpp \ PasswordPromptDialog.cpp \ ProcTableModel.cpp \ - FunctionsPage.cpp + FunctionsPage.cpp \ + ColumnPage.cpp HEADERS += \ QueryResultModel.h \ @@ -136,7 +137,8 @@ CustomDataRole.h \ PropertiesPage.h \ PasswordPromptDialog.h \ ProcTableModel.h \ - FunctionsPage.h + FunctionsPage.h \ + ColumnPage.h FORMS += mainwindow.ui \ ConnectionManagerWindow.ui \ diff --git a/pglablib/PgAttribute.cpp b/pglablib/PgAttribute.cpp index ff3549e..1c0fa4a 100644 --- a/pglablib/PgAttribute.cpp +++ b/pglablib/PgAttribute.cpp @@ -1,2 +1,56 @@ #include "PgAttribute.h" +#include "QStringBuilder" +#include "SqlFormattingUtils.h" +#include "PgClass.h" +#include "PgDatabaseCatalog.h" +#include "PgTypeContainer.h" +#include "PgCollation.h" +#include "PgCollationContainer.h" + +QString PgAttribute::columnDefinition(const PgDatabaseCatalog &cat) const +{ + // create: column_name data_type [ COLLATE collation ] [ column_constraint [ ... ] + // alter: column_name data_type [ COLLATE collation ] [ column_constraint [ ... ] + // constraints NULL/NOT NULL, DEFAULT, GENERATED other constraints will be ignored here a + auto&& type = cat.types()->getByKey(typid); + + QString sql = quoteIdent(name) % " " % type->name; + if (collation != InvalidOid) { + auto&& col = cat.collations()->getByKey(collation); + QString oname = col->objectName(); + if (oname != "default") + sql += " COLLATE " % quoteIdent(oname); + } + + if (notnull) + sql += " NOT NULL"; + + if (hasdef) + sql += " DEFAULT " % defaultValue; + + if (identity != ' ') { + sql += " GENERATED "; + if (identity == 'a') sql += "ALWAYS"; + else if (identity == 'd') sql += "BY DEFAULT"; + sql += " AS IDENTITY"; + } + // TODO sequence options might be missing + + return sql; +} + +QString PgAttribute::alterTableAddColumn(const PgDatabaseCatalog &cat, const PgClass &table) const +{ + QString sql = "ALTER TABLE " % table.fullyQualifiedQuotedObjectName() + % " ADD COLUMN " % columnDefinition(cat) % ";"; + return sql; +} + +QString PgAttribute::alterTableDropColumn(const PgDatabaseCatalog &cat, const PgClass &table) const +{ + QString sql = "ALTER TABLE " % table.fullyQualifiedQuotedObjectName() + % " DROP COLUMN " % quoteIdent(name) % ";"; + return sql; +} + diff --git a/pglablib/PgAttribute.h b/pglablib/PgAttribute.h index d03b81d..2707bdc 100644 --- a/pglablib/PgAttribute.h +++ b/pglablib/PgAttribute.h @@ -6,11 +6,13 @@ #include #include +class PgClass; +class PgDatabaseCatalog; + class PgAttribute { public: using Key = std::tuple; - // Oid oid = InvalidOid; Oid relid = InvalidOid; QString name; Oid typid = InvalidOid; @@ -20,6 +22,7 @@ public: int32_t typmod = -1; bool notnull = false; bool hasdef = false; + char identity = ' '; bool isdropped = false; Oid collation = InvalidOid; QString acl; @@ -33,6 +36,10 @@ public: bool operator<(Key _k) const { return relid < std::get<0>(_k) || (relid == std::get<0>(_k) && num < std::get<1>(_k)); } bool operator<(const PgAttribute &rhs) const { return relid < rhs.relid || (relid == rhs.relid && num < rhs.num); } + /// Return the part of the SQL create statement that can be reused for both the CREATE TABLE and ALTER TABLE ADD COLUMN + QString columnDefinition(const PgDatabaseCatalog &cat) const; + QString alterTableAddColumn(const PgDatabaseCatalog &cat, const PgClass &table) const; + QString alterTableDropColumn(const PgDatabaseCatalog &cat, const PgClass &table) const; }; #endif // PGATTRIBUTE_H diff --git a/pglablib/PgAttributeContainer.cpp b/pglablib/PgAttributeContainer.cpp index 42e173c..ef7bca3 100644 --- a/pglablib/PgAttributeContainer.cpp +++ b/pglablib/PgAttributeContainer.cpp @@ -1,5 +1,6 @@ #include "PgAttributeContainer.h" #include "Pgsql_Col.h" +#include "PgDatabaseCatalog.h" //SELECT attname, pg_get_expr(adbin, adrelid) AS def_value //FROM pg_attribute @@ -8,12 +9,16 @@ std::string PgAttributeContainer::getLoadQuery() const { - return R"__( + std::string q = R"__( SELECT attrelid, attname, atttypid, attstattarget, attnum, attndims, atttypmod, attnotnull, atthasdef, attisdropped, - attcollation, attacl, attoptions, pg_get_expr(adbin, adrelid) AS def_value -FROM pg_catalog.pg_attribute - LEFT JOIN pg_attrdef ON attrelid=adrelid AND attnum=adnum)__"; + attcollation, attacl, attoptions, pg_get_expr(adbin, adrelid) AS def_value)__"; + if (m_catalog.serverVersion() >= 100000) + q += ", attidentity"; + q += + "\n FROM pg_catalog.pg_attribute \n" + " LEFT JOIN pg_attrdef ON attrelid=adrelid AND attnum=adnum"; + return q; } PgAttribute PgAttributeContainer::loadElem(const Pgsql::Row &row) @@ -23,6 +28,9 @@ PgAttribute PgAttributeContainer::loadElem(const Pgsql::Row &row) col >> v.relid >> v.name >> v.typid >> v.stattarget >> v.num >> v.ndims >> v.typmod >> v.notnull >> v.hasdef >> v.isdropped >> v.collation >> v.acl >> v.options >> v.defaultValue; + if (m_catalog.serverVersion() >= 100000) + col >> v.identity; + return v; } diff --git a/pglablib/PgCollation.cpp b/pglablib/PgCollation.cpp new file mode 100644 index 0000000..447437c --- /dev/null +++ b/pglablib/PgCollation.cpp @@ -0,0 +1,2 @@ +#include "PgCollation.h" + diff --git a/pglablib/PgCollation.h b/pglablib/PgCollation.h new file mode 100644 index 0000000..bb4a1b2 --- /dev/null +++ b/pglablib/PgCollation.h @@ -0,0 +1,25 @@ +#ifndef PGCOLLATION_H +#define PGCOLLATION_H + +#include "PgNamespaceObject.h" +#include "PgOwnedObject.h" +#include +#include +#include "Pgsql_Value.h" +//#include + +class PgCollation: public PgNamespaceObject, public PgOwnedObject { +public: + using PgNamespaceObject::PgNamespaceObject; + +// Oid oid; // oid +// QString collname; // name +// Oid collnamespace; // oid +// Oid collowner; // oid + int32_t collencoding; // integer + QString collcollate; // name + QString collctype; // name + +}; + +#endif // PGCOLLATION_H diff --git a/pglablib/PgCollationContainer.cpp b/pglablib/PgCollationContainer.cpp new file mode 100644 index 0000000..d93ce67 --- /dev/null +++ b/pglablib/PgCollationContainer.cpp @@ -0,0 +1,28 @@ +#include "PgCollationContainer.h" +#include "Pgsql_Connection.h" +#include "Pgsql_Col.h" +#include "PgDatabaseCatalog.h" +#include + +std::string PgCollationContainer::getLoadQuery() const +{ + return "SELECT oid, collname, collnamespace, collowner, collencoding, \n" + " collcollate, collctype \n" + "FROM pg_collation"; +} + +PgCollation PgCollationContainer::loadElem(const Pgsql::Row &row) +{ + Pgsql::Col col(row); + Oid class_oid = col.nextValue(); + QString name = col.nextValue(); + Oid ns_oid = col.nextValue(); + + PgCollation v(m_catalog, class_oid, name, ns_oid); + Oid owner ; + + col >> owner >> v.collencoding >> v.collcollate >> v.collctype; + v.setOwnerOid(m_catalog, owner); + + return v; +} diff --git a/pglablib/PgCollationContainer.h b/pglablib/PgCollationContainer.h new file mode 100644 index 0000000..ae398f2 --- /dev/null +++ b/pglablib/PgCollationContainer.h @@ -0,0 +1,25 @@ +#ifndef PGCOLLATIONCONTAINER_H +#define PGCOLLATIONCONTAINER_H + +#include "PgContainer.h" +#include "PgCollation.h" + +namespace Pgsql { + + class Result; + +} + + +class PgCollationContainer: public PgContainer { +public: + using PgContainer::PgContainer; + + virtual std::string getLoadQuery() const override; +protected: + PgCollation loadElem(const Pgsql::Row &row) override; +private: +}; + + +#endif // PGCOLLATIONCONTAINER_H diff --git a/pglablib/PgDatabaseCatalog.cpp b/pglablib/PgDatabaseCatalog.cpp index d51374d..18139a3 100644 --- a/pglablib/PgDatabaseCatalog.cpp +++ b/pglablib/PgDatabaseCatalog.cpp @@ -13,6 +13,7 @@ #include "PgTriggerContainer.h" #include "PgTypeContainer.h" #include "PgProcContainer.h" +#include "PgCollationContainer.h" #include "Pgsql_Connection.h" #include "Pgsql_oids.h" @@ -160,6 +161,9 @@ void PgDatabaseCatalog::loadAll(Pgsql::Connection &conn, // Load database objects load2(m_namespaces, conn); + if (progress_callback && !progress_callback(++n, count)) + return; + load2(m_collations, conn); if (progress_callback && !progress_callback(++n, count)) return; load2(m_classes, conn); // needs namespaces @@ -294,3 +298,8 @@ std::shared_ptr PgDatabaseCatalog::procs() const { return m_procs; } + +std::shared_ptr PgDatabaseCatalog::collations() const +{ + return m_collations; +} diff --git a/pglablib/PgDatabaseCatalog.h b/pglablib/PgDatabaseCatalog.h index 7d796e3..fce4ea7 100644 --- a/pglablib/PgDatabaseCatalog.h +++ b/pglablib/PgDatabaseCatalog.h @@ -27,6 +27,8 @@ class PgTablespaceContainer; class PgTriggerContainer; class PgTypeContainer; class PgProcContainer; +class PgCollationContainer; + class PgDatabaseCatalog: public QObject, public std::enable_shared_from_this { Q_OBJECT @@ -57,6 +59,7 @@ public: std::shared_ptr triggers() const; std::shared_ptr types() const; std::shared_ptr procs() const; + std::shared_ptr collations() const; enum RefreshFlag { Attributes = 1, @@ -94,6 +97,7 @@ private: std::shared_ptr m_triggers; std::shared_ptr m_types; std::shared_ptr m_procs; + std::shared_ptr m_collations; template void load2(std::shared_ptr &ptr, Pgsql::Connection &conn) diff --git a/pglablib/SqlFormattingUtils.cpp b/pglablib/SqlFormattingUtils.cpp index 6757785..20b801e 100644 --- a/pglablib/SqlFormattingUtils.cpp +++ b/pglablib/SqlFormattingUtils.cpp @@ -195,7 +195,7 @@ bool identNeedsQuotes(QString ident) if (ident[0].isDigit()) return true; for (auto c : ident) - if ((c < 'a' || c > 'z') && c != '_') + if ((c < 'a' || c > 'z') && c != '_' && (c < '0' || c > '9')) return true; auto kw = getPgsqlKeyword(ident); diff --git a/pglablib/pglablib.pro b/pglablib/pglablib.pro index 7926bb4..da41771 100644 --- a/pglablib/pglablib.pro +++ b/pglablib/pglablib.pro @@ -71,7 +71,9 @@ codebuilder/StructureTemplate.cpp \ PgDatabaseObject.cpp \ PgServerObject.cpp \ PgOwnedObject.cpp \ - PgNamespaceObject.cpp + PgNamespaceObject.cpp \ + PgCollation.cpp \ + PgCollationContainer.cpp HEADERS += \ Pglablib.h \ @@ -125,7 +127,9 @@ codebuilder/StructureTemplate.h \ PgDatabaseObject.h \ PgServerObject.h \ PgOwnedObject.h \ - PgNamespaceObject.h + PgNamespaceObject.h \ + PgCollation.h \ + PgCollationContainer.h unix { target.path = /usr/lib