Show SQL for database

Also improvements to the SQL for tables and views.
This commit is contained in:
eelke 2022-01-20 20:13:56 +01:00
parent b5a706a2a2
commit 3158a4364b
12 changed files with 172 additions and 58 deletions

View file

@ -142,10 +142,9 @@ QVariant DatabasesTableModel::getData(const QModelIndex &index) const
v = db.objectName();
break;
case DbaCol:
v = getRoleDisplayString(*m_catalog, db.dba);
v = db.ownerName();
break;
case EncodingCol:
// todo lookup encoding name
v = db.encodingString;
break;
case CollateCol:
@ -164,7 +163,6 @@ QVariant DatabasesTableModel::getData(const QModelIndex &index) const
v = db.connLimit;
break;
case TablespaceCol:
// todo lookup tablespace name
v = getTablespaceDisplayString(*m_catalog, db.tablespace);
break;
case CommentCol:

View file

@ -38,6 +38,10 @@ public:
virtual Oid getType(int column) const override;
virtual QVariant getData(const QModelIndex &index) const override;
RowItem rowItem(int row) const
{
return databases.at(row).database;
}
protected:
virtual QVariant getDataMeaning(const QModelIndex &index) const override;
private:

View file

@ -1,8 +1,11 @@
#include "DatabasesPage.h"
#include "DatabasesTableModel.h"
#include "SqlCodePreview.h"
#include "SqlFormattingUtils.h"
#include "catalog/PgDatabaseCatalog.h"
#include "PgLabTableView.h"
#include <QStringBuilder>
DatabasesPage::DatabasesPage(std::shared_ptr<OpenDatabase> opendatabase, QWidget * parent)
@ -12,10 +15,18 @@ DatabasesPage::DatabasesPage(std::shared_ptr<OpenDatabase> opendatabase, QWidget
auto tv = m_databasesTableView.tableView();
tv->setSelectionMode(QAbstractItemView::SingleSelection);
m_detailsTabs = new QTabWidget(this);
// m_detailsTabs = new QTabWidget(this);
addWidget(tv);
addWidget(m_detailsTabs);
// addWidget(m_detailsTabs);
m_tableSql = new SqlCodePreview(this);
// m_detailsTabs->addTab(m_tableSql, "");
addWidget(m_tableSql);
connect(m_databasesTableView.tableView()->selectionModel(), &QItemSelectionModel::currentRowChanged,
this, &DatabasesPage::databaseSelectionChanged);
}
void DatabasesPage::setCatalog(std::shared_ptr<PgDatabaseCatalog> cat)
@ -25,6 +36,34 @@ void DatabasesPage::setCatalog(std::shared_ptr<PgDatabaseCatalog> cat)
m_databasesTableView.tableView()->resizeColumnsToContents();
}
void DatabasesPage::updateDatabaseDetails(const PgDatabase &db)
{
updateSqlTab(db);
}
void DatabasesPage::updateSqlTab(const PgDatabase &db)
{
QString drop_sql = db.dropSql();
QString create_sql = db.createSql();
create_sql += "\n\n-- set Privileges\n";
create_sql += db.grantSql() % "\n";
create_sql += "-- set comment\n";
create_sql += db.commentSql() % "\n";
m_tableSql->setPlainText(drop_sql % "\n\n" % create_sql);
}
void DatabasesPage::databaseSelectionChanged(const QModelIndex &current, const QModelIndex &previous)
{
if (current.row() == previous.row())
return;
auto db = m_databasesTableView.rowItemForProxyIndex(current);
updateDatabaseDetails(db);
}

View file

@ -6,9 +6,11 @@
#include "PgLabTableViewHelper.h"
#include "DatabasesTableModel.h"
class PgDatabase;
class PgDatabaseCatalog;
class PgLabTableView;
class QSortFilterProxyModel;
class SqlCodePreview;
class DatabasesPage: public QSplitter {
public:
@ -20,9 +22,16 @@ public:
private:
PgLabTableViewHelper<DatabasesTableModel> m_databasesTableView;
QTabWidget *m_detailsTabs = nullptr;
// QTabWidget *m_detailsTabs = nullptr;
SqlCodePreview *m_tableSql = nullptr;
std::shared_ptr<PgDatabaseCatalog> m_catalog;
void updateDatabaseDetails(const PgDatabase &db);
void updateSqlTab(const PgDatabase &db);
private slots:
void databaseSelectionChanged(const QModelIndex &current, const QModelIndex &previous);
};

View file

@ -20,7 +20,7 @@
#include <QApplication>
#include <QHeaderView>
#include <QStringBuilder>
#include <QSortFilterProxyModel>
//#include <QSortFilterProxyModel>
#include <QTableWidget>
CatalogTablesPage::CatalogTablesPage(std::shared_ptr<OpenDatabase> opendatabase, QWidget *parent)
@ -69,12 +69,6 @@ CatalogTablesPage::CatalogTablesPage(std::shared_ptr<OpenDatabase> opendatabase,
// Signals
connect(tv->selectionModel(), &QItemSelectionModel::currentRowChanged, this,
&CatalogTablesPage::tableListTable_currentRowChanged);
// connect(m_tablesTableView.dataModel(), &TablesTableModel::modelReset,
// [this] ()
// {
// selectedTableChanged({});
// m_propertiesPage->setActiveRow({});
// });
connect(m_tablesTableView.dataModel(), &QAbstractItemModel::layoutChanged,
this, &CatalogTablesPage::tableListTable_layoutChanged);
@ -117,10 +111,11 @@ void CatalogTablesPage::setNamespaceFilter(NamespaceFilter filter)
void CatalogTablesPage::tableListTable_currentRowChanged(const QModelIndex &current, const QModelIndex &previous)
{
if (current.row() != previous.row()) {
auto table = m_tablesTableView.rowItemForProxyIndex(current);
selectedTableChanged(table);
}
if (current.row() == previous.row())
return;
auto table = m_tablesTableView.rowItemForProxyIndex(current);
selectedTableChanged(table);
}
@ -160,8 +155,9 @@ void CatalogTablesPage::updateSqlTab(const std::optional<PgClass> &table)
QString drop_sql;
QString create_sql;
// create table
create_sql += table->createSql();
// table
drop_sql += table->dropSql() % "\n";
create_sql += table->createSql() % "\n";
// - columns
// - constraints
// table details (inherits etc)
@ -194,10 +190,7 @@ void CatalogTablesPage::updateSqlTab(const std::optional<PgClass> &table)
// Comments
create_sql += "-- set Comments table + columns\n";
if (!table->description.isEmpty()) {
create_sql += "COMMENT ON TABLE " + table->fullyQualifiedQuotedObjectName()
+ " IS " + dollarQuoteString(table->description) + ";\n";
}
create_sql += table->commentSql() % "\n";
auto && cols = m_catalog->attributes()->getColumnsForRelation(table->oid());
for (auto && col : cols) {

View file

@ -13,7 +13,8 @@ void operator<<(RelPersistence &s, const Pgsql::Value &v)
{
//s = static_cast<T>(v);
const char *c = v.c_str();
switch (*c) {
switch (*c)
{
case 'p':
s = RelPersistence::Permanent;
break;
@ -30,7 +31,8 @@ void operator<<(RelKind &s, const Pgsql::Value &v)
{
//s = static_cast<T>(v);
const char *c = v.c_str();
switch (*c) {
switch (*c)
{
case 'r':
s = RelKind::Table;
break;
@ -58,26 +60,27 @@ void operator<<(RelKind &s, const Pgsql::Value &v)
}
}
//QString PgClass::objectName() const
//{
// return name;
//}
QString PgClass::createSql() const
{
if (createSqlCache.isEmpty()) {
if (kind == RelKind::Table)
createSqlCache = createTableSql();
else if (kind == RelKind::View)
createSqlCache = createViewSql();
if (createSqlCache.isEmpty())
{
switch (kind)
{
case RelKind::Table:
createSqlCache = createTableSql();
break;
case RelKind::View:
createSqlCache = createViewSql();
break;
}
}
return createSqlCache;
}
QString PgClass::typeName() const
{
switch (kind) {
switch (kind)
{
case RelKind::Table: return "TABLE";
case RelKind::Index: return "INDEX";
case RelKind::Sequence: return "SEQUENCE";
@ -92,7 +95,8 @@ QString PgClass::typeName() const
QString PgClass::aclAllPattern() const
{
switch (kind) {
switch (kind)
{
case RelKind::Table: return "arwdDxt";
default:
break;
@ -115,9 +119,12 @@ QString PgClass::createTableSql() const
auto && cols = catalog().attributes()->getColumnsForRelation(oid());
bool first = true;
for (auto && col : cols) {
if (col.num > 0 && !col.isdropped) {
if (first) {
for (auto && col : cols)
{
if (col.num > 0 && !col.isdropped)
{
if (first)
{
first = false;
}
else sql += ",\n ";
@ -129,8 +136,10 @@ QString PgClass::createTableSql() const
// ] )
}
auto && constraints = catalog().constraints()->getConstraintsForRelation(oid());
for (auto && constraint: constraints) {
if (first) {
for (auto && constraint: constraints)
{
if (first)
{
sql += "\n ";
first = false;
}
@ -142,10 +151,12 @@ QString PgClass::createTableSql() const
{
// [ INHERITS ( parent_table [, ... ] ) ]
auto parents = catalog().inherits()->getParentsOf(oid());
if (!parents.empty()) {
if (!parents.empty())
{
sql += "\nINHERITS (";
bool first = true;
for (auto parent_oid : parents) {
for (auto parent_oid : parents)
{
if (first) first = false;
else sql += ", ";
sql += catalog().classes()->getByKey(parent_oid)->fullyQualifiedQuotedObjectName();
@ -156,8 +167,12 @@ QString PgClass::createTableSql() const
// [ PARTITION BY { RANGE | LIST } ( { column_name | ( expression ) } [ COLLATE collation ] [ opclass ] [, ... ] ) ]
// [ WITH ( storage_parameter [= value] [, ... ] ) | WITH OIDS | WITHOUT OIDS ]
// [ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ]
// [ TABLESPACE tablespace_name ]
sql += ";\n";
if (tablespace != 0)
{
auto ns = getTablespaceDisplayString(catalog(), tablespace);
sql += "\n TABLESPACE " % quoteIdent(ns);
}
sql += ";\n";
return sql;
}

View file

@ -32,7 +32,6 @@ class PgClass: public PgNamespaceObject {
public:
Oid type = InvalidOid;
Oid oftype = InvalidOid;
//Oid owner = InvalidOid;
Oid am = InvalidOid;
Oid filenode = InvalidOid;
Oid tablespace = InvalidOid;
@ -49,8 +48,6 @@ public:
std::vector<QString> options;
QString viewdef;
QString description; // from pg_description
using PgNamespaceObject::PgNamespaceObject;
QString kindString() const;

View file

@ -1,6 +1,51 @@
#include "PgDatabase.h"
#include "PgDatabaseCatalog.h"
#include "SqlFormattingUtils.h"
#include <QStringBuilder>
QString PgDatabase::typeName() const
{
return "DATABASE";
return "DATABASE";
}
QString PgDatabase::aclAllPattern() const
{
// Create
// Connect
// Temporary
return "CcT";
}
QString PgDatabase::dropSql() const
{
return "DROP DATABASE " % quotedObjectName() % ";";
}
QString PgDatabase::createSql() const
{
QString s = "CREATE DATABASE " % quotedObjectName()
// TEMPLATE is missing as this is not stored in the catalog
% "\n OWNER " % quoteIdent(ownerName())
% "\n ENCODING " % escapeLiteral(encodingString)
% "\n LC_COLLATE " % escapeLiteral(collate)
% "\n LC_TYPE " % escapeLiteral(ctype);
auto ns = getTablespaceDisplayString(catalog(), tablespace);
if (ns != "pg_default")
{
s += "\n TABLESPACE " % quoteIdent(ns);
}
if (!allowConn)
{
s += "\n ALLOW_CONNECTIONS FALSE";
}
if (connLimit >= 0)
{
s += "\n CONNECTION LIMIT " % QString::number(connLimit);
}
if (isTemplate)
{
s += "\n IS_TEMPLATE TRUE";
}
s += ";";
return s;
}

View file

@ -8,7 +8,6 @@
class PgDatabase: public PgServerObject {
public:
Oid dba; // owner?
int encoding;
QString encodingString;
QString collate;
@ -17,13 +16,15 @@ public:
bool allowConn;
int connLimit;
Oid tablespace;
QString description;
using PgServerObject::PgServerObject;
bool isValid() const { return oid() != InvalidOid; }
QString typeName() const override;
virtual QString aclAllPattern() const override;
virtual QString dropSql() const override;
virtual QString createSql() const override;
};
#endif // PGDATABASE_H

View file

@ -18,9 +18,10 @@ PgDatabase PgDatabaseContainer::loadElem(const Pgsql::Row &row)
Oid oid = col.nextValue();
QString name = col.nextValue();
PgDatabase v(m_catalog, oid, name);
col >> v.dba >> v.encoding >> v.encodingString >> v.collate >> v.ctype >> v.isTemplate
Oid owner;
col >> owner >> v.encoding >> v.encodingString >> v.collate >> v.ctype >> v.isTemplate
>> v.allowConn >> v.connLimit >> v.tablespace >> v.description;
v.setOwnerOid(owner);
AclList acl_list;
col >> acl_list;
v.setAcls(std::move(acl_list));

View file

@ -94,10 +94,20 @@ QString PgServerObject::aclAllPattern() const
QString PgServerObject::dropSql() const
{
return {};
return "DROP " % typeName() % " " % fullyQualifiedQuotedObjectName() % ";";
}
QString PgServerObject::createSql() const
{
return {};
return {};
}
QString PgServerObject::commentSql() const
{
if (description.isEmpty())
return {};
return "COMMENT ON " + typeName() + " " + fullyQualifiedQuotedObjectName()
+ " IS " + escapeLiteral(description) + ";";
}

View file

@ -13,7 +13,6 @@ class PgServerObject: public PgObject {
public:
using PgObject::PgObject;
void setOwnerOid(Oid oid);
Oid ownerOid() const;
bool hasOwner() const;
@ -21,6 +20,8 @@ public:
const PgAuthId* owner() const;
QString alterOwnerSql(const QString& ident) const;
QString description;
/**
* @brief setAcls
* @param acls Important: pass empty optional when acl IS NULL, pass empty list for empty array
@ -44,6 +45,7 @@ public:
virtual QString dropSql() const;
virtual QString createSql() const;
QString commentSql() const;
private:
Oid m_ownerOid = InvalidOid;
const PgAuthId * m_owner;