Add dependencies for stat schemas

pull/4395/head
Ahmet Gedemenli 2020-12-18 16:44:10 +03:00
parent 6c0465566a
commit 770d3da1ca
6 changed files with 173 additions and 29 deletions

View File

@ -144,10 +144,6 @@ GetExplicitStatisticsCommandList(Oid relationId)
Oid statisticsId = InvalidOid;
foreach_oid(statisticsId, statisticsIdList)
{
ObjectAddress address = { 0 };
ObjectAddressSet(address, StatisticExtRelationId, statisticsId);
EnsureDependenciesExistOnAllNodes(&address);
char *createStatisticsCommand = pg_get_statisticsobj_worker(statisticsId, false);
createStatisticsCommandList = lappend(
@ -162,6 +158,51 @@ GetExplicitStatisticsCommandList(Oid relationId)
}
/*
* GetExplicitStatisticsSchemaIdList returns the list of schema ids of statistics'
* which are created on relation with given relation id.
*/
List *
GetExplicitStatisticsSchemaIdList(Oid relationId)
{
List *schemaIdList = NIL;
Relation pgStatistics = table_open(StatisticExtRelationId, AccessShareLock);
int scanKeyCount = 1;
ScanKeyData scanKey[1];
ScanKeyInit(&scanKey[0], Anum_pg_statistic_ext_stxrelid,
BTEqualStrategyNumber, F_OIDEQ, relationId);
bool useIndex = true;
SysScanDesc scanDescriptor = systable_beginscan(pgStatistics,
StatisticExtRelidIndexId,
useIndex, NULL, scanKeyCount,
scanKey);
HeapTuple heapTuple = systable_getnext(scanDescriptor);
while (HeapTupleIsValid(heapTuple))
{
FormData_pg_statistic_ext *statisticsForm =
(FormData_pg_statistic_ext *) GETSTRUCT(heapTuple);
Oid schemaId = statisticsForm->stxnamespace;
if (!list_member_oid(schemaIdList, schemaId))
{
schemaIdList = lappend_oid(schemaIdList, schemaId);
}
heapTuple = systable_getnext(scanDescriptor);
}
systable_endscan(scanDescriptor);
table_close(pgStatistics, NoLock);
return schemaIdList;
}
/*
* GetExplicitStatisticsIdList returns a list of OIDs corresponding to the statistics
* that are explicitly created on the relation with relationId. That means,

View File

@ -258,7 +258,7 @@ PreprocessCreateEnumStmt(Node *node, const char *queryString)
QualifyTreeNode(node);
/* reconstruct creation statement in a portable fashion */
const char *createEnumStmtSql = DeparseTreeNode((Node *) node);
const char *createEnumStmtSql = DeparseCreateEnumStmt(node);
createEnumStmtSql = WrapCreateOrReplace(createEnumStmtSql);
/*

View File

@ -21,6 +21,7 @@
#include "catalog/indexing.h"
#include "catalog/pg_class.h"
#include "catalog/pg_depend.h"
#include "catalog/pg_namespace.h"
#include "catalog/pg_proc_d.h"
#include "catalog/pg_rewrite.h"
#include "catalog/pg_rewrite_d.h"
@ -119,6 +120,7 @@ typedef struct ViewDependencyNode
static List * GetRelationTriggerFunctionDepencyList(Oid relationId);
static List * GetRelationStatsSchemaDependencyList(Oid relationId);
static DependencyDefinition * CreateObjectAddressDependencyDef(Oid classId, Oid objectId);
static ObjectAddress DependencyDefinitionObjectAddress(DependencyDefinition *definition);
@ -926,6 +928,17 @@ ExpandCitusSupportedTypes(ObjectAddressCollector *collector, ObjectAddress targe
List *triggerFunctionDepencyList =
GetRelationTriggerFunctionDepencyList(relationId);
result = list_concat(result, triggerFunctionDepencyList);
/*
* Statistics' both depend to the relations and to the schemas they belong
* to. Also, pg_depend records dependencies from statistics to their schemas
* but not from relations to their statistics' schemas. Given above two,
* we directly expand dependencies for the relations to schemas of
* statistics.
*/
List *statisticsSchemaDependencyList =
GetRelationStatsSchemaDependencyList(relationId);
result = list_concat(result, statisticsSchemaDependencyList);
}
default:
@ -938,6 +951,28 @@ ExpandCitusSupportedTypes(ObjectAddressCollector *collector, ObjectAddress targe
}
/*
* GetRelationStatsSchemaDependencyList returns a list of DependencyDefinition
* objects for the schemas that statistics' of the relation with relationId depends.
*/
static List *
GetRelationStatsSchemaDependencyList(Oid relationId)
{
List *dependencyList = NIL;
List *schemaIds = GetExplicitStatisticsSchemaIdList(relationId);
Oid schemaId = InvalidOid;
foreach_oid(schemaId, schemaIds)
{
DependencyDefinition *dependency =
CreateObjectAddressDependencyDef(NamespaceRelationId, schemaId);
dependencyList = lappend(dependencyList, dependency);
}
return dependencyList;
}
/*
* GetRelationTriggerFunctionDepencyList returns a list of DependencyDefinition
* objects for the functions that triggers of the relation with relationId depends.

View File

@ -244,6 +244,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 * GetExplicitStatisticsCommandList(Oid relationId);
extern List * GetExplicitStatisticsSchemaIdList(Oid relationId);
/* subscription.c - forward declarations */
extern Node * ProcessCreateSubscriptionStmt(CreateSubscriptionStmt *createSubStmt);

View File

@ -1,5 +1,5 @@
CREATE SCHEMA "statistics'test";
SET search_path TO "statistics'test";
CREATE SCHEMA "statistics'Test";
SET search_path TO "statistics'Test";
SET citus.next_shard_id TO 980000;
SET client_min_messages TO WARNING;
SET citus.shard_count TO 32;
@ -17,12 +17,12 @@ SELECT create_distributed_table('test_stats', 'a');
CREATE STATISTICS s1 (dependencies) ON a, b FROM test_stats;
-- test for distributing an already existing statistics
CREATE TABLE test_stats2 (
CREATE TABLE "test'stats2" (
a int,
b int
);
CREATE STATISTICS s2 (dependencies) ON a, b FROM test_stats2;
SELECT create_distributed_table('test_stats2', 'a');
CREATE STATISTICS s2 (dependencies) ON a, b FROM "test'stats2";
SELECT create_distributed_table('test''stats2', 'a');
create_distributed_table
---------------------------------------------------------------------
@ -30,18 +30,54 @@ SELECT create_distributed_table('test_stats2', 'a');
-- test when stats is on a different schema
CREATE SCHEMA sc1;
CREATE TABLE tbl (a int, b int);
CREATE TABLE tbl (a int, "B" text);
SELECT create_distributed_table ('tbl', 'a');
create_distributed_table
---------------------------------------------------------------------
(1 row)
CREATE STATISTICS sc1.st1 ON a, b FROM tbl;
\c - - - :worker_1_port
SELECT stxname FROM pg_statistic_ext ORDER BY stxname ASC;
stxname
CREATE STATISTICS sc1.st1 ON a, "B" FROM tbl;
-- test distributing table with already created stats on a new schema
CREATE TABLE test_stats3 (
a int,
b int
);
CREATE SCHEMA sc2;
CREATE STATISTICS sc2."neW'Stat" ON a,b FROM test_stats3;
SELECT create_distributed_table ('test_stats3','a');
create_distributed_table
---------------------------------------------------------------------
(1 row)
\c - - - :worker_1_port
SELECT stxname
FROM pg_statistic_ext
WHERE stxnamespace IN (
SELECT oid
FROM pg_namespace
WHERE nspname IN ('public', 'statistics''Test', 'sc1', 'sc2')
)
ORDER BY stxname ASC;
stxname
---------------------------------------------------------------------
neW'Stat_980096
neW'Stat_980098
neW'Stat_980100
neW'Stat_980102
neW'Stat_980104
neW'Stat_980106
neW'Stat_980108
neW'Stat_980110
neW'Stat_980112
neW'Stat_980114
neW'Stat_980116
neW'Stat_980118
neW'Stat_980120
neW'Stat_980122
neW'Stat_980124
neW'Stat_980126
s1_980000
s1_980002
s1_980004
@ -90,15 +126,22 @@ SELECT stxname FROM pg_statistic_ext ORDER BY stxname ASC;
st1_980090
st1_980092
st1_980094
(48 rows)
(64 rows)
SELECT count(DISTINCT stxnamespace) FROM pg_statistic_ext;
SELECT count(DISTINCT stxnamespace)
FROM pg_statistic_ext
WHERE stxnamespace IN (
SELECT oid
FROM pg_namespace
WHERE nspname IN ('public', 'statistics''Test', 'sc1', 'sc2')
);
count
---------------------------------------------------------------------
2
3
(1 row)
\c - - - :master_port
SET client_min_messages TO WARNING;
DROP SCHEMA "statistics'test" CASCADE;
DROP SCHEMA "statistics'Test" CASCADE;
DROP SCHEMA sc1 CASCADE;
DROP SCHEMA sc2 CASCADE;

View File

@ -1,6 +1,6 @@
CREATE SCHEMA "statistics'test";
CREATE SCHEMA "statistics'Test";
SET search_path TO "statistics'test";
SET search_path TO "statistics'Test";
SET citus.next_shard_id TO 980000;
SET client_min_messages TO WARNING;
SET citus.shard_count TO 32;
@ -17,27 +17,51 @@ SELECT create_distributed_table('test_stats', 'a');
CREATE STATISTICS s1 (dependencies) ON a, b FROM test_stats;
-- test for distributing an already existing statistics
CREATE TABLE test_stats2 (
CREATE TABLE "test'stats2" (
a int,
b int
);
CREATE STATISTICS s2 (dependencies) ON a, b FROM test_stats2;
CREATE STATISTICS s2 (dependencies) ON a, b FROM "test'stats2";
SELECT create_distributed_table('test_stats2', 'a');
SELECT create_distributed_table('test''stats2', 'a');
-- test when stats is on a different schema
CREATE SCHEMA sc1;
CREATE TABLE tbl (a int, b int);
CREATE TABLE tbl (a int, "B" text);
SELECT create_distributed_table ('tbl', 'a');
CREATE STATISTICS sc1.st1 ON a, b FROM tbl;
CREATE STATISTICS sc1.st1 ON a, "B" FROM tbl;
-- test distributing table with already created stats on a new schema
CREATE TABLE test_stats3 (
a int,
b int
);
CREATE SCHEMA sc2;
CREATE STATISTICS sc2."neW'Stat" ON a,b FROM test_stats3;
SELECT create_distributed_table ('test_stats3','a');
\c - - - :worker_1_port
SELECT stxname FROM pg_statistic_ext ORDER BY stxname ASC;
SELECT count(DISTINCT stxnamespace) FROM pg_statistic_ext;
SELECT stxname
FROM pg_statistic_ext
WHERE stxnamespace IN (
SELECT oid
FROM pg_namespace
WHERE nspname IN ('public', 'statistics''Test', 'sc1', 'sc2')
)
ORDER BY stxname ASC;
SELECT count(DISTINCT stxnamespace)
FROM pg_statistic_ext
WHERE stxnamespace IN (
SELECT oid
FROM pg_namespace
WHERE nspname IN ('public', 'statistics''Test', 'sc1', 'sc2')
);
\c - - - :master_port
SET client_min_messages TO WARNING;
DROP SCHEMA "statistics'test" CASCADE;
DROP SCHEMA "statistics'Test" CASCADE;
DROP SCHEMA sc1 CASCADE;
DROP SCHEMA sc2 CASCADE;