From d4bc17f6f0c8160695d576983d4969376a808a7e Mon Sep 17 00:00:00 2001 From: Ahmet Gedemenli Date: Thu, 24 Dec 2020 13:55:35 +0300 Subject: [PATCH] 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;