From 1f8c343d1553eeb41074a836c0ee6975b764441a Mon Sep 17 00:00:00 2001 From: Onder Kalaci Date: Fri, 23 Jun 2017 14:17:55 +0300 Subject: [PATCH] Enable CREATE TABLE PARTITION OF syntax for distributed tables --- .../commands/create_distributed_table.c | 5 +- .../distributed/executor/multi_utility.c | 35 +++++++++++++ src/include/distributed/citus_ruleutils.h | 4 ++ .../regress/expected/multi_partitioning.out | 49 +++++++++++++++++++ .../regress/expected/multi_partitioning_0.out | 39 +++++++++++++++ src/test/regress/sql/multi_partitioning.sql | 31 ++++++++++++ 6 files changed, 159 insertions(+), 4 deletions(-) diff --git a/src/backend/distributed/commands/create_distributed_table.c b/src/backend/distributed/commands/create_distributed_table.c index dfd701962..673108c3f 100644 --- a/src/backend/distributed/commands/create_distributed_table.c +++ b/src/backend/distributed/commands/create_distributed_table.c @@ -78,9 +78,6 @@ static char LookupDistributionMethod(Oid distributionMethodOid); static Oid SupportFunctionForColumn(Var *partitionColumn, Oid accessMethodId, int16 supportFunctionNumber); static bool LocalTableEmpty(Oid tableId); -static void CreateHashDistributedTable(Oid relationId, char *distributionColumnName, - char *colocateWithTableName, - int shardCount, int replicationFactor); static Oid ColumnType(Oid relationId, char *columnName); static void CopyLocalDataIntoShards(Oid destinationDistributedRelationId, List * sourceLocalRelationList); @@ -618,7 +615,7 @@ CreateTruncateTrigger(Oid relationId) /* * CreateHashDistributedTable creates a hash distributed table. */ -static void +void CreateHashDistributedTable(Oid relationId, char *distributionColumnName, char *colocateWithTableName, int shardCount, int replicationFactor) diff --git a/src/backend/distributed/executor/multi_utility.c b/src/backend/distributed/executor/multi_utility.c index cdc4e7f38..fc21ddf20 100644 --- a/src/backend/distributed/executor/multi_utility.c +++ b/src/backend/distributed/executor/multi_utility.c @@ -512,6 +512,41 @@ multi_ProcessUtility(PlannedStmt *pstmt, } } +#if (PG_VERSION_NUM >= 100000) + if (IsA(parsetree, CreateStmt)) + { + CreateStmt *createStatement = (CreateStmt *) parsetree; + + /* if a partition is being created */ + if (createStatement->inhRelations != NIL && createStatement->partbound != NULL) + { + RangeVar *parentRelation = linitial(createStatement->inhRelations); + char *parentSchemaName = parentRelation->schemaname ? + parentRelation->schemaname : "public"; + + Oid parentId = get_relname_relid(parentRelation->relname, get_namespace_oid( + parentSchemaName, false)); + char *schemaName = createStatement->relation->schemaname ? + createStatement->relation->schemaname : "public"; + + Oid relationId = get_relname_relid(createStatement->relation->relname, + get_namespace_oid(schemaName, false)); + + /* if the table is being attached to a distribtued table, it should be distributed as well */ + if (IsDistributedTable(parentId)) + { + Var *parentPartitionKey = DistPartitionKey(parentId); + char *parentPartitionKeyStr = + get_relid_attribute_name(parentId, + parentPartitionKey->varattno); + + CreateHashDistributedTable(relationId, parentPartitionKeyStr, + get_rel_name(parentId), 0, 0); + } + } + } +#endif + /* TODO: fold VACUUM's processing into the above block */ if (IsA(parsetree, VacuumStmt)) { diff --git a/src/include/distributed/citus_ruleutils.h b/src/include/distributed/citus_ruleutils.h index d4a4e5a1c..2135d691a 100644 --- a/src/include/distributed/citus_ruleutils.h +++ b/src/include/distributed/citus_ruleutils.h @@ -49,5 +49,9 @@ extern void deparse_shard_query(Query *query, Oid distrelid, int64 shardid, extern char * generate_relation_name(Oid relid, List *namespaces); extern char * generate_qualified_relation_name(Oid relid); +/* TODO: THIS SHOULD NOT BE HERE */ +extern void CreateHashDistributedTable(Oid relationId, char *distributionColumnName, + char *colocateWithTableName, + int shardCount, int replicationFactor); #endif /* CITUS_RULEUTILS_H */ diff --git a/src/test/regress/expected/multi_partitioning.out b/src/test/regress/expected/multi_partitioning.out index e64447d8f..b8da66b37 100644 --- a/src/test/regress/expected/multi_partitioning.out +++ b/src/test/regress/expected/multi_partitioning.out @@ -81,6 +81,55 @@ ORDER BY localhost | 57638 | 6 (2 rows) +-- now create a partition and see that it also becomes a distributed table +CREATE TABLE partitioning_test_2011 PARTITION OF partitioning_test FOR VALUES FROM ('2011-01-01') TO ('2012-01-01'); +SELECT + * +FROM + pg_dist_partition +WHERE + logicalrelid IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010', 'partitioning_test_2011') +ORDER BY 1; + logicalrelid | partmethod | partkey | colocationid | repmodel +------------------------+------------+------------------------------------------------------------------------------------------------------------------------+--------------+---------- + partitioning_test | h | {VAR :varno 1 :varattno 1 :vartype 23 :vartypmod -1 :varcollid 0 :varlevelsup 0 :varnoold 1 :varoattno 1 :location -1} | 2 | c + partitioning_test_2009 | h | {VAR :varno 1 :varattno 1 :vartype 23 :vartypmod -1 :varcollid 0 :varlevelsup 0 :varnoold 1 :varoattno 1 :location -1} | 2 | c + partitioning_test_2010 | h | {VAR :varno 1 :varattno 1 :vartype 23 :vartypmod -1 :varcollid 0 :varlevelsup 0 :varnoold 1 :varoattno 1 :location -1} | 2 | c + partitioning_test_2011 | h | {VAR :varno 1 :varattno 1 :vartype 23 :vartypmod -1 :varcollid 0 :varlevelsup 0 :varnoold 1 :varoattno 1 :location -1} | 2 | c +(4 rows) + +SELECT + logicalrelid, count(*) +FROM pg_dist_shard + WHERE logicalrelid IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010', 'partitioning_test_2011') +GROUP BY + logicalrelid +ORDER BY + 1,2; + logicalrelid | count +------------------------+------- + partitioning_test | 4 + partitioning_test_2009 | 4 + partitioning_test_2010 | 4 + partitioning_test_2011 | 4 +(4 rows) + +SELECT + nodename, nodeport, count(*) +FROM + pg_dist_shard_placement +WHERE + shardid IN (SELECT shardid FROM pg_dist_shard WHERE logicalrelid IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010', 'partitioning_test_2011') ) +GROUP BY + nodename, nodeport +ORDER BY + 1,2,3; + nodename | nodeport | count +-----------+----------+------- + localhost | 57637 | 8 + localhost | 57638 | 8 +(2 rows) + -- dropping the parent should CASCADE to the children as well DROP TABLE partitioning_test; \d+ partitioning_test* diff --git a/src/test/regress/expected/multi_partitioning_0.out b/src/test/regress/expected/multi_partitioning_0.out index 823fffc6f..f95f9978b 100644 --- a/src/test/regress/expected/multi_partitioning_0.out +++ b/src/test/regress/expected/multi_partitioning_0.out @@ -80,6 +80,45 @@ GROUP BY ORDER BY 1,2,3; ERROR: relation "partitioning_test" does not exist +LINE 6: ...shardid FROM pg_dist_shard WHERE logicalrelid IN ('partition... + ^ +-- now create a partition and see that it also becomes a distributed table +CREATE TABLE partitioning_test_2011 PARTITION OF partitioning_test FOR VALUES FROM ('2011-01-01') TO ('2012-01-01'); +ERROR: syntax error at or near "PARTITION" +LINE 1: CREATE TABLE partitioning_test_2011 PARTITION OF partitionin... + ^ +SELECT + * +FROM + pg_dist_partition +WHERE + logicalrelid IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010', 'partitioning_test_2011') +ORDER BY 1; +ERROR: relation "partitioning_test" does not exist +LINE 6: logicalrelid IN ('partitioning_test', 'partitioning_test_20... + ^ +SELECT + logicalrelid, count(*) +FROM pg_dist_shard + WHERE logicalrelid IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010', 'partitioning_test_2011') +GROUP BY + logicalrelid +ORDER BY + 1,2; +ERROR: relation "partitioning_test" does not exist +LINE 4: WHERE logicalrelid IN ('partitioning_test', 'partitioning_t... + ^ +SELECT + nodename, nodeport, count(*) +FROM + pg_dist_shard_placement +WHERE + shardid IN (SELECT shardid FROM pg_dist_shard WHERE logicalrelid IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010', 'partitioning_test_2011') ) +GROUP BY + nodename, nodeport +ORDER BY + 1,2,3; +ERROR: relation "partitioning_test" does not exist LINE 6: ...shardid FROM pg_dist_shard WHERE logicalrelid IN ('partition... ^ -- dropping the parent should CASCADE to the children as well diff --git a/src/test/regress/sql/multi_partitioning.sql b/src/test/regress/sql/multi_partitioning.sql index 18d9b5cd5..3b1fd5b82 100644 --- a/src/test/regress/sql/multi_partitioning.sql +++ b/src/test/regress/sql/multi_partitioning.sql @@ -54,6 +54,37 @@ GROUP BY ORDER BY 1,2,3; +-- now create a partition and see that it also becomes a distributed table +CREATE TABLE partitioning_test_2011 PARTITION OF partitioning_test FOR VALUES FROM ('2011-01-01') TO ('2012-01-01'); + +SELECT + * +FROM + pg_dist_partition +WHERE + logicalrelid IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010', 'partitioning_test_2011') +ORDER BY 1; + +SELECT + logicalrelid, count(*) +FROM pg_dist_shard + WHERE logicalrelid IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010', 'partitioning_test_2011') +GROUP BY + logicalrelid +ORDER BY + 1,2; + +SELECT + nodename, nodeport, count(*) +FROM + pg_dist_shard_placement +WHERE + shardid IN (SELECT shardid FROM pg_dist_shard WHERE logicalrelid IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010', 'partitioning_test_2011') ) +GROUP BY + nodename, nodeport +ORDER BY + 1,2,3; + -- dropping the parent should CASCADE to the children as well DROP TABLE partitioning_test;