From bdce4a7e67ff73f14eb344abb9f8bed7deb1a38d Mon Sep 17 00:00:00 2001 From: Ahmet Gedemenli Date: Wed, 23 Dec 2020 14:46:46 +0300 Subject: [PATCH 1/6] 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 From 5a1607b6c082cca1e60071eec1632f027c8566b3 Mon Sep 17 00:00:00 2001 From: Ahmet Gedemenli Date: Wed, 23 Dec 2020 15:56:33 +0300 Subject: [PATCH 2/6] Propagate alter stats schema --- .../commands/distribute_object_ops.c | 24 +++-- src/backend/distributed/commands/statistics.c | 90 +++++++++++++++++++ .../deparser/deparse_statistics_stmts.c | 29 +++++- .../deparser/qualify_statistics_stmt.c | 21 +++++ .../distributed/relay/relay_event_utility.c | 30 +++++-- src/include/distributed/commands.h | 3 + src/include/distributed/deparser.h | 2 + .../regress/expected/propagate_statistics.out | 6 +- src/test/regress/sql/propagate_statistics.sql | 7 +- 9 files changed, 196 insertions(+), 16 deletions(-) diff --git a/src/backend/distributed/commands/distribute_object_ops.c b/src/backend/distributed/commands/distribute_object_ops.c index 77d9b2659..7e140a13d 100644 --- a/src/backend/distributed/commands/distribute_object_ops.c +++ b/src/backend/distributed/commands/distribute_object_ops.c @@ -414,12 +414,12 @@ 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_AlterObjectSchema = { + .deparse = DeparseAlterStatisticsSchemaStmt, + .qualify = QualifyAlterStatisticsSchemaStmt, + .preprocess = PreprocessAlterStatisticsSchemaStmt, + .postprocess = PostprocessAlterStatisticsSchemaStmt, + .address = AlterStatisticsSchemaStmtObjectAddress, }; static DistributeObjectOps Statistics_Drop = { .deparse = NULL, @@ -428,6 +428,13 @@ static DistributeObjectOps Statistics_Drop = { .postprocess = NULL, .address = NULL, }; +static DistributeObjectOps Statistics_Rename = { + .deparse = DeparseAlterStatisticsRenameStmt, + .qualify = QualifyAlterStatisticsRenameStmt, + .preprocess = PreprocessAlterStatisticsRenameStmt, + .postprocess = NULL, + .address = NULL, +}; static DistributeObjectOps Table_AlterTable = { .deparse = NULL, .qualify = NULL, @@ -597,6 +604,11 @@ GetDistributeObjectOps(Node *node) return &Routine_AlterObjectSchema; } + case OBJECT_STATISTIC_EXT: + { + return &Statistics_AlterObjectSchema; + } + case OBJECT_TABLE: { return &Table_AlterObjectSchema; diff --git a/src/backend/distributed/commands/statistics.c b/src/backend/distributed/commands/statistics.c index 2d214bfc7..7db7e06c4 100644 --- a/src/backend/distributed/commands/statistics.c +++ b/src/backend/distributed/commands/statistics.c @@ -228,6 +228,96 @@ PreprocessAlterStatisticsRenameStmt(Node *node, const char *queryString) } +/* + * PreprocessAlterStatisticsSchemaStmt is called during the planning phase for + * ALTER STATISTICS SET SCHEMA. + */ +List * +PreprocessAlterStatisticsSchemaStmt(Node *node, const char *queryString) +{ + AlterObjectSchemaStmt *stmt = castNode(AlterObjectSchemaStmt, node); + Assert(stmt->objectType == OBJECT_STATISTIC_EXT); + + Oid statsOid = get_statistics_object_oid((List *) stmt->object, false); + Oid relationId = GetRelIdByStatsOid(statsOid); + + if (!IsCitusTable(relationId) || !ShouldPropagate()) + { + return NIL; + } + + EnsureCoordinator(); + + QualifyTreeNode((Node *) stmt); + + char *ddlCommand = DeparseTreeNode((Node *) stmt); + + 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; +} + + +/* + * PostprocessAlterStatisticsSchemaStmt is called after a ALTER STATISTICS SCHEMA + * command has been executed by standard process utility. + */ +List * +PostprocessAlterStatisticsSchemaStmt(Node *node, const char *queryString) +{ + AlterObjectSchemaStmt *stmt = castNode(AlterObjectSchemaStmt, node); + Assert(stmt->objectType == OBJECT_STATISTIC_EXT); + + Value *statName = llast((List *) stmt->object); + Oid statsOid = get_statistics_object_oid(list_make2(makeString(stmt->newschema), + statName), false); + Oid relationId = GetRelIdByStatsOid(statsOid); + + if (!IsCitusTable(relationId) || !ShouldPropagate()) + { + return NIL; + } + + bool missingOk = false; + ObjectAddress objectAddress = GetObjectAddressFromParseTree((Node *) stmt, missingOk); + + EnsureDependenciesExistOnAllNodes(&objectAddress); + + return NIL; +} + + +/* + * AlterStatisticsSchemaStmtObjectAddress finds the ObjectAddress for the statistics + * that is altered by given AlterObjectSchemaStmt. If missingOk is false and if + * the statistics does not exist, then it errors out. + * + * Never returns NULL, but the objid in the address can be invalid if missingOk + * was set to true. + */ +ObjectAddress +AlterStatisticsSchemaStmtObjectAddress(Node *node, bool missingOk) +{ + AlterObjectSchemaStmt *stmt = castNode(AlterObjectSchemaStmt, node); + + ObjectAddress address = { 0 }; + Value *statName = llast((List *) stmt->object); + Oid statsOid = get_statistics_object_oid(list_make2(makeString(stmt->newschema), + statName), false); + ObjectAddressSet(address, StatisticExtRelationId, statsOid); + + return address; +} + + /* * GetExplicitStatisticsCommandList returns the list of DDL commands to create * statistics that are explicitly created for the table with relationId. See diff --git a/src/backend/distributed/deparser/deparse_statistics_stmts.c b/src/backend/distributed/deparser/deparse_statistics_stmts.c index 117b19709..b085f027f 100644 --- a/src/backend/distributed/deparser/deparse_statistics_stmts.c +++ b/src/backend/distributed/deparser/deparse_statistics_stmts.c @@ -22,11 +22,12 @@ static void AppendCreateStatisticsStmt(StringInfo buf, CreateStatsStmt *stmt); static void AppendDropStatisticsStmt(StringInfo buf, List *nameList, bool ifExists); +static void AppendAlterStatisticsRenameStmt(StringInfo buf, RenameStmt *stmt); +static void AppendAlterStatisticsSchemaStmt(StringInfo buf, AlterObjectSchemaStmt *stmt); 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) @@ -68,6 +69,20 @@ DeparseAlterStatisticsRenameStmt(Node *node) } +char * +DeparseAlterStatisticsSchemaStmt(Node *node) +{ + AlterObjectSchemaStmt *stmt = castNode(AlterObjectSchemaStmt, node); + + StringInfoData str; + initStringInfo(&str); + + AppendAlterStatisticsSchemaStmt(&str, stmt); + + return str.data; +} + + static void AppendCreateStatisticsStmt(StringInfo buf, CreateStatsStmt *stmt) { @@ -110,7 +125,17 @@ static void AppendAlterStatisticsRenameStmt(StringInfo buf, RenameStmt *stmt) { appendStringInfo(buf, "ALTER STATISTICS %s RENAME TO %s", - NameListToQuotedString((List *) stmt->object), stmt->newname); + NameListToQuotedString((List *) stmt->object), quote_identifier( + stmt->newname)); +} + + +static void +AppendAlterStatisticsSchemaStmt(StringInfo buf, AlterObjectSchemaStmt *stmt) +{ + appendStringInfo(buf, "ALTER STATISTICS %s SET SCHEMA %s", + NameListToQuotedString((List *) stmt->object), quote_identifier( + stmt->newschema)); } diff --git a/src/backend/distributed/deparser/qualify_statistics_stmt.c b/src/backend/distributed/deparser/qualify_statistics_stmt.c index 8947f2f5d..eb7d19080 100644 --- a/src/backend/distributed/deparser/qualify_statistics_stmt.c +++ b/src/backend/distributed/deparser/qualify_statistics_stmt.c @@ -99,3 +99,24 @@ QualifyAlterStatisticsRenameStmt(Node *node) renameStmt->object = (Node *) MakeNameListFromRangeVar(stat); } } + + +/* + * QualifyAlterStatisticsSchemaStmt qualifies RenameStmt's with schema name for + * ALTER STATISTICS RENAME statements. + */ +void +QualifyAlterStatisticsSchemaStmt(Node *node) +{ + AlterObjectSchemaStmt *stmt = castNode(AlterObjectSchemaStmt, node); + Assert(stmt->objectType == OBJECT_STATISTIC_EXT); + + List *nameList = (List *) stmt->object; + if (list_length(nameList) == 1) + { + RangeVar *stat = makeRangeVarFromNameList(nameList); + Oid schemaOid = RangeVarGetCreationNamespace(stat); + stat->schemaname = get_namespace_name(schemaOid); + stmt->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 5483966b9..4d0a9104e 100644 --- a/src/backend/distributed/relay/relay_event_utility.c +++ b/src/backend/distributed/relay/relay_event_utility.c @@ -82,14 +82,32 @@ RelayEventExtendNames(Node *parseTree, char *schemaName, uint64 shardId) { AlterObjectSchemaStmt *alterObjectSchemaStmt = (AlterObjectSchemaStmt *) parseTree; - char **relationName = &(alterObjectSchemaStmt->relation->relname); - char **relationSchemaName = &(alterObjectSchemaStmt->relation->schemaname); + ObjectType objectType = alterObjectSchemaStmt->objectType; - /* prefix with schema name if it is not added already */ - SetSchemaNameIfNotExist(relationSchemaName, schemaName); + if (objectType == OBJECT_STATISTIC_EXT) + { + RangeVar *stat = makeRangeVarFromNameList( + (List *) alterObjectSchemaStmt->object); + + /* set schema name and append shard id */ + SetSchemaNameIfNotExist(&stat->schemaname, schemaName); + AppendShardIdToName(&stat->relname, shardId); + + alterObjectSchemaStmt->object = (Node *) MakeNameListFromRangeVar(stat); + } + else + { + char **relationName = &(alterObjectSchemaStmt->relation->relname); + char **relationSchemaName = + &(alterObjectSchemaStmt->relation->schemaname); + + /* prefix with schema name if it is not added already */ + SetSchemaNameIfNotExist(relationSchemaName, schemaName); + + /* append shardId to base relation name */ + AppendShardIdToName(relationName, shardId); + } - /* append shardId to base relation name */ - AppendShardIdToName(relationName, shardId); break; } diff --git a/src/include/distributed/commands.h b/src/include/distributed/commands.h index cde9193d2..054ea5fc0 100644 --- a/src/include/distributed/commands.h +++ b/src/include/distributed/commands.h @@ -283,6 +283,9 @@ extern List * PostprocessCreateStatisticsStmt(Node *node, const char *queryStrin 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 * PreprocessAlterStatisticsSchemaStmt(Node *node, const char *queryString); +extern List * PostprocessAlterStatisticsSchemaStmt(Node *node, const char *queryString); +extern ObjectAddress AlterStatisticsSchemaStmtObjectAddress(Node *node, bool missingOk); 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 9f152e880..59227a658 100644 --- a/src/include/distributed/deparser.h +++ b/src/include/distributed/deparser.h @@ -59,10 +59,12 @@ extern char * DeparseAlterSchemaRenameStmt(Node *stmt); extern char * DeparseCreateStatisticsStmt(Node *node); extern char * DeparseDropStatisticsStmt(List *nameList, bool ifExists); extern char * DeparseAlterStatisticsRenameStmt(Node *node); +extern char * DeparseAlterStatisticsSchemaStmt(Node *node); extern void QualifyCreateStatisticsStmt(Node *node); extern void QualifyDropStatisticsStmt(Node *node); extern void QualifyAlterStatisticsRenameStmt(Node *node); +extern void QualifyAlterStatisticsSchemaStmt(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 0cd0825a4..9516d0b4a 100644 --- a/src/test/regress/expected/propagate_statistics.out +++ b/src/test/regress/expected/propagate_statistics.out @@ -75,7 +75,10 @@ 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; +-- test altering stats schema +CREATE SCHEMA test_alter_schema; +ALTER STATISTICS s7 SET SCHEMA test_alter_schema; +DROP STATISTICS test_alter_schema.s7; \c - - - :worker_1_port SELECT stxname FROM pg_statistic_ext @@ -168,5 +171,6 @@ WHERE stxnamespace IN ( \c - - - :master_port SET client_min_messages TO WARNING; DROP SCHEMA "statistics'Test" CASCADE; +DROP SCHEMA test_alter_schema CASCADE; DROP SCHEMA sc1 CASCADE; DROP SCHEMA sc2 CASCADE; diff --git a/src/test/regress/sql/propagate_statistics.sql b/src/test/regress/sql/propagate_statistics.sql index 7a4dbcc94..ffdd3dd29 100644 --- a/src/test/regress/sql/propagate_statistics.sql +++ b/src/test/regress/sql/propagate_statistics.sql @@ -61,7 +61,11 @@ DROP STATISTICS IF EXISTS s5,s5,s6,s6; CREATE STATISTICS s6 ON a,b FROM test_stats4; DROP STATISTICS s7; ALTER STATISTICS s6 RENAME TO s7; -DROP STATISTICS s7; + +-- test altering stats schema +CREATE SCHEMA test_alter_schema; +ALTER STATISTICS s7 SET SCHEMA test_alter_schema; +DROP STATISTICS test_alter_schema.s7; \c - - - :worker_1_port SELECT stxname @@ -84,5 +88,6 @@ WHERE stxnamespace IN ( \c - - - :master_port SET client_min_messages TO WARNING; DROP SCHEMA "statistics'Test" CASCADE; +DROP SCHEMA test_alter_schema CASCADE; DROP SCHEMA sc1 CASCADE; DROP SCHEMA sc2 CASCADE; From f7c70f9a63f53efb988eef0389946b1c38248ff3 Mon Sep 17 00:00:00 2001 From: Ahmet Gedemenli Date: Wed, 23 Dec 2020 17:45:55 +0300 Subject: [PATCH 3/6] Propagate alter stats target --- .../commands/distribute_object_ops.c | 17 ++++ src/backend/distributed/commands/statistics.c | 43 ++++++++++ .../deparser/deparse_statistics_stmts.c | 33 ++++++++ .../deparser/qualify_statistics_stmt.c | 24 ++++++ .../distributed/relay/relay_event_utility.c | 15 ++++ src/include/distributed/commands.h | 1 + src/include/distributed/deparser.h | 2 + .../regress/expected/propagate_statistics.out | 81 +++++++++++++++++++ src/test/regress/sql/propagate_statistics.sql | 14 ++++ 9 files changed, 230 insertions(+) diff --git a/src/backend/distributed/commands/distribute_object_ops.c b/src/backend/distributed/commands/distribute_object_ops.c index 7e140a13d..258986327 100644 --- a/src/backend/distributed/commands/distribute_object_ops.c +++ b/src/backend/distributed/commands/distribute_object_ops.c @@ -14,6 +14,7 @@ #include "distributed/commands.h" #include "distributed/deparser.h" +#include "distributed/pg_version_constants.h" static DistributeObjectOps NoDistributeOps = { .deparse = NULL, @@ -414,6 +415,15 @@ static DistributeObjectOps Schema_Rename = { .postprocess = NULL, .address = AlterSchemaRenameStmtObjectAddress, }; +#if PG_VERSION_NUM >= PG_VERSION_13 +static DistributeObjectOps Statistics_Alter = { + .deparse = DeparseAlterStatisticsStmt, + .qualify = QualifyAlterStatisticsStmt, + .preprocess = PreprocessAlterStatisticsStmt, + .postprocess = NULL, + .address = NULL, +}; +#endif static DistributeObjectOps Statistics_AlterObjectSchema = { .deparse = DeparseAlterStatisticsSchemaStmt, .qualify = QualifyAlterStatisticsSchemaStmt, @@ -683,6 +693,13 @@ GetDistributeObjectOps(Node *node) return &Any_AlterRoleSet; } +#if PG_VERSION_NUM >= PG_VERSION_13 + case T_AlterStatsStmt: + { + return &Statistics_Alter; + } + +#endif case T_AlterTableStmt: { AlterTableStmt *stmt = castNode(AlterTableStmt, node); diff --git a/src/backend/distributed/commands/statistics.c b/src/backend/distributed/commands/statistics.c index 7db7e06c4..95c63d900 100644 --- a/src/backend/distributed/commands/statistics.c +++ b/src/backend/distributed/commands/statistics.c @@ -318,6 +318,49 @@ AlterStatisticsSchemaStmtObjectAddress(Node *node, bool missingOk) } +#if PG_VERSION_NUM >= PG_VERSION_13 + +/* + * PreprocessAlterStatisticsStmt is called during the planning phase for + * ALTER STATISTICS .. SET STATISTICS command has been executed + * by standard process utility. + */ +List * +PreprocessAlterStatisticsStmt(Node *node, const char *queryString) +{ + AlterStatsStmt *stmt = castNode(AlterStatsStmt, node); + + Oid statsOid = get_statistics_object_oid(stmt->defnames, false); + Oid relationId = GetRelIdByStatsOid(statsOid); + + if (!IsCitusTable(relationId) || !ShouldPropagate()) + { + return NIL; + } + + EnsureCoordinator(); + + QualifyTreeNode((Node *) stmt); + + char *ddlCommand = DeparseTreeNode((Node *) stmt); + + 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; +} + + +#endif + + /* * GetExplicitStatisticsCommandList returns the list of DDL commands to create * statistics that are explicitly created for the table with relationId. See diff --git a/src/backend/distributed/deparser/deparse_statistics_stmts.c b/src/backend/distributed/deparser/deparse_statistics_stmts.c index b085f027f..1473980db 100644 --- a/src/backend/distributed/deparser/deparse_statistics_stmts.c +++ b/src/backend/distributed/deparser/deparse_statistics_stmts.c @@ -24,6 +24,9 @@ static void AppendCreateStatisticsStmt(StringInfo buf, CreateStatsStmt *stmt); static void AppendDropStatisticsStmt(StringInfo buf, List *nameList, bool ifExists); static void AppendAlterStatisticsRenameStmt(StringInfo buf, RenameStmt *stmt); static void AppendAlterStatisticsSchemaStmt(StringInfo buf, AlterObjectSchemaStmt *stmt); +#if PG_VERSION_NUM >= PG_VERSION_13 +static void AppendAlterStatisticsStmt(StringInfo buf, AlterStatsStmt *stmt); +#endif static void AppendStatisticsName(StringInfo buf, CreateStatsStmt *stmt); static void AppendStatTypes(StringInfo buf, CreateStatsStmt *stmt); static void AppendColumnNames(StringInfo buf, CreateStatsStmt *stmt); @@ -83,6 +86,24 @@ DeparseAlterStatisticsSchemaStmt(Node *node) } +#if PG_VERSION_NUM >= PG_VERSION_13 +char * +DeparseAlterStatisticsStmt(Node *node) +{ + AlterStatsStmt *stmt = castNode(AlterStatsStmt, node); + + StringInfoData str; + initStringInfo(&str); + + AppendAlterStatisticsStmt(&str, stmt); + + return str.data; +} + + +#endif + + static void AppendCreateStatisticsStmt(StringInfo buf, CreateStatsStmt *stmt) { @@ -139,6 +160,18 @@ AppendAlterStatisticsSchemaStmt(StringInfo buf, AlterObjectSchemaStmt *stmt) } +#if PG_VERSION_NUM >= PG_VERSION_13 +static void +AppendAlterStatisticsStmt(StringInfo buf, AlterStatsStmt *stmt) +{ + appendStringInfo(buf, "ALTER STATISTICS %s SET STATISTICS %d", NameListToQuotedString( + stmt->defnames), stmt->stxstattarget); +} + + +#endif + + 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 eb7d19080..ad60b42a3 100644 --- a/src/backend/distributed/deparser/qualify_statistics_stmt.c +++ b/src/backend/distributed/deparser/qualify_statistics_stmt.c @@ -120,3 +120,27 @@ QualifyAlterStatisticsSchemaStmt(Node *node) stmt->object = (Node *) MakeNameListFromRangeVar(stat); } } + + +#if PG_VERSION_NUM >= PG_VERSION_13 + +/* + * QualifyAlterStatisticsStmt qualifies AlterObjectSchemaStmt's with schema name for + * ALTER STATISTICS .. SET STATISTICS statements. + */ +void +QualifyAlterStatisticsStmt(Node *node) +{ + AlterStatsStmt *stmt = castNode(AlterStatsStmt, node); + + if (list_length(stmt->defnames) == 1) + { + RangeVar *stat = makeRangeVarFromNameList(stmt->defnames); + Oid schemaOid = RangeVarGetCreationNamespace(stat); + stat->schemaname = get_namespace_name(schemaOid); + stmt->defnames = MakeNameListFromRangeVar(stat); + } +} + + +#endif diff --git a/src/backend/distributed/relay/relay_event_utility.c b/src/backend/distributed/relay/relay_event_utility.c index 4d0a9104e..6db69297b 100644 --- a/src/backend/distributed/relay/relay_event_utility.c +++ b/src/backend/distributed/relay/relay_event_utility.c @@ -111,6 +111,21 @@ RelayEventExtendNames(Node *parseTree, char *schemaName, uint64 shardId) break; } +#if PG_VERSION_NUM >= PG_VERSION_13 + case T_AlterStatsStmt: + { + AlterStatsStmt *alterStatsStmt = (AlterStatsStmt *) parseTree; + RangeVar *stat = makeRangeVarFromNameList(alterStatsStmt->defnames); + + AppendShardIdToName(&stat->relname, shardId); + SetSchemaNameIfNotExist(&stat->schemaname, schemaName); + + alterStatsStmt->defnames = MakeNameListFromRangeVar(stat); + + break; + } +#endif + case T_AlterTableStmt: { /* diff --git a/src/include/distributed/commands.h b/src/include/distributed/commands.h index 054ea5fc0..e25aee2d2 100644 --- a/src/include/distributed/commands.h +++ b/src/include/distributed/commands.h @@ -286,6 +286,7 @@ extern List * PreprocessAlterStatisticsRenameStmt(Node *node, const char *queryS extern List * PreprocessAlterStatisticsSchemaStmt(Node *node, const char *queryString); extern List * PostprocessAlterStatisticsSchemaStmt(Node *node, const char *queryString); extern ObjectAddress AlterStatisticsSchemaStmtObjectAddress(Node *node, bool missingOk); +extern List * PreprocessAlterStatisticsStmt(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 59227a658..7ff42b6e3 100644 --- a/src/include/distributed/deparser.h +++ b/src/include/distributed/deparser.h @@ -60,11 +60,13 @@ extern char * DeparseCreateStatisticsStmt(Node *node); extern char * DeparseDropStatisticsStmt(List *nameList, bool ifExists); extern char * DeparseAlterStatisticsRenameStmt(Node *node); extern char * DeparseAlterStatisticsSchemaStmt(Node *node); +extern char * DeparseAlterStatisticsStmt(Node *node); extern void QualifyCreateStatisticsStmt(Node *node); extern void QualifyDropStatisticsStmt(Node *node); extern void QualifyAlterStatisticsRenameStmt(Node *node); extern void QualifyAlterStatisticsSchemaStmt(Node *node); +extern void QualifyAlterStatisticsStmt(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 9516d0b4a..18367b5d0 100644 --- a/src/test/regress/expected/propagate_statistics.out +++ b/src/test/regress/expected/propagate_statistics.out @@ -79,6 +79,11 @@ ALTER STATISTICS s6 RENAME TO s7; CREATE SCHEMA test_alter_schema; ALTER STATISTICS s7 SET SCHEMA test_alter_schema; DROP STATISTICS test_alter_schema.s7; +-- test altering stats target +ALTER STATISTICS s1 SET STATISTICS 3; +-- since max value for target is 10000, this will automatically be lowered +ALTER STATISTICS s2 SET STATISTICS 999999; +WARNING: lowering statistics target to 10000 \c - - - :worker_1_port SELECT stxname FROM pg_statistic_ext @@ -168,6 +173,82 @@ WHERE stxnamespace IN ( 3 (1 row) +SELECT stxstattarget +FROM pg_statistic_ext +WHERE stxnamespace IN ( + SELECT oid + FROM pg_namespace + WHERE nspname IN ('public', 'statistics''Test', 'sc1', 'sc2') +) +ORDER BY stxstattarget ASC; + stxstattarget +--------------------------------------------------------------------- + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + 3 + 3 + 3 + 3 + 3 + 3 + 3 + 3 + 3 + 3 + 3 + 3 + 3 + 3 + 3 + 3 + 10000 + 10000 + 10000 + 10000 + 10000 + 10000 + 10000 + 10000 + 10000 + 10000 + 10000 + 10000 + 10000 + 10000 + 10000 + 10000 +(64 rows) + \c - - - :master_port SET client_min_messages TO WARNING; DROP SCHEMA "statistics'Test" CASCADE; diff --git a/src/test/regress/sql/propagate_statistics.sql b/src/test/regress/sql/propagate_statistics.sql index ffdd3dd29..dda73c368 100644 --- a/src/test/regress/sql/propagate_statistics.sql +++ b/src/test/regress/sql/propagate_statistics.sql @@ -67,6 +67,11 @@ CREATE SCHEMA test_alter_schema; ALTER STATISTICS s7 SET SCHEMA test_alter_schema; DROP STATISTICS test_alter_schema.s7; +-- test altering stats target +ALTER STATISTICS s1 SET STATISTICS 3; +-- since max value for target is 10000, this will automatically be lowered +ALTER STATISTICS s2 SET STATISTICS 999999; + \c - - - :worker_1_port SELECT stxname FROM pg_statistic_ext @@ -85,6 +90,15 @@ WHERE stxnamespace IN ( WHERE nspname IN ('public', 'statistics''Test', 'sc1', 'sc2') ); +SELECT stxstattarget +FROM pg_statistic_ext +WHERE stxnamespace IN ( + SELECT oid + FROM pg_namespace + WHERE nspname IN ('public', 'statistics''Test', 'sc1', 'sc2') +) +ORDER BY stxstattarget ASC; + \c - - - :master_port SET client_min_messages TO WARNING; DROP SCHEMA "statistics'Test" CASCADE; From 48ca1637a465062f8c5a68e5f7b9205c6eddbbca Mon Sep 17 00:00:00 2001 From: Ahmet Gedemenli Date: Wed, 23 Dec 2020 19:28:41 +0300 Subject: [PATCH 4/6] Propagate alter stats owner --- .../commands/distribute_object_ops.c | 12 ++++++ src/backend/distributed/commands/statistics.c | 40 ++++++++++++++++++- .../deparser/deparse_statistics_stmts.c | 22 ++++++++++ .../deparser/qualify_statistics_stmt.c | 24 ++++++++++- .../distributed/relay/relay_event_utility.c | 17 ++++++++ src/include/distributed/commands.h | 1 + src/include/distributed/deparser.h | 2 + 7 files changed, 114 insertions(+), 4 deletions(-) diff --git a/src/backend/distributed/commands/distribute_object_ops.c b/src/backend/distributed/commands/distribute_object_ops.c index 258986327..dd456ec4d 100644 --- a/src/backend/distributed/commands/distribute_object_ops.c +++ b/src/backend/distributed/commands/distribute_object_ops.c @@ -431,6 +431,13 @@ static DistributeObjectOps Statistics_AlterObjectSchema = { .postprocess = PostprocessAlterStatisticsSchemaStmt, .address = AlterStatisticsSchemaStmtObjectAddress, }; +static DistributeObjectOps Statistics_AlterOwner = { + .deparse = DeparseAlterStatisticsOwnerStmt, + .qualify = QualifyAlterStatisticsOwnerStmt, + .preprocess = PreprocessAlterStatisticsOwnerStmt, + .postprocess = NULL, + .address = NULL, +}; static DistributeObjectOps Statistics_Drop = { .deparse = NULL, .qualify = QualifyDropStatisticsStmt, @@ -666,6 +673,11 @@ GetDistributeObjectOps(Node *node) return &Routine_AlterOwner; } + case OBJECT_STATISTIC_EXT: + { + return &Statistics_AlterOwner; + } + case OBJECT_TYPE: { return &Type_AlterOwner; diff --git a/src/backend/distributed/commands/statistics.c b/src/backend/distributed/commands/statistics.c index 95c63d900..7476b8ca9 100644 --- a/src/backend/distributed/commands/statistics.c +++ b/src/backend/distributed/commands/statistics.c @@ -322,8 +322,7 @@ AlterStatisticsSchemaStmtObjectAddress(Node *node, bool missingOk) /* * PreprocessAlterStatisticsStmt is called during the planning phase for - * ALTER STATISTICS .. SET STATISTICS command has been executed - * by standard process utility. + * ALTER STATISTICS .. SET STATISTICS. */ List * PreprocessAlterStatisticsStmt(Node *node, const char *queryString) @@ -360,6 +359,43 @@ PreprocessAlterStatisticsStmt(Node *node, const char *queryString) #endif +/* + * PreprocessAlterStatisticsOwnerStmt is called during the planning phase for + * ALTER STATISTICS .. OWNER TO. + */ +List * +PreprocessAlterStatisticsOwnerStmt(Node *node, const char *queryString) +{ + AlterOwnerStmt *stmt = castNode(AlterOwnerStmt, node); + Assert(stmt->objectType == OBJECT_STATISTIC_EXT); + + Oid statsOid = get_statistics_object_oid((List *) stmt->object, false); + Oid relationId = GetRelIdByStatsOid(statsOid); + + if (!IsCitusTable(relationId) || !ShouldPropagate()) + { + return NIL; + } + + EnsureCoordinator(); + + QualifyTreeNode((Node *) stmt); + + char *ddlCommand = DeparseTreeNode((Node *) stmt); + + 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 diff --git a/src/backend/distributed/deparser/deparse_statistics_stmts.c b/src/backend/distributed/deparser/deparse_statistics_stmts.c index 1473980db..74350c766 100644 --- a/src/backend/distributed/deparser/deparse_statistics_stmts.c +++ b/src/backend/distributed/deparser/deparse_statistics_stmts.c @@ -27,6 +27,7 @@ static void AppendAlterStatisticsSchemaStmt(StringInfo buf, AlterObjectSchemaStm #if PG_VERSION_NUM >= PG_VERSION_13 static void AppendAlterStatisticsStmt(StringInfo buf, AlterStatsStmt *stmt); #endif +static void AppendAlterStatisticsOwnerStmt(StringInfo buf, AlterOwnerStmt *stmt); static void AppendStatisticsName(StringInfo buf, CreateStatsStmt *stmt); static void AppendStatTypes(StringInfo buf, CreateStatsStmt *stmt); static void AppendColumnNames(StringInfo buf, CreateStatsStmt *stmt); @@ -102,6 +103,19 @@ DeparseAlterStatisticsStmt(Node *node) #endif +char * +DeparseAlterStatisticsOwnerStmt(Node *node) +{ + AlterOwnerStmt *stmt = castNode(AlterOwnerStmt, node); + Assert(stmt->objectType == OBJECT_STATISTIC_EXT); + + StringInfoData str; + initStringInfo(&str); + + AppendAlterStatisticsOwnerStmt(&str, stmt); + + return str.data; +} static void @@ -170,6 +184,14 @@ AppendAlterStatisticsStmt(StringInfo buf, AlterStatsStmt *stmt) #endif +static void +AppendAlterStatisticsOwnerStmt(StringInfo buf, AlterOwnerStmt *stmt) +{ + List *names = (List *) stmt->object; + appendStringInfo(buf, "ALTER STATISTICS %s OWNER TO %s;", NameListToQuotedString( + names), + RoleSpecString(stmt->newowner, true)); +} static void diff --git a/src/backend/distributed/deparser/qualify_statistics_stmt.c b/src/backend/distributed/deparser/qualify_statistics_stmt.c index ad60b42a3..2a8cb1eaa 100644 --- a/src/backend/distributed/deparser/qualify_statistics_stmt.c +++ b/src/backend/distributed/deparser/qualify_statistics_stmt.c @@ -102,7 +102,7 @@ QualifyAlterStatisticsRenameStmt(Node *node) /* - * QualifyAlterStatisticsSchemaStmt qualifies RenameStmt's with schema name for + * QualifyAlterStatisticsSchemaStmt qualifies AlterObjectSchemaStmt's with schema name for * ALTER STATISTICS RENAME statements. */ void @@ -125,7 +125,7 @@ QualifyAlterStatisticsSchemaStmt(Node *node) #if PG_VERSION_NUM >= PG_VERSION_13 /* - * QualifyAlterStatisticsStmt qualifies AlterObjectSchemaStmt's with schema name for + * QualifyAlterStatisticsStmt qualifies AlterStatsStmt's with schema name for * ALTER STATISTICS .. SET STATISTICS statements. */ void @@ -144,3 +144,23 @@ QualifyAlterStatisticsStmt(Node *node) #endif + +/* + * QualifyAlterStatisticsStmt qualifies AlterOwnerStmt's with schema name for + * ALTER STATISTICS .. OWNER TO statements. + */ +void +QualifyAlterStatisticsOwnerStmt(Node *node) +{ + AlterOwnerStmt *stmt = castNode(AlterOwnerStmt, node); + Assert(stmt->objectType == OBJECT_STATISTIC_EXT); + + List *nameList = (List *) stmt->object; + if (list_length(nameList) == 1) + { + RangeVar *stat = makeRangeVarFromNameList(nameList); + Oid schemaOid = RangeVarGetCreationNamespace(stat); + stat->schemaname = get_namespace_name(schemaOid); + stmt->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 6db69297b..6cc8ab1ca 100644 --- a/src/backend/distributed/relay/relay_event_utility.c +++ b/src/backend/distributed/relay/relay_event_utility.c @@ -213,6 +213,23 @@ RelayEventExtendNames(Node *parseTree, char *schemaName, uint64 shardId) break; } + case T_AlterOwnerStmt: + { + AlterOwnerStmt *alterOwnerStmt = castNode(AlterOwnerStmt, parseTree); + + /* we currently extend names in alter owner statements only for statistics */ + Assert(alterOwnerStmt->objectType == OBJECT_STATISTIC_EXT); + + RangeVar *stat = makeRangeVarFromNameList((List *) alterOwnerStmt->object); + + AppendShardIdToName(&stat->relname, shardId); + SetSchemaNameIfNotExist(&stat->schemaname, schemaName); + + alterOwnerStmt->object = (Node *) MakeNameListFromRangeVar(stat); + + break; + } + case T_ClusterStmt: { ClusterStmt *clusterStmt = (ClusterStmt *) parseTree; diff --git a/src/include/distributed/commands.h b/src/include/distributed/commands.h index e25aee2d2..338f3f25c 100644 --- a/src/include/distributed/commands.h +++ b/src/include/distributed/commands.h @@ -287,6 +287,7 @@ extern List * PreprocessAlterStatisticsSchemaStmt(Node *node, const char *queryS extern List * PostprocessAlterStatisticsSchemaStmt(Node *node, const char *queryString); extern ObjectAddress AlterStatisticsSchemaStmtObjectAddress(Node *node, bool missingOk); extern List * PreprocessAlterStatisticsStmt(Node *node, const char *queryString); +extern List * PreprocessAlterStatisticsOwnerStmt(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 7ff42b6e3..7e264544c 100644 --- a/src/include/distributed/deparser.h +++ b/src/include/distributed/deparser.h @@ -61,12 +61,14 @@ extern char * DeparseDropStatisticsStmt(List *nameList, bool ifExists); extern char * DeparseAlterStatisticsRenameStmt(Node *node); extern char * DeparseAlterStatisticsSchemaStmt(Node *node); extern char * DeparseAlterStatisticsStmt(Node *node); +extern char * DeparseAlterStatisticsOwnerStmt(Node *node); extern void QualifyCreateStatisticsStmt(Node *node); extern void QualifyDropStatisticsStmt(Node *node); extern void QualifyAlterStatisticsRenameStmt(Node *node); extern void QualifyAlterStatisticsSchemaStmt(Node *node); extern void QualifyAlterStatisticsStmt(Node *node); +extern void QualifyAlterStatisticsOwnerStmt(Node *node); /* forward declarations for deparse_type_stmts.c */ extern char * DeparseCompositeTypeStmt(Node *stmt); From d4bc17f6f0c8160695d576983d4969376a808a7e Mon Sep 17 00:00:00 2001 From: Ahmet Gedemenli Date: Thu, 24 Dec 2020 13:55:35 +0300 Subject: [PATCH 5/6] Propagate statistics with altered targets --- src/backend/distributed/commands/statistics.c | 63 ++++++++++++- .../deparser/deparse_statistics_stmts.c | 2 +- .../distributed/relay/relay_event_utility.c | 1 - .../regress/expected/propagate_statistics.out | 88 +++++++++++++++---- src/test/regress/sql/propagate_statistics.sql | 12 ++- 5 files changed, 142 insertions(+), 24 deletions(-) diff --git a/src/backend/distributed/commands/statistics.c b/src/backend/distributed/commands/statistics.c index 7476b8ca9..9a1797fc8 100644 --- a/src/backend/distributed/commands/statistics.c +++ b/src/backend/distributed/commands/statistics.c @@ -45,7 +45,9 @@ static List * GetExplicitStatisticsIdList(Oid relationId); static Oid GetRelIdByStatsOid(Oid statsOid); - +#if PG_VERSION_NUM >= PG_VERSION_13 +static char * CreateAlterCommandIfTargetNotDefault(Oid statsOid); +#endif /* * PreprocessCreateStatisticsStmt is called during the planning phase for @@ -311,7 +313,7 @@ AlterStatisticsSchemaStmtObjectAddress(Node *node, bool missingOk) ObjectAddress address = { 0 }; Value *statName = llast((List *) stmt->object); Oid statsOid = get_statistics_object_oid(list_make2(makeString(stmt->newschema), - statName), false); + statName), missingOk); ObjectAddressSet(address, StatisticExtRelationId, statsOid); return address; @@ -406,6 +408,7 @@ List * GetExplicitStatisticsCommandList(Oid relationId) { List *createStatisticsCommandList = NIL; + List *alterStatisticsCommandList = NIL; PushOverrideEmptySearchPath(CurrentMemoryContext); @@ -420,11 +423,25 @@ GetExplicitStatisticsCommandList(Oid relationId) createStatisticsCommandList = lappend( createStatisticsCommandList, makeTableDDLCommandString(createStatisticsCommand)); +#if PG_VERSION_NUM >= PG_VERSION_13 + char *alterStatisticsTargetCommand = CreateAlterCommandIfTargetNotDefault( + statisticsId); + + if (alterStatisticsTargetCommand != NULL) + { + alterStatisticsCommandList = lappend(alterStatisticsCommandList, + makeTableDDLCommandString( + alterStatisticsTargetCommand)); + } +#endif } /* revert back to original search_path */ PopOverrideSearchPath(); + createStatisticsCommandList = list_concat(createStatisticsCommandList, + alterStatisticsCommandList); + return createStatisticsCommandList; } @@ -540,3 +557,45 @@ GetRelIdByStatsOid(Oid statsOid) return statisticsForm->stxrelid; } + + +#if PG_VERSION_NUM >= PG_VERSION_13 + +/* + * CreateAlterCommandIfTargetNotDefault returns an ALTER STATISTICS .. SET STATISTICS + * command if the stats object with given id has a target different than the default one. + * Returns NULL otherwise. + */ +static char * +CreateAlterCommandIfTargetNotDefault(Oid statsOid) +{ + HeapTuple tup = SearchSysCache1(STATEXTOID, ObjectIdGetDatum(statsOid)); + + if (!HeapTupleIsValid(tup)) + { + ereport(WARNING, (errmsg("No stats object found with id: %u", statsOid))); + return NULL; + } + + Form_pg_statistic_ext statisticsForm = (Form_pg_statistic_ext) GETSTRUCT(tup); + ReleaseSysCache(tup); + + if (statisticsForm->stxstattarget == -1) + { + return NULL; + } + + AlterStatsStmt *alterStatsStmt = palloc0(sizeof(AlterStatsStmt)); + + char *schemaName = get_namespace_name(statisticsForm->stxnamespace); + char *statName = NameStr(statisticsForm->stxname); + + alterStatsStmt->type = T_AlterStatsStmt; + alterStatsStmt->stxstattarget = statisticsForm->stxstattarget; + alterStatsStmt->defnames = list_make2(makeString(schemaName), makeString(statName)); + + return DeparseAlterStatisticsStmt((Node *) alterStatsStmt); +} + + +#endif diff --git a/src/backend/distributed/deparser/deparse_statistics_stmts.c b/src/backend/distributed/deparser/deparse_statistics_stmts.c index 74350c766..f4658b0d7 100644 --- a/src/backend/distributed/deparser/deparse_statistics_stmts.c +++ b/src/backend/distributed/deparser/deparse_statistics_stmts.c @@ -188,7 +188,7 @@ static void AppendAlterStatisticsOwnerStmt(StringInfo buf, AlterOwnerStmt *stmt) { List *names = (List *) stmt->object; - appendStringInfo(buf, "ALTER STATISTICS %s OWNER TO %s;", NameListToQuotedString( + appendStringInfo(buf, "ALTER STATISTICS %s OWNER TO %s", NameListToQuotedString( names), RoleSpecString(stmt->newowner, true)); } diff --git a/src/backend/distributed/relay/relay_event_utility.c b/src/backend/distributed/relay/relay_event_utility.c index 6cc8ab1ca..c1f114d79 100644 --- a/src/backend/distributed/relay/relay_event_utility.c +++ b/src/backend/distributed/relay/relay_event_utility.c @@ -223,7 +223,6 @@ RelayEventExtendNames(Node *parseTree, char *schemaName, uint64 shardId) RangeVar *stat = makeRangeVarFromNameList((List *) alterOwnerStmt->object); AppendShardIdToName(&stat->relname, shardId); - SetSchemaNameIfNotExist(&stat->schemaname, schemaName); alterOwnerStmt->object = (Node *) MakeNameListFromRangeVar(stat); diff --git a/src/test/regress/expected/propagate_statistics.out b/src/test/regress/expected/propagate_statistics.out index 18367b5d0..470a92826 100644 --- a/src/test/regress/expected/propagate_statistics.out +++ b/src/test/regress/expected/propagate_statistics.out @@ -75,15 +75,27 @@ 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; +ALTER STATISTICS sc1.st1 RENAME TO st1_new; -- test altering stats schema CREATE SCHEMA test_alter_schema; ALTER STATISTICS s7 SET SCHEMA test_alter_schema; -DROP STATISTICS test_alter_schema.s7; -- test altering stats target ALTER STATISTICS s1 SET STATISTICS 3; -- since max value for target is 10000, this will automatically be lowered ALTER STATISTICS s2 SET STATISTICS 999999; WARNING: lowering statistics target to 10000 +-- test alter target before distribution +CREATE TABLE targettable(a int, b int); +CREATE STATISTICS s8 ON a,b FROM targettable; +ALTER STATISTICS s8 SET STATISTICS 46; +SELECT create_distributed_table('targettable', 'b'); + create_distributed_table +--------------------------------------------------------------------- + +(1 row) + +-- test alter owner +ALTER STATISTICS s8 OWNER TO pg_monitor; \c - - - :worker_1_port SELECT stxname FROM pg_statistic_ext @@ -143,23 +155,39 @@ ORDER BY stxname ASC; s2_980058 s2_980060 s2_980062 - st1_980064 - st1_980066 - st1_980068 - st1_980070 - st1_980072 - st1_980074 - st1_980076 - st1_980078 - st1_980080 - st1_980082 - st1_980084 - st1_980086 - st1_980088 - st1_980090 - st1_980092 - st1_980094 -(64 rows) + s8_980129 + s8_980131 + s8_980133 + s8_980135 + s8_980137 + s8_980139 + s8_980141 + s8_980143 + s8_980145 + s8_980147 + s8_980149 + s8_980151 + s8_980153 + s8_980155 + s8_980157 + s8_980159 + st1_new_980064 + st1_new_980066 + st1_new_980068 + st1_new_980070 + st1_new_980072 + st1_new_980074 + st1_new_980076 + st1_new_980078 + st1_new_980080 + st1_new_980082 + st1_new_980084 + st1_new_980086 + st1_new_980088 + st1_new_980090 + st1_new_980092 + st1_new_980094 +(80 rows) SELECT count(DISTINCT stxnamespace) FROM pg_statistic_ext @@ -231,6 +259,22 @@ ORDER BY stxstattarget ASC; 3 3 3 + 46 + 46 + 46 + 46 + 46 + 46 + 46 + 46 + 46 + 46 + 46 + 46 + 46 + 46 + 46 + 46 10000 10000 10000 @@ -247,7 +291,13 @@ ORDER BY stxstattarget ASC; 10000 10000 10000 -(64 rows) +(80 rows) + +SELECT COUNT(DISTINCT stxowner) FROM pg_statistic_ext; + count +--------------------------------------------------------------------- + 2 +(1 row) \c - - - :master_port SET client_min_messages TO WARNING; diff --git a/src/test/regress/sql/propagate_statistics.sql b/src/test/regress/sql/propagate_statistics.sql index dda73c368..e9b78ee57 100644 --- a/src/test/regress/sql/propagate_statistics.sql +++ b/src/test/regress/sql/propagate_statistics.sql @@ -61,16 +61,24 @@ DROP STATISTICS IF EXISTS s5,s5,s6,s6; CREATE STATISTICS s6 ON a,b FROM test_stats4; DROP STATISTICS s7; ALTER STATISTICS s6 RENAME TO s7; +ALTER STATISTICS sc1.st1 RENAME TO st1_new; -- test altering stats schema CREATE SCHEMA test_alter_schema; ALTER STATISTICS s7 SET SCHEMA test_alter_schema; -DROP STATISTICS test_alter_schema.s7; -- test altering stats target ALTER STATISTICS s1 SET STATISTICS 3; -- since max value for target is 10000, this will automatically be lowered ALTER STATISTICS s2 SET STATISTICS 999999; +-- test alter target before distribution +CREATE TABLE targettable(a int, b int); +CREATE STATISTICS s8 ON a,b FROM targettable; +ALTER STATISTICS s8 SET STATISTICS 46; +SELECT create_distributed_table('targettable', 'b'); + +-- test alter owner +ALTER STATISTICS s8 OWNER TO pg_monitor; \c - - - :worker_1_port SELECT stxname @@ -99,6 +107,8 @@ WHERE stxnamespace IN ( ) ORDER BY stxstattarget ASC; +SELECT COUNT(DISTINCT stxowner) FROM pg_statistic_ext; + \c - - - :master_port SET client_min_messages TO WARNING; DROP SCHEMA "statistics'Test" CASCADE; From 5af585269a8de0119ff711d34d8b891e95c42b90 Mon Sep 17 00:00:00 2001 From: Ahmet Gedemenli Date: Thu, 24 Dec 2020 17:09:59 +0300 Subject: [PATCH 6/6] Add separate pg13 test for stats targets --- src/backend/distributed/commands/statistics.c | 74 +++++++-- .../deparser/deparse_statistics_stmts.c | 4 +- .../distributed/relay/relay_event_utility.c | 4 +- .../expected/pg13_propagate_statistics.out | 112 ++++++++++++++ .../expected/pg13_propagate_statistics_0.out | 6 + .../regress/expected/propagate_statistics.out | 143 ++++-------------- src/test/regress/multi_schedule | 1 + .../regress/sql/pg13_propagate_statistics.sql | 45 ++++++ src/test/regress/sql/propagate_statistics.sql | 24 +-- 9 files changed, 265 insertions(+), 148 deletions(-) create mode 100644 src/test/regress/expected/pg13_propagate_statistics.out create mode 100644 src/test/regress/expected/pg13_propagate_statistics_0.out create mode 100644 src/test/regress/sql/pg13_propagate_statistics.sql diff --git a/src/backend/distributed/commands/statistics.c b/src/backend/distributed/commands/statistics.c index 9a1797fc8..c922a6f31 100644 --- a/src/backend/distributed/commands/statistics.c +++ b/src/backend/distributed/commands/statistics.c @@ -37,6 +37,7 @@ #include "distributed/relation_access_tracking.h" #include "distributed/resource_lock.h" #include "distributed/worker_transaction.h" +#include "miscadmin.h" #include "utils/builtins.h" #include "utils/fmgroids.h" #include "utils/lsyscache.h" @@ -45,6 +46,7 @@ static List * GetExplicitStatisticsIdList(Oid relationId); static Oid GetRelIdByStatsOid(Oid statsOid); +static char * CreateAlterCommandIfOwnerNotDefault(Oid statsOid); #if PG_VERSION_NUM >= PG_VERSION_13 static char * CreateAlterCommandIfTargetNotDefault(Oid statsOid); #endif @@ -420,20 +422,33 @@ GetExplicitStatisticsCommandList(Oid relationId) char *createStatisticsCommand = pg_get_statisticsobj_worker(statisticsId, false); - createStatisticsCommandList = lappend( - createStatisticsCommandList, - makeTableDDLCommandString(createStatisticsCommand)); + createStatisticsCommandList = + lappend(createStatisticsCommandList, + makeTableDDLCommandString(createStatisticsCommand)); #if PG_VERSION_NUM >= PG_VERSION_13 - char *alterStatisticsTargetCommand = CreateAlterCommandIfTargetNotDefault( - statisticsId); + + /* we need to alter stats' target if it's getting distributed after creation */ + char *alterStatisticsTargetCommand = + CreateAlterCommandIfTargetNotDefault(statisticsId); if (alterStatisticsTargetCommand != NULL) { - alterStatisticsCommandList = lappend(alterStatisticsCommandList, - makeTableDDLCommandString( - alterStatisticsTargetCommand)); + alterStatisticsCommandList = + lappend(alterStatisticsCommandList, + makeTableDDLCommandString(alterStatisticsTargetCommand)); } #endif + + /* we need to alter stats' owner if it's getting distributed after creation */ + char *alterStatisticsOwnerCommand = + CreateAlterCommandIfOwnerNotDefault(statisticsId); + + if (alterStatisticsOwnerCommand != NULL) + { + alterStatisticsCommandList = + lappend(alterStatisticsCommandList, + makeTableDDLCommandString(alterStatisticsOwnerCommand)); + } } /* revert back to original search_path */ @@ -559,6 +574,46 @@ GetRelIdByStatsOid(Oid statsOid) } +/* + * CreateAlterCommandIfOwnerNotDefault returns an ALTER STATISTICS .. OWNER TO + * command if the stats object with given id has an owner different than the default one. + * Returns NULL otherwise. + */ +static char * +CreateAlterCommandIfOwnerNotDefault(Oid statsOid) +{ + HeapTuple tup = SearchSysCache1(STATEXTOID, ObjectIdGetDatum(statsOid)); + + if (!HeapTupleIsValid(tup)) + { + ereport(WARNING, (errmsg("No stats object found with id: %u", statsOid))); + return NULL; + } + + Form_pg_statistic_ext statisticsForm = (Form_pg_statistic_ext) GETSTRUCT(tup); + ReleaseSysCache(tup); + + if (statisticsForm->stxowner == GetUserId()) + { + return NULL; + } + + char *schemaName = get_namespace_name(statisticsForm->stxnamespace); + char *statName = NameStr(statisticsForm->stxname); + char *ownerName = GetUserNameFromId(statisticsForm->stxowner, false); + + StringInfoData str; + initStringInfo(&str); + + appendStringInfo(&str, "ALTER STATISTICS %s OWNER TO %s", + NameListToQuotedString(list_make2(makeString(schemaName), + makeString(statName))), + quote_identifier(ownerName)); + + return str.data; +} + + #if PG_VERSION_NUM >= PG_VERSION_13 /* @@ -585,12 +640,11 @@ CreateAlterCommandIfTargetNotDefault(Oid statsOid) return NULL; } - AlterStatsStmt *alterStatsStmt = palloc0(sizeof(AlterStatsStmt)); + AlterStatsStmt *alterStatsStmt = makeNode(AlterStatsStmt); char *schemaName = get_namespace_name(statisticsForm->stxnamespace); char *statName = NameStr(statisticsForm->stxname); - alterStatsStmt->type = T_AlterStatsStmt; alterStatsStmt->stxstattarget = statisticsForm->stxstattarget; alterStatsStmt->defnames = list_make2(makeString(schemaName), makeString(statName)); diff --git a/src/backend/distributed/deparser/deparse_statistics_stmts.c b/src/backend/distributed/deparser/deparse_statistics_stmts.c index f4658b0d7..125d4494f 100644 --- a/src/backend/distributed/deparser/deparse_statistics_stmts.c +++ b/src/backend/distributed/deparser/deparse_statistics_stmts.c @@ -188,8 +188,8 @@ static void AppendAlterStatisticsOwnerStmt(StringInfo buf, AlterOwnerStmt *stmt) { List *names = (List *) stmt->object; - appendStringInfo(buf, "ALTER STATISTICS %s OWNER TO %s", NameListToQuotedString( - names), + appendStringInfo(buf, "ALTER STATISTICS %s OWNER TO %s", + NameListToQuotedString(names), RoleSpecString(stmt->newowner, true)); } diff --git a/src/backend/distributed/relay/relay_event_utility.c b/src/backend/distributed/relay/relay_event_utility.c index c1f114d79..9e1ca2865 100644 --- a/src/backend/distributed/relay/relay_event_utility.c +++ b/src/backend/distributed/relay/relay_event_utility.c @@ -89,8 +89,7 @@ RelayEventExtendNames(Node *parseTree, char *schemaName, uint64 shardId) RangeVar *stat = makeRangeVarFromNameList( (List *) alterObjectSchemaStmt->object); - /* set schema name and append shard id */ - SetSchemaNameIfNotExist(&stat->schemaname, schemaName); + /* append shard id */ AppendShardIdToName(&stat->relname, shardId); alterObjectSchemaStmt->object = (Node *) MakeNameListFromRangeVar(stat); @@ -118,7 +117,6 @@ RelayEventExtendNames(Node *parseTree, char *schemaName, uint64 shardId) RangeVar *stat = makeRangeVarFromNameList(alterStatsStmt->defnames); AppendShardIdToName(&stat->relname, shardId); - SetSchemaNameIfNotExist(&stat->schemaname, schemaName); alterStatsStmt->defnames = MakeNameListFromRangeVar(stat); diff --git a/src/test/regress/expected/pg13_propagate_statistics.out b/src/test/regress/expected/pg13_propagate_statistics.out new file mode 100644 index 000000000..c75eb333f --- /dev/null +++ b/src/test/regress/expected/pg13_propagate_statistics.out @@ -0,0 +1,112 @@ +SHOW server_version \gset +SELECT substring(:'server_version', '\d+')::int > 12 AS server_version_above_twelve +\gset +\if :server_version_above_twelve +\else +\q +\endif +CREATE SCHEMA "statistics'TestTarget"; +SET search_path TO "statistics'TestTarget"; +SET citus.next_shard_id TO 980000; +SET client_min_messages TO WARNING; +SET citus.shard_count TO 32; +SET citus.shard_replication_factor TO 1; +CREATE TABLE t1 (a int, b int); +CREATE STATISTICS s1 ON a,b FROM t1; +CREATE STATISTICS s2 ON a,b FROM t1; +CREATE STATISTICS s3 ON a,b FROM t1; +CREATE STATISTICS s4 ON a,b FROM t1; +-- test altering stats target +-- test alter target before distribution +ALTER STATISTICS s1 SET STATISTICS 3; +-- since max value for target is 10000, this will automatically be lowered +ALTER STATISTICS s2 SET STATISTICS 999999; +WARNING: lowering statistics target to 10000 +SELECT create_distributed_table('t1', 'b'); + create_distributed_table +--------------------------------------------------------------------- + +(1 row) + +-- test alter target before distribution +ALTER STATISTICS s3 SET STATISTICS 46; +\c - - - :worker_1_port +SELECT stxstattarget, stxrelid::regclass +FROM pg_statistic_ext +WHERE stxnamespace IN ( + SELECT oid + FROM pg_namespace + WHERE nspname IN ('statistics''TestTarget') +) +ORDER BY stxstattarget, stxrelid::regclass ASC; + stxstattarget | stxrelid +--------------------------------------------------------------------- + -1 | "statistics'TestTarget".t1_980000 + -1 | "statistics'TestTarget".t1_980002 + -1 | "statistics'TestTarget".t1_980004 + -1 | "statistics'TestTarget".t1_980006 + -1 | "statistics'TestTarget".t1_980008 + -1 | "statistics'TestTarget".t1_980010 + -1 | "statistics'TestTarget".t1_980012 + -1 | "statistics'TestTarget".t1_980014 + -1 | "statistics'TestTarget".t1_980016 + -1 | "statistics'TestTarget".t1_980018 + -1 | "statistics'TestTarget".t1_980020 + -1 | "statistics'TestTarget".t1_980022 + -1 | "statistics'TestTarget".t1_980024 + -1 | "statistics'TestTarget".t1_980026 + -1 | "statistics'TestTarget".t1_980028 + -1 | "statistics'TestTarget".t1_980030 + 3 | "statistics'TestTarget".t1_980000 + 3 | "statistics'TestTarget".t1_980002 + 3 | "statistics'TestTarget".t1_980004 + 3 | "statistics'TestTarget".t1_980006 + 3 | "statistics'TestTarget".t1_980008 + 3 | "statistics'TestTarget".t1_980010 + 3 | "statistics'TestTarget".t1_980012 + 3 | "statistics'TestTarget".t1_980014 + 3 | "statistics'TestTarget".t1_980016 + 3 | "statistics'TestTarget".t1_980018 + 3 | "statistics'TestTarget".t1_980020 + 3 | "statistics'TestTarget".t1_980022 + 3 | "statistics'TestTarget".t1_980024 + 3 | "statistics'TestTarget".t1_980026 + 3 | "statistics'TestTarget".t1_980028 + 3 | "statistics'TestTarget".t1_980030 + 46 | "statistics'TestTarget".t1_980000 + 46 | "statistics'TestTarget".t1_980002 + 46 | "statistics'TestTarget".t1_980004 + 46 | "statistics'TestTarget".t1_980006 + 46 | "statistics'TestTarget".t1_980008 + 46 | "statistics'TestTarget".t1_980010 + 46 | "statistics'TestTarget".t1_980012 + 46 | "statistics'TestTarget".t1_980014 + 46 | "statistics'TestTarget".t1_980016 + 46 | "statistics'TestTarget".t1_980018 + 46 | "statistics'TestTarget".t1_980020 + 46 | "statistics'TestTarget".t1_980022 + 46 | "statistics'TestTarget".t1_980024 + 46 | "statistics'TestTarget".t1_980026 + 46 | "statistics'TestTarget".t1_980028 + 46 | "statistics'TestTarget".t1_980030 + 10000 | "statistics'TestTarget".t1_980000 + 10000 | "statistics'TestTarget".t1_980002 + 10000 | "statistics'TestTarget".t1_980004 + 10000 | "statistics'TestTarget".t1_980006 + 10000 | "statistics'TestTarget".t1_980008 + 10000 | "statistics'TestTarget".t1_980010 + 10000 | "statistics'TestTarget".t1_980012 + 10000 | "statistics'TestTarget".t1_980014 + 10000 | "statistics'TestTarget".t1_980016 + 10000 | "statistics'TestTarget".t1_980018 + 10000 | "statistics'TestTarget".t1_980020 + 10000 | "statistics'TestTarget".t1_980022 + 10000 | "statistics'TestTarget".t1_980024 + 10000 | "statistics'TestTarget".t1_980026 + 10000 | "statistics'TestTarget".t1_980028 + 10000 | "statistics'TestTarget".t1_980030 +(64 rows) + +\c - - - :master_port +SET client_min_messages TO WARNING; +DROP SCHEMA "statistics'TestTarget" CASCADE; diff --git a/src/test/regress/expected/pg13_propagate_statistics_0.out b/src/test/regress/expected/pg13_propagate_statistics_0.out new file mode 100644 index 000000000..e25fbb82d --- /dev/null +++ b/src/test/regress/expected/pg13_propagate_statistics_0.out @@ -0,0 +1,6 @@ +SHOW server_version \gset +SELECT substring(:'server_version', '\d+')::int > 12 AS server_version_above_twelve +\gset +\if :server_version_above_twelve +\else +\q diff --git a/src/test/regress/expected/propagate_statistics.out b/src/test/regress/expected/propagate_statistics.out index 470a92826..80e501fff 100644 --- a/src/test/regress/expected/propagate_statistics.out +++ b/src/test/regress/expected/propagate_statistics.out @@ -79,23 +79,18 @@ ALTER STATISTICS sc1.st1 RENAME TO st1_new; -- test altering stats schema CREATE SCHEMA test_alter_schema; ALTER STATISTICS s7 SET SCHEMA test_alter_schema; --- test altering stats target -ALTER STATISTICS s1 SET STATISTICS 3; --- since max value for target is 10000, this will automatically be lowered -ALTER STATISTICS s2 SET STATISTICS 999999; -WARNING: lowering statistics target to 10000 --- test alter target before distribution -CREATE TABLE targettable(a int, b int); -CREATE STATISTICS s8 ON a,b FROM targettable; -ALTER STATISTICS s8 SET STATISTICS 46; -SELECT create_distributed_table('targettable', 'b'); +-- test alter owner +ALTER STATISTICS sc2."neW'Stat" OWNER TO pg_monitor; +-- test alter owner before distribution +CREATE TABLE ownertest(a int, b int); +CREATE STATISTICS sc1.s9 ON a,b FROM ownertest; +ALTER STATISTICS sc1.s9 OWNER TO pg_signal_backend; +SELECT create_distributed_table('ownertest','a'); create_distributed_table --------------------------------------------------------------------- (1 row) --- test alter owner -ALTER STATISTICS s8 OWNER TO pg_monitor; \c - - - :worker_1_port SELECT stxname FROM pg_statistic_ext @@ -155,22 +150,22 @@ ORDER BY stxname ASC; s2_980058 s2_980060 s2_980062 - s8_980129 - s8_980131 - s8_980133 - s8_980135 - s8_980137 - s8_980139 - s8_980141 - s8_980143 - s8_980145 - s8_980147 - s8_980149 - s8_980151 - s8_980153 - s8_980155 - s8_980157 - s8_980159 + s9_980129 + s9_980131 + s9_980133 + s9_980135 + s9_980137 + s9_980139 + s9_980141 + s9_980143 + s9_980145 + s9_980147 + s9_980149 + s9_980151 + s9_980153 + s9_980155 + s9_980157 + s9_980159 st1_new_980064 st1_new_980066 st1_new_980068 @@ -201,102 +196,16 @@ WHERE stxnamespace IN ( 3 (1 row) -SELECT stxstattarget +SELECT COUNT(DISTINCT stxowner) FROM pg_statistic_ext WHERE stxnamespace IN ( SELECT oid FROM pg_namespace WHERE nspname IN ('public', 'statistics''Test', 'sc1', 'sc2') -) -ORDER BY stxstattarget ASC; - stxstattarget ---------------------------------------------------------------------- - -1 - -1 - -1 - -1 - -1 - -1 - -1 - -1 - -1 - -1 - -1 - -1 - -1 - -1 - -1 - -1 - -1 - -1 - -1 - -1 - -1 - -1 - -1 - -1 - -1 - -1 - -1 - -1 - -1 - -1 - -1 - -1 - 3 - 3 - 3 - 3 - 3 - 3 - 3 - 3 - 3 - 3 - 3 - 3 - 3 - 3 - 3 - 3 - 46 - 46 - 46 - 46 - 46 - 46 - 46 - 46 - 46 - 46 - 46 - 46 - 46 - 46 - 46 - 46 - 10000 - 10000 - 10000 - 10000 - 10000 - 10000 - 10000 - 10000 - 10000 - 10000 - 10000 - 10000 - 10000 - 10000 - 10000 - 10000 -(80 rows) - -SELECT COUNT(DISTINCT stxowner) FROM pg_statistic_ext; +); count --------------------------------------------------------------------- - 2 + 3 (1 row) \c - - - :master_port diff --git a/src/test/regress/multi_schedule b/src/test/regress/multi_schedule index 5f862dc71..8a65fb475 100644 --- a/src/test/regress/multi_schedule +++ b/src/test/regress/multi_schedule @@ -94,6 +94,7 @@ test: tableam # Tests for statistics propagation # ---------- test: propagate_statistics +test: pg13_propagate_statistics # ---------- # Miscellaneous tests to check our query planning behavior diff --git a/src/test/regress/sql/pg13_propagate_statistics.sql b/src/test/regress/sql/pg13_propagate_statistics.sql new file mode 100644 index 000000000..9716d3289 --- /dev/null +++ b/src/test/regress/sql/pg13_propagate_statistics.sql @@ -0,0 +1,45 @@ +SHOW server_version \gset +SELECT substring(:'server_version', '\d+')::int > 12 AS server_version_above_twelve +\gset +\if :server_version_above_twelve +\else +\q +\endif + +CREATE SCHEMA "statistics'TestTarget"; +SET search_path TO "statistics'TestTarget"; +SET citus.next_shard_id TO 980000; +SET client_min_messages TO WARNING; +SET citus.shard_count TO 32; +SET citus.shard_replication_factor TO 1; + +CREATE TABLE t1 (a int, b int); +CREATE STATISTICS s1 ON a,b FROM t1; +CREATE STATISTICS s2 ON a,b FROM t1; +CREATE STATISTICS s3 ON a,b FROM t1; +CREATE STATISTICS s4 ON a,b FROM t1; + +-- test altering stats target +-- test alter target before distribution +ALTER STATISTICS s1 SET STATISTICS 3; +-- since max value for target is 10000, this will automatically be lowered +ALTER STATISTICS s2 SET STATISTICS 999999; + +SELECT create_distributed_table('t1', 'b'); + +-- test alter target before distribution +ALTER STATISTICS s3 SET STATISTICS 46; + +\c - - - :worker_1_port +SELECT stxstattarget, stxrelid::regclass +FROM pg_statistic_ext +WHERE stxnamespace IN ( + SELECT oid + FROM pg_namespace + WHERE nspname IN ('statistics''TestTarget') +) +ORDER BY stxstattarget, stxrelid::regclass ASC; + +\c - - - :master_port +SET client_min_messages TO WARNING; +DROP SCHEMA "statistics'TestTarget" CASCADE; diff --git a/src/test/regress/sql/propagate_statistics.sql b/src/test/regress/sql/propagate_statistics.sql index e9b78ee57..8a0372cf7 100644 --- a/src/test/regress/sql/propagate_statistics.sql +++ b/src/test/regress/sql/propagate_statistics.sql @@ -67,18 +67,13 @@ ALTER STATISTICS sc1.st1 RENAME TO st1_new; CREATE SCHEMA test_alter_schema; ALTER STATISTICS s7 SET SCHEMA test_alter_schema; --- test altering stats target -ALTER STATISTICS s1 SET STATISTICS 3; --- since max value for target is 10000, this will automatically be lowered -ALTER STATISTICS s2 SET STATISTICS 999999; --- test alter target before distribution -CREATE TABLE targettable(a int, b int); -CREATE STATISTICS s8 ON a,b FROM targettable; -ALTER STATISTICS s8 SET STATISTICS 46; -SELECT create_distributed_table('targettable', 'b'); - -- test alter owner -ALTER STATISTICS s8 OWNER TO pg_monitor; +ALTER STATISTICS sc2."neW'Stat" OWNER TO pg_monitor; +-- test alter owner before distribution +CREATE TABLE ownertest(a int, b int); +CREATE STATISTICS sc1.s9 ON a,b FROM ownertest; +ALTER STATISTICS sc1.s9 OWNER TO pg_signal_backend; +SELECT create_distributed_table('ownertest','a'); \c - - - :worker_1_port SELECT stxname @@ -98,16 +93,13 @@ WHERE stxnamespace IN ( WHERE nspname IN ('public', 'statistics''Test', 'sc1', 'sc2') ); -SELECT stxstattarget +SELECT COUNT(DISTINCT stxowner) FROM pg_statistic_ext WHERE stxnamespace IN ( SELECT oid FROM pg_namespace WHERE nspname IN ('public', 'statistics''Test', 'sc1', 'sc2') -) -ORDER BY stxstattarget ASC; - -SELECT COUNT(DISTINCT stxowner) FROM pg_statistic_ext; +); \c - - - :master_port SET client_min_messages TO WARNING;