From bdce4a7e67ff73f14eb344abb9f8bed7deb1a38d Mon Sep 17 00:00:00 2001 From: Ahmet Gedemenli Date: Wed, 23 Dec 2020 14:46:46 +0300 Subject: [PATCH] Propagate rename statistics --- .../commands/distribute_object_ops.c | 12 ++++++ src/backend/distributed/commands/statistics.c | 41 ++++++++++++++++++- .../deparser/deparse_statistics_stmts.c | 25 ++++++++++- .../deparser/qualify_statistics_stmt.c | 21 ++++++++++ .../distributed/relay/relay_event_utility.c | 11 +++++ src/include/distributed/commands.h | 1 + src/include/distributed/deparser.h | 2 + .../regress/expected/propagate_statistics.out | 6 +++ src/test/regress/sql/propagate_statistics.sql | 6 +++ 9 files changed, 122 insertions(+), 3 deletions(-) diff --git a/src/backend/distributed/commands/distribute_object_ops.c b/src/backend/distributed/commands/distribute_object_ops.c index 38cee4041..77d9b2659 100644 --- a/src/backend/distributed/commands/distribute_object_ops.c +++ b/src/backend/distributed/commands/distribute_object_ops.c @@ -414,6 +414,13 @@ static DistributeObjectOps Schema_Rename = { .postprocess = NULL, .address = AlterSchemaRenameStmtObjectAddress, }; +static DistributeObjectOps Statistics_Rename = { + .deparse = DeparseAlterStatisticsRenameStmt, + .qualify = QualifyAlterStatisticsRenameStmt, + .preprocess = PreprocessAlterStatisticsRenameStmt, + .postprocess = NULL, + .address = NULL, +}; static DistributeObjectOps Statistics_Drop = { .deparse = NULL, .qualify = QualifyDropStatisticsStmt, @@ -907,6 +914,11 @@ GetDistributeObjectOps(Node *node) return &Schema_Rename; } + case OBJECT_STATISTIC_EXT: + { + return &Statistics_Rename; + } + case OBJECT_TYPE: { return &Type_Rename; diff --git a/src/backend/distributed/commands/statistics.c b/src/backend/distributed/commands/statistics.c index 46fd2ed33..2d214bfc7 100644 --- a/src/backend/distributed/commands/statistics.c +++ b/src/backend/distributed/commands/statistics.c @@ -190,6 +190,44 @@ PreprocessDropStatisticsStmt(Node *node, const char *queryString) } +/* + * PreprocessAlterStatisticsRenameStmt is called during the planning phase for + * ALTER STATISTICS RENAME. + */ +List * +PreprocessAlterStatisticsRenameStmt(Node *node, const char *queryString) +{ + RenameStmt *renameStmt = castNode(RenameStmt, node); + Assert(renameStmt->renameType == OBJECT_STATISTIC_EXT); + + Oid statsOid = get_statistics_object_oid((List *) renameStmt->object, false); + Oid relationId = GetRelIdByStatsOid(statsOid); + + if (!IsCitusTable(relationId) || !ShouldPropagate()) + { + return NIL; + } + + EnsureCoordinator(); + + QualifyTreeNode((Node *) renameStmt); + + char *ddlCommand = DeparseTreeNode((Node *) renameStmt); + + DDLJob *ddlJob = palloc0(sizeof(DDLJob)); + + ddlJob->targetRelationId = relationId; + ddlJob->concurrentIndexCmd = false; + ddlJob->startNewTransaction = false; + ddlJob->commandString = ddlCommand; + ddlJob->taskList = DDLTaskList(relationId, ddlCommand); + + List *ddlJobs = list_make1(ddlJob); + + return ddlJobs; +} + + /* * GetExplicitStatisticsCommandList returns the list of DDL commands to create * statistics that are explicitly created for the table with relationId. See @@ -207,7 +245,8 @@ GetExplicitStatisticsCommandList(Oid relationId) Oid statisticsId = InvalidOid; foreach_oid(statisticsId, statisticsIdList) { - char *createStatisticsCommand = pg_get_statisticsobj_worker(statisticsId, false); + char *createStatisticsCommand = pg_get_statisticsobj_worker(statisticsId, + false); createStatisticsCommandList = lappend( createStatisticsCommandList, diff --git a/src/backend/distributed/deparser/deparse_statistics_stmts.c b/src/backend/distributed/deparser/deparse_statistics_stmts.c index 58fd8f736..117b19709 100644 --- a/src/backend/distributed/deparser/deparse_statistics_stmts.c +++ b/src/backend/distributed/deparser/deparse_statistics_stmts.c @@ -26,6 +26,7 @@ static void AppendStatisticsName(StringInfo buf, CreateStatsStmt *stmt); static void AppendStatTypes(StringInfo buf, CreateStatsStmt *stmt); static void AppendColumnNames(StringInfo buf, CreateStatsStmt *stmt); static void AppendTableName(StringInfo buf, CreateStatsStmt *stmt); +static void AppendAlterStatisticsRenameStmt(StringInfo buf, RenameStmt *stmt); char * DeparseCreateStatisticsStmt(Node *node) @@ -53,6 +54,20 @@ DeparseDropStatisticsStmt(List *nameList, bool ifExists) } +char * +DeparseAlterStatisticsRenameStmt(Node *node) +{ + RenameStmt *stmt = castNode(RenameStmt, node); + + StringInfoData str; + initStringInfo(&str); + + AppendAlterStatisticsRenameStmt(&str, stmt); + + return str.data; +} + + static void AppendCreateStatisticsStmt(StringInfo buf, CreateStatsStmt *stmt) { @@ -74,8 +89,6 @@ AppendCreateStatisticsStmt(StringInfo buf, CreateStatsStmt *stmt) appendStringInfoString(buf, " FROM "); AppendTableName(buf, stmt); - - appendStringInfoString(buf, ";"); } @@ -93,6 +106,14 @@ AppendDropStatisticsStmt(StringInfo buf, List *nameList, bool ifExists) } +static void +AppendAlterStatisticsRenameStmt(StringInfo buf, RenameStmt *stmt) +{ + appendStringInfo(buf, "ALTER STATISTICS %s RENAME TO %s", + NameListToQuotedString((List *) stmt->object), stmt->newname); +} + + static void AppendStatisticsName(StringInfo buf, CreateStatsStmt *stmt) { diff --git a/src/backend/distributed/deparser/qualify_statistics_stmt.c b/src/backend/distributed/deparser/qualify_statistics_stmt.c index 9e6d97fa8..8947f2f5d 100644 --- a/src/backend/distributed/deparser/qualify_statistics_stmt.c +++ b/src/backend/distributed/deparser/qualify_statistics_stmt.c @@ -78,3 +78,24 @@ QualifyDropStatisticsStmt(Node *node) dropStatisticsStmt->objects = objectNameListWithSchema; } + + +/* + * QualifyAlterStatisticsRenameStmt qualifies RenameStmt's with schema name for + * ALTER STATISTICS RENAME statements. + */ +void +QualifyAlterStatisticsRenameStmt(Node *node) +{ + RenameStmt *renameStmt = castNode(RenameStmt, node); + Assert(renameStmt->renameType == OBJECT_STATISTIC_EXT); + + List *nameList = (List *) renameStmt->object; + if (list_length(nameList) == 1) + { + RangeVar *stat = makeRangeVarFromNameList(nameList); + Oid schemaOid = RangeVarGetCreationNamespace(stat); + stat->schemaname = get_namespace_name(schemaOid); + renameStmt->object = (Node *) MakeNameListFromRangeVar(stat); + } +} diff --git a/src/backend/distributed/relay/relay_event_utility.c b/src/backend/distributed/relay/relay_event_utility.c index fd9f4de71..5483966b9 100644 --- a/src/backend/distributed/relay/relay_event_utility.c +++ b/src/backend/distributed/relay/relay_event_utility.c @@ -530,6 +530,17 @@ RelayEventExtendNames(Node *parseTree, char *schemaName, uint64 shardId) { RenamePolicyEventExtendNames(renameStmt, schemaName, shardId); } + else if (objectType == OBJECT_STATISTIC_EXT) + { + RangeVar *stat = makeRangeVarFromNameList((List *) renameStmt->object); + + AppendShardIdToName(&stat->relname, shardId); + AppendShardIdToName(&renameStmt->newname, shardId); + + SetSchemaNameIfNotExist(&stat->schemaname, schemaName); + + renameStmt->object = (Node *) MakeNameListFromRangeVar(stat); + } else { ereport(WARNING, (errmsg("unsafe object type in rename statement"), diff --git a/src/include/distributed/commands.h b/src/include/distributed/commands.h index b33e5486e..cde9193d2 100644 --- a/src/include/distributed/commands.h +++ b/src/include/distributed/commands.h @@ -282,6 +282,7 @@ extern List * PreprocessCreateStatisticsStmt(Node *node, const char *queryString extern List * PostprocessCreateStatisticsStmt(Node *node, const char *queryString); extern ObjectAddress CreateStatisticsStmtObjectAddress(Node *node, bool missingOk); extern List * PreprocessDropStatisticsStmt(Node *node, const char *queryString); +extern List * PreprocessAlterStatisticsRenameStmt(Node *node, const char *queryString); extern List * GetExplicitStatisticsCommandList(Oid relationId); extern List * GetExplicitStatisticsSchemaIdList(Oid relationId); diff --git a/src/include/distributed/deparser.h b/src/include/distributed/deparser.h index d49797f05..9f152e880 100644 --- a/src/include/distributed/deparser.h +++ b/src/include/distributed/deparser.h @@ -58,9 +58,11 @@ extern char * DeparseAlterSchemaRenameStmt(Node *stmt); /* forward declarations for deparse_statistics_stmts.c */ extern char * DeparseCreateStatisticsStmt(Node *node); extern char * DeparseDropStatisticsStmt(List *nameList, bool ifExists); +extern char * DeparseAlterStatisticsRenameStmt(Node *node); extern void QualifyCreateStatisticsStmt(Node *node); extern void QualifyDropStatisticsStmt(Node *node); +extern void QualifyAlterStatisticsRenameStmt(Node *node); /* forward declarations for deparse_type_stmts.c */ extern char * DeparseCompositeTypeStmt(Node *stmt); diff --git a/src/test/regress/expected/propagate_statistics.out b/src/test/regress/expected/propagate_statistics.out index 2a69cec89..0cd0825a4 100644 --- a/src/test/regress/expected/propagate_statistics.out +++ b/src/test/regress/expected/propagate_statistics.out @@ -70,6 +70,12 @@ DROP STATISTICS IF EXISTS s3, sc2.s4, s6; DROP STATISTICS s5,s6; ERROR: statistics object "statistics'Test.s6" does not exist DROP STATISTICS IF EXISTS s5,s5,s6,s6; +-- test renaming statistics +CREATE STATISTICS s6 ON a,b FROM test_stats4; +DROP STATISTICS s7; +ERROR: statistics object "statistics'Test.s7" does not exist +ALTER STATISTICS s6 RENAME TO s7; +DROP STATISTICS s7; \c - - - :worker_1_port SELECT stxname FROM pg_statistic_ext diff --git a/src/test/regress/sql/propagate_statistics.sql b/src/test/regress/sql/propagate_statistics.sql index 1c46b9644..7a4dbcc94 100644 --- a/src/test/regress/sql/propagate_statistics.sql +++ b/src/test/regress/sql/propagate_statistics.sql @@ -57,6 +57,12 @@ DROP STATISTICS IF EXISTS s3, sc2.s4, s6; DROP STATISTICS s5,s6; DROP STATISTICS IF EXISTS s5,s5,s6,s6; +-- test renaming statistics +CREATE STATISTICS s6 ON a,b FROM test_stats4; +DROP STATISTICS s7; +ALTER STATISTICS s6 RENAME TO s7; +DROP STATISTICS s7; + \c - - - :worker_1_port SELECT stxname FROM pg_statistic_ext