From 365490870a712885ce11cb43ac8ce97b93cb80d9 Mon Sep 17 00:00:00 2001 From: Sumit Jaiswal <54075285+sumitj824@users.noreply.github.com> Date: Thu, 25 Jul 2024 20:48:02 +0530 Subject: [PATCH] BABEL: Support Table and Index partitioning in Babelfish (#399) To support partitioned tables and indexes in Babelfish, this commit introduces the following changes: Babelfish stores the creation date and original name of the table in the reloption, whereas PostgreSQL does not allow the usage of reloption for partitioned tables. This commit enables the usage of reloption for Babelfish partitioned tables to store the creation date and original name. This information will be utilized by various system views, such as information_schema_tsql.tables, sys.tables, etc., to display the table creation date and original name. Babelfish supports column ordering and NULLs ordering in table constraints while PostgreSQL does not and to handle dump/restore of this we dump the underlying index of a UNIQUE/PRIMARY KEY constraint and make use of ALTER TABLE ADD CONSTRAINT USING syntax to support column ordering and NULLs ordering in table constraints. PostgreSQL disallows creation of an constraint using index like this for partitioned table so we will need to bypass that check during restore of Babelfish databases. Signed-off-by: Sumit Jaiswal sumiji@amazon.com --- src/backend/access/common/reloptions.c | 12 +++++++++++- src/backend/commands/tablecmds.c | 4 +++- src/backend/parser/parse_utilcmd.c | 9 +++++++-- src/include/access/reloptions.h | 2 ++ src/include/nodes/parsenodes.h | 1 + 5 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c index 571572c86ac..f399c0b655c 100644 --- a/src/backend/access/common/reloptions.c +++ b/src/backend/access/common/reloptions.c @@ -564,6 +564,8 @@ static void initialize_reloptions(void); static void parse_one_reloption(relopt_value *option, char *text_str, int text_len, bool validate); +pltsql_is_partitioned_table_reloptions_allowed_hook_type pltsql_is_partitioned_table_reloptions_allowed_hook = NULL; + /* * Get the length of a string reloption (either default or the user-defined * value). This is used for allocation purposes when building a set of @@ -2001,10 +2003,18 @@ bytea * partitioned_table_reloptions(Datum reloptions, bool validate) { if (validate && reloptions) + { + /* + * For babelfish partitioned table, allow usage of reloptions in TSQL dialect. + */ + if (pltsql_is_partitioned_table_reloptions_allowed_hook && pltsql_is_partitioned_table_reloptions_allowed_hook(reloptions)) + return NULL; + ereport(ERROR, errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("cannot specify storage parameters for a partitioned table"), - errhint("Specify storage parameters for its leaf partitions, instead.")); + errhint("Specify storage parameters for its leaf partitions instead.")); + } return NULL; } diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 4adcc406aff..c78d4043713 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -8857,6 +8857,7 @@ ATExecAddIndexConstraint(AlteredTableInfo *tab, Relation rel, char constraintType; ObjectAddress address; bits16 flags; + const char *bbf_dump_restore = GetConfigOption("babelfishpg_tsql.dump_restore", true, false); Assert(IsA(stmt, IndexStmt)); Assert(OidIsValid(index_oid)); @@ -8866,7 +8867,8 @@ ATExecAddIndexConstraint(AlteredTableInfo *tab, Relation rel, * Doing this on partitioned tables is not a simple feature to implement, * so let's punt for now. */ - if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) + if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE && + (!bbf_dump_restore || strcmp(bbf_dump_restore, "on") != 0)) /* For Babelfish databases, allow the restore of index for partitioned table. */ ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("ALTER TABLE / ADD CONSTRAINT USING INDEX is not supported on partitioned tables"))); diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c index fcb8020836a..9d452bd58af 100644 --- a/src/backend/parser/parse_utilcmd.c +++ b/src/backend/parser/parse_utilcmd.c @@ -2282,8 +2282,13 @@ transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt) errmsg("index \"%s\" does not belong to table \"%s\"", index_name, RelationGetRelationName(heap_rel)), parser_errposition(cxt->pstate, constraint->location))); - - if (!index_form->indisvalid) + /* + * For Babelfish databases, allow the restore of index which is + * marked as not valid for partitioned table. + */ + if (!index_form->indisvalid && + !(bbf_dump_restore && strcmp(bbf_dump_restore, "on") == 0 && + RelationGetForm(heap_rel)->relkind == RELKIND_PARTITIONED_TABLE)) ereport(ERROR, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), errmsg("index \"%s\" is not valid", index_name), diff --git a/src/include/access/reloptions.h b/src/include/access/reloptions.h index 1d5bfa62ffc..eddd45be50d 100644 --- a/src/include/access/reloptions.h +++ b/src/include/access/reloptions.h @@ -243,5 +243,7 @@ extern bytea *index_reloptions(amoptions_function amoptions, Datum reloptions, extern bytea *attribute_reloptions(Datum reloptions, bool validate); extern bytea *tablespace_reloptions(Datum reloptions, bool validate); extern LOCKMODE AlterTableGetRelOptionsLockLevel(List *defList); +typedef bool (*pltsql_is_partitioned_table_reloptions_allowed_hook_type)(); +extern PGDLLEXPORT pltsql_is_partitioned_table_reloptions_allowed_hook_type pltsql_is_partitioned_table_reloptions_allowed_hook; #endif /* RELOPTIONS_H */ diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index bc21ac9b7ca..4afa27961c1 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -883,6 +883,7 @@ typedef struct PartitionSpec PartitionStrategy strategy; List *partParams; /* List of PartitionElems */ int location; /* token location, or -1 if unknown */ + char *tsql_partition_scheme; /* tsql partition scheme name */ } PartitionSpec; /*