Improve support for declarative partitioning.

Generated SQL for a partition is now correct (atleast for simple cases)
Switched to C++ 20 so the ranges library can be used in this case
to filter unwanted items.
This commit is contained in:
eelke 2023-01-18 19:43:12 +01:00
parent 7a4d8f3410
commit 60fb4ce285
4 changed files with 92 additions and 38 deletions

View file

@ -4,7 +4,7 @@ error( "Use local.pri.sample to create your own local.pri" )
LIBS += -lUser32 -lws2_32 -llibpq LIBS += -lUser32 -lws2_32 -llibpq
CONFIG += c++latest CONFIG += c++20
# The following define makes your compiler emit warnings if you use # The following define makes your compiler emit warnings if you use
# any feature of Qt which as been marked as deprecated (the exact warnings # any feature of Qt which as been marked as deprecated (the exact warnings

View file

@ -6,7 +6,7 @@
#include "PgInheritsContainer.h" #include "PgInheritsContainer.h"
#include <QStringBuilder> #include <QStringBuilder>
#include "SqlFormattingUtils.h" #include "SqlFormattingUtils.h"
#include <ranges>
void operator<<(RelPersistence &s, const Pgsql::Value &v) void operator<<(RelPersistence &s, const Pgsql::Value &v)
@ -125,13 +125,56 @@ QString PgClass::createTableSql() const
sql += "TEMP "; sql += "TEMP ";
sql += "TABLE "; sql += "TABLE ";
sql += fullyQualifiedQuotedObjectName(); sql += fullyQualifiedQuotedObjectName();
sql += " (\n ";
auto && cols = catalog().attributes()->getColumnsForRelation(oid()); if (!partitionBoundaries.isEmpty())
{
sql += " PARTITION OF " + getPartitionOfName();
sql += generateBodySql(true);
}
else
sql += generateBodySql(false);
sql += generateInheritsSql()
% generateTablespaceSql()
% ";\n";
return sql;
}
QString PgClass::generateBodySql(bool isPartition) const
{
// - also remove commented inherited column list? They are listed in the column view no need for them in sql
// - mark them in the view as inherited?
// - detect when body empty and leave it out completely (only for partitions, is leaving it out always legal?)
// - need to detect "inherited" constraint because these should not be listed either
auto colsFilter = isPartition ?
[] (const PgAttribute &c)
{
return c.num > 0 // ignore system columns
&& !c.isdropped // ignore dropped columns
&& c.islocal;
}
:
[] (const PgAttribute &c)
{
return c.num > 0 // ignore system columns
&& !c.isdropped; // ignore dropped columns
}
;
auto && cols = catalog().attributes()->getColumnsForRelation(oid())
| std::views::filter(colsFilter);
auto && constraints = catalog().constraints()->getConstraintsForRelation(oid())
| std::views::filter([] (const auto &c) { return c.islocal; });
if (cols.empty() && constraints.empty())
return {};
QString sql = " (\n ";
bool first = true; bool first = true;
for (auto && col : cols) for (auto && col : cols)
{
if (col.num > 0 && !col.isdropped)
{ {
if (first) if (first)
{ {
@ -142,11 +185,8 @@ QString PgClass::createTableSql() const
if (!col.islocal) sql += "-- "; if (!col.islocal) sql += "-- ";
sql += col.columnDefinition(catalog()); sql += col.columnDefinition(catalog());
} }
// { column_name data_type [ COLLATE collation ] [ column_constraint [ ... ] ]
// | table_constraint
// ] )
}
auto && constraints = catalog().constraints()->getConstraintsForRelation(oid());
for (auto && constraint: constraints) for (auto && constraint: constraints)
{ {
if (first) if (first)
@ -159,18 +199,16 @@ QString PgClass::createTableSql() const
sql += getConstraintDefinition(catalog(), constraint, " "); sql += getConstraintDefinition(catalog(), constraint, " ");
} }
sql += "\n)" sql += "\n)";
% generateInheritsSql()
// [ 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 } ]
% generateTablespaceSql()
% ";\n";
return sql; return sql;
} }
QString PgClass::generateInheritsSql() const QString PgClass::generateInheritsSql() const
{ {
if (!partitionBoundaries.isEmpty())
return "\n" + partitionBoundaries;
QString sql; QString sql;
// [ INHERITS ( parent_table [, ... ] ) ] // [ INHERITS ( parent_table [, ... ] ) ]
auto parents = catalog().inherits()->getParentsOf(oid()); auto parents = catalog().inherits()->getParentsOf(oid());
@ -189,6 +227,16 @@ QString PgClass::generateInheritsSql() const
return sql; return sql;
} }
QString PgClass::getPartitionOfName() const
{
auto parents = catalog().inherits()->getParentsOf(oid());
if (!parents.empty())
{
return catalog().classes()->getByKey(parents.front())->fullyQualifiedQuotedObjectName();
}
throw std::logic_error("Should only be called if there is a parent table");
}
QString PgClass::generateTablespaceSql() const QString PgClass::generateTablespaceSql() const
{ {
if (tablespace != 0) if (tablespace != 0)

View file

@ -62,7 +62,9 @@ private:
mutable QString createSqlCache; mutable QString createSqlCache;
QString createTableSql() const; QString createTableSql() const;
QString generateBodySql(bool isPartition) const;
QString generateInheritsSql() const; QString generateInheritsSql() const;
QString getPartitionOfName() const;
QString generateTablespaceSql() const; QString generateTablespaceSql() const;
QString createViewSql() const; QString createViewSql() const;
}; };

View file

@ -79,6 +79,10 @@ public:
QString dropSql() const override; QString dropSql() const override;
QString createSql() const override; QString createSql() const override;
bool isInherited() const
{
return inhcount > 0;
}
}; };