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;