WIP: SQL for creating table and related objects

This commit is contained in:
eelke 2018-11-30 18:41:38 +01:00
parent 57217974f4
commit 498233d58c
15 changed files with 221 additions and 121 deletions

View file

@ -1,4 +1,10 @@
#include "PgClass.h"
#include "PgAttributeContainer.h"
#include "PgDatabaseCatalog.h"
#include "PgConstraintContainer.h"
#include <QStringBuilder>
#include "SqlFormattingUtils.h"
void operator<<(RelPersistence &s, const Pgsql::Value &v)
@ -54,3 +60,61 @@ void operator<<(RelKind &s, const Pgsql::Value &v)
//{
// return name;
//}
QString PgClass::createSql() const
{
if (createSqlCache.isEmpty()) {
if (kind == RelKind::Table)
createSqlCache = createTableSql();
}
return createSqlCache;
}
QString PgClass::createTableSql() const
{
QString sql;
// CREATE [ TEMP | UNLOGGED ] TABLE [ IF NOT EXISTS ] table_name ( [
sql += "CREATE ";
if (persistence == RelPersistence::Unlogged)
sql += "UNLOGGED ";
else if (persistence == RelPersistence::Temporary)
sql += "TEMP ";
sql += "TABLE ";
sql += fullyQualifiedQuotedObjectName();
sql += " (\n ";
auto && cols = catalog().attributes()->getColumnsForRelation(oid());
bool first = true;
for (auto && col : cols) {
if (col.num > 0 && !col.isdropped) {
if (first) {
sql += "\n ";
first = false;
}
else sql += ",\n ";
sql += col.columnDefinition(catalog());
}
// { column_name data_type [ COLLATE collation ] [ column_constraint [ ... ] ]
// | table_constraint
// ] )
}
auto && constraints = catalog().constraints()->getConstraintsForRelation(oid());
for (auto && constraint: constraints) {
if (first) {
sql += "\n ";
first = false;
}
else sql += ",\n ";
sql += getConstraintDefinition(catalog(), constraint);
}
sql += ")";
// [ INHERITS ( parent_table [, ... ] ) ]
// [ 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";
return sql;
}

View file

@ -65,7 +65,12 @@ public:
// bool operator<(Oid _oid) const { return oid < _oid; }
// bool operator<(const PgClass &rhs) const { return oid < rhs.oid; }
QString createSql() const;
private:
mutable QString createSqlCache;
QString createTableSql() const;
};
#endif // PGCLASS_H

View file

@ -163,7 +163,7 @@ QString ForeignKeyMatchToString(ForeignKeyMatch fkm)
}
PgConstraint::PgConstraint()
{
//PgConstraint::PgConstraint()
//{
}
//}

View file

@ -1,6 +1,7 @@
#ifndef PGCONSTRAINT_H
#define PGCONSTRAINT_H
#include "PgNamespaceObject.h"
#include "Pgsql_Value.h"
#include "PgCatalogTypes.h"
#include <QString>
@ -46,11 +47,8 @@ void operator<<(ForeignKeyMatch &s, const Pgsql::Value &v);
QString ForeignKeyMatchToString(ForeignKeyMatch fkm);
class PgConstraint {
class PgConstraint: public PgNamespaceObject {
public:
Oid oid = InvalidOid;
QString name;
Oid connamespace = InvalidOid;
ConstraintType type;
bool deferrable;
bool deferred;
@ -76,11 +74,7 @@ public:
QString definition;
PgConstraint();
bool operator==(Oid _oid) const { return oid == _oid; }
bool operator==(const QString &n) const { return name == n; }
bool operator<(Oid _oid) const { return oid < _oid; }
bool operator<(const PgConstraint &rhs) const { return oid < rhs.oid; }
using PgNamespaceObject::PgNamespaceObject;
};

View file

@ -20,25 +20,17 @@ FROM pg_constraint)__";
return q;
}
//void operator<<(std::vector<int16_t> &s, const Pgsql::Value &v)
//{
//}
//void operator<<(std::vector<Oid> &s, const Pgsql::Value &v)
//{
//}
PgConstraint PgConstraintContainer::loadElem(const Pgsql::Row &row)
{
using namespace Pgsql;
Col col(row);
PgConstraint v;
col >> v.oid >> v.name >> v.connamespace >> v.type >> v.deferrable
Oid oid = col.nextValue();
QString name = col.nextValue();
Oid ns_oid = col.nextValue();
PgConstraint v(m_catalog, oid, name, ns_oid);
col >> v.type >> v.deferrable
>> v.deferred >> v.validated >> v.relid >> v.typid >> v.indid
>> v.frelid >> v.fupdtype >> v.fdeltype >> v.fmatchtype
>> v.islocal >> v.inhcount >> v.noinherit

View file

@ -42,16 +42,6 @@ QString getRoleDisplayString(const PgDatabaseCatalog &cat, Oid oid)
return name;
}
QString getNamespaceDisplayString(const PgDatabaseCatalog &cat, Oid oid)
{
QString result;
auto nss = cat.namespaces();
auto ns = nss->getByKey(oid);
if (ns)
result = ns->objectName(); //QString("ns %1").arg(oid);
return result;
}
QString getClassDisplayString(const PgDatabaseCatalog &cat, Oid oid)
{
QString result;

View file

@ -112,7 +112,6 @@ private:
QString getRoleNameFromOid(const PgDatabaseCatalog &cat, Oid oid);
QString getRoleDisplayString(const PgDatabaseCatalog &cat, Oid oid);
QString getNamespaceDisplayString(const PgDatabaseCatalog &cat, Oid oid);
QString getTablespaceDisplayString(const PgDatabaseCatalog &cat, Oid oid);
QString getTypeDisplayString(const PgDatabaseCatalog &cat, Oid oid, int32_t typmod = -1);
QString getIndexDisplayString(const PgDatabaseCatalog &cat, Oid oid);

View file

@ -2,6 +2,7 @@
#include "PgDatabaseCatalog.h"
#include "PgClassContainer.h"
#include "PgAmContainer.h"
#include <QStringBuilder>
QString PgIndex::getAm() const
{
@ -15,3 +16,62 @@ QString PgIndex::getAm() const
}
return result;
}
QString PgIndex::createSql() const
{
return definition + ";";
// const PgClass *table_class = catalog.classes()->getByKey(index.relid);
// const PgClass *index_class = catalog.classes()->getByKey(index.indexrelid);
// QString result;
// result = "CREATE ";
// if (index.isunique)
// result += "UNIQUE ";
// result += "INDEX "
//// % quoteIdent(getIndexDisplayString(catalog, index.indexrelid))
// % quoteIdent(index_class.name)
// % "\n ON " % genFQTableName(catalog, table_class);
//// % "\n USING " % index_class.am lookup in pg_am table
// return result;
#if 0
+ wxT("\n USING ") + GetIndexType()
+ wxT("\n (");
if (GetProcName().IsNull())
str += GetQuotedColumns();
else
{
str += GetQuotedSchemaPrefix(GetProcNamespace()) + qtIdent(GetProcName()) + wxT("(") + GetQuotedColumns() + wxT(")");
if (!this->GetOperatorClasses().IsNull())
str += wxT(" ") + GetOperatorClasses();
}
str += wxT(")");
if (GetConnection()->BackendMinimumVersion(8, 2) && GetFillFactor().Length() > 0)
str += wxT("\n WITH (FILLFACTOR=") + GetFillFactor() + wxT(")");
if (GetConnection()->BackendMinimumVersion(8, 0) && tablespace != GetDatabase()->GetDefaultTablespace())
str += wxT("\nTABLESPACE ") + qtIdent(tablespace);
AppendIfFilled(str, wxT("\n WHERE "), GetConstraint());
str += wxT(";\n");
if (GetConnection()->BackendMinimumVersion(7, 5))
if (GetIsClustered())
str += wxT("ALTER TABLE ") + GetQuotedSchemaPrefix(GetIdxSchema()) + qtIdent(GetIdxTable())
+ wxT(" CLUSTER ON ") + qtIdent(GetName())
+ wxT(";\n");
#endif
}
QString PgIndex::dropSql() const
{
QString result;
result = "DROP INDEX "
% fullyQualifiedQuotedObjectName()
% ";";
return result;
}

View file

@ -37,6 +37,9 @@ public:
// //bool operator==(const QString &n) const { return name == n; }
// bool operator<(Oid _oid) const { return indexrelid < _oid; }
// bool operator<(const PgIndex &rhs) const { return indexrelid < rhs.indexrelid; }
QString createSql() const;
QString dropSql() const;
};
#endif // PGINDEX_H

View file

@ -261,7 +261,7 @@ QString dollarQuoteString(const QString &value)
// return ns->quotedObjectName() % "." % cls.quotedObjectName();
//}
QString genAlterTable(const PgDatabaseCatalog &catalog, const PgClass &cls)
QString genAlterTable(const PgDatabaseCatalog &, const PgClass &cls)
{
return "ALTER TABLE " % cls.fullyQualifiedQuotedObjectName(); // genFQTableName(catalog, cls);
}
@ -269,7 +269,7 @@ QString genAlterTable(const PgDatabaseCatalog &catalog, const PgClass &cls)
QString getDropConstraintDefinition(const PgDatabaseCatalog &catalog, const PgConstraint &constraint)
{
const PgClass *cls = catalog.classes()->getByKey(constraint.relid);
return genAlterTable(catalog, *cls) % " DROP CONSTRAINT " % quoteIdent(constraint.name) % ";";
return genAlterTable(catalog, *cls) % " DROP CONSTRAINT " % quoteIdent(constraint.objectName()) % ";";
}
@ -368,7 +368,7 @@ QString getForeignKeyConstraintReferencesShort(const PgDatabaseCatalog &catalog,
QString getPrimaryKeyConstraintDefinition(const PgDatabaseCatalog &catalog, const PgConstraint &constraint)
{
QString ddl = " PRIMARY KEY ("
% getColumnNameList(catalog, constraint.relid, constraint.key) % ");";
% getColumnNameList(catalog, constraint.relid, constraint.key) % ")";
return ddl;
}
@ -376,18 +376,22 @@ QString getPrimaryKeyConstraintDefinition(const PgDatabaseCatalog &catalog, cons
QString getUniqueConstraintDefinition(const PgDatabaseCatalog &catalog, const PgConstraint &constraint)
{
QString ddl = " UNIQUE ("
% getColumnNameList(catalog, constraint.relid, constraint.key) % ");";
% getColumnNameList(catalog, constraint.relid, constraint.key) % ")";
return ddl;
}
QString getConstraintDefinition(const PgDatabaseCatalog &catalog, const PgConstraint &constraint)
QString getAlterTableConstraintDefinition(const PgDatabaseCatalog &catalog, const PgConstraint &constraint)
{
const PgClass *cls = catalog.classes()->getByKey(constraint.relid);
// return genAlterTable(catalog, cls) % " ADD CONSTRAINT "
// % quoteIdent(constraint.name) % " " % constraint.definition % ";";
QString result = genAlterTable(catalog, *cls) % "\n ADD CONSTRAINT "
% quoteIdent(constraint.name);
QString result = genAlterTable(catalog, *cls) % "\n ADD ";
result += getConstraintDefinition(catalog, constraint) % ";";
return result;
}
QString getConstraintDefinition(const PgDatabaseCatalog &catalog, const PgConstraint &constraint)
{
QString result = "CONSTRAINT " % quoteIdent(constraint.objectName());
switch (constraint.type) {
case ConstraintType::ForeignKey:
result += getForeignKeyConstraintDefinition(catalog, constraint);
@ -406,66 +410,4 @@ QString getConstraintDefinition(const PgDatabaseCatalog &catalog, const PgConstr
return result;
}
QString getIndexDefinition(const PgDatabaseCatalog &, const PgIndex &index)
{
// const PgClass *table_class = catalog.classes()->getByKey(index.relid);
// const PgClass *index_class = catalog.classes()->getByKey(index.indexrelid);
return index.definition + ";";
// QString result;
// result = "CREATE ";
// if (index.isunique)
// result += "UNIQUE ";
// result += "INDEX "
//// % quoteIdent(getIndexDisplayString(catalog, index.indexrelid))
// % quoteIdent(index_class.name)
// % "\n ON " % genFQTableName(catalog, table_class);
//// % "\n USING " % index_class.am lookup in pg_am table
// return result;
#if 0
+ wxT("\n USING ") + GetIndexType()
+ wxT("\n (");
if (GetProcName().IsNull())
str += GetQuotedColumns();
else
{
str += GetQuotedSchemaPrefix(GetProcNamespace()) + qtIdent(GetProcName()) + wxT("(") + GetQuotedColumns() + wxT(")");
if (!this->GetOperatorClasses().IsNull())
str += wxT(" ") + GetOperatorClasses();
}
str += wxT(")");
if (GetConnection()->BackendMinimumVersion(8, 2) && GetFillFactor().Length() > 0)
str += wxT("\n WITH (FILLFACTOR=") + GetFillFactor() + wxT(")");
if (GetConnection()->BackendMinimumVersion(8, 0) && tablespace != GetDatabase()->GetDefaultTablespace())
str += wxT("\nTABLESPACE ") + qtIdent(tablespace);
AppendIfFilled(str, wxT("\n WHERE "), GetConstraint());
str += wxT(";\n");
if (GetConnection()->BackendMinimumVersion(7, 5))
if (GetIsClustered())
str += wxT("ALTER TABLE ") + GetQuotedSchemaPrefix(GetIdxSchema()) + qtIdent(GetIdxTable())
+ wxT(" CLUSTER ON ") + qtIdent(GetName())
+ wxT(";\n");
#endif
}
QString getDropIndexDefinition(const PgDatabaseCatalog &catalog, const PgIndex &index)
{
// const PgClass *table_class = catalog.classes()->getByKey(index.relid);
// const PgClass *index_class = catalog.classes()->getByKey(index.indexrelid);
QString result;
result = "DROP INDEX "
% index.fullyQualifiedQuotedObjectName() // quoteIdent(getIndexDisplayString(catalog, index.indexrelid))
% ";";
return result;
}

View file

@ -20,9 +20,8 @@ QString dollarQuoteString(const QString &value);
//QString genFQTableName(const PgDatabaseCatalog &catalog, const PgClass &cls);
QString getDropConstraintDefinition(const PgDatabaseCatalog &catalog, const PgConstraint &constraint);
QString getAlterTableConstraintDefinition(const PgDatabaseCatalog &catalog, const PgConstraint &constraint);
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