Add support for ALTER TABLE .. ATTACH PARTITION

pull/1467/head
Onder Kalaci 2017-06-23 16:05:51 +03:00
parent 1f8c343d15
commit 2f879f0e26
4 changed files with 202 additions and 0 deletions

View File

@ -42,6 +42,7 @@
#include "distributed/metadata_sync.h"
#include "distributed/multi_copy.h"
#include "distributed/multi_join_order.h"
#include "distributed/multi_partitioning_utils.h"
#include "distributed/multi_planner.h"
#include "distributed/multi_router_executor.h"
#include "distributed/multi_router_planner.h"
@ -545,6 +546,45 @@ multi_ProcessUtility(PlannedStmt *pstmt,
}
}
}
else if (IsA(parsetree, AlterTableStmt))
{
AlterTableStmt *alterTableStatement = (AlterTableStmt *) parsetree;
List *commandList = alterTableStatement->cmds;
ListCell *commandCell = NULL;
foreach(commandCell, commandList)
{
AlterTableCmd *alterTableCommand = (AlterTableCmd *) lfirst(commandCell);
AlterTableType alterTableType = alterTableCommand->subtype;
if (alterTableType == AT_AttachPartition)
{
PartitionCmd *partitionCommand = (PartitionCmd *) alterTableCommand->def;
char *relationName = partitionCommand->name->relname;
char *schemaName = partitionCommand->name->schemaname ?
partitionCommand->name->schemaname : "public";
Oid relationId = get_relname_relid(relationName,
get_namespace_oid(schemaName, false));
Oid parentId = PartitionParentOid(relationId);
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 */
@ -1070,6 +1110,30 @@ PlanAlterTableStmt(AlterTableStmt *alterTableStatement, const char *alterTableCo
constraint->skip_validation = true;
}
}
#if (PG_VERSION_NUM >= 100000)
else if (alterTableType == AT_AttachPartition)
{
PartitionCmd *partitionCommand = (PartitionCmd *) command->def;
char *relationName = partitionCommand->name->relname;
char *schemaName = partitionCommand->name->schemaname ?
partitionCommand->name->schemaname : "public";
Oid relationId = get_relname_relid(relationName,
get_namespace_oid(schemaName, false));
Oid parentId = leftRelationId;
/*
* Do not generate tasks if relation is not distributed and the parent
* is distributed. Because, we'll manually convert the relation into
* distribtued relation and co-locate with its parent.
*/
if (!IsDistributedTable(relationId) && IsDistributedTable(parentId))
{
return NIL;
}
}
#endif
}
ddlJob = palloc0(sizeof(DDLJob));
@ -1813,6 +1877,9 @@ ErrorIfUnsupportedAlterTableStmt(AlterTableStmt *alterTableStatement)
case AT_DropConstraint:
case AT_EnableTrigAll:
case AT_DisableTrigAll:
#if (PG_VERSION_NUM >= 100000)
case AT_AttachPartition:
#endif
{
/*
* We will not perform any special check for ALTER TABLE DROP CONSTRAINT

View File

@ -130,6 +130,59 @@ ORDER BY
localhost | 57638 | 8
(2 rows)
-- citus can also support ALTER TABLE .. ATTACH PARTITION
-- even if the partition is not distributed
CREATE TABLE partitioning_test_2012(id int, time date);
ALTER TABLE partitioning_test ATTACH PARTITION partitioning_test_2012 FOR VALUES FROM ('2012-01-01') TO ('2013-01-01');
SELECT
*
FROM
pg_dist_partition
WHERE
logicalrelid IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010', 'partitioning_test_2011', 'partitioning_test_2012')
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
partitioning_test_2012 | h | {VAR :varno 1 :varattno 1 :vartype 23 :vartypmod -1 :varcollid 0 :varlevelsup 0 :varnoold 1 :varoattno 1 :location -1} | 2 | c
(5 rows)
SELECT
logicalrelid, count(*)
FROM pg_dist_shard
WHERE logicalrelid IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010', 'partitioning_test_2011', 'partitioning_test_2012')
GROUP BY
logicalrelid
ORDER BY
1,2;
logicalrelid | count
------------------------+-------
partitioning_test | 4
partitioning_test_2009 | 4
partitioning_test_2010 | 4
partitioning_test_2011 | 4
partitioning_test_2012 | 4
(5 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', 'partitioning_test_2012') )
GROUP BY
nodename, nodeport
ORDER BY
1,2,3;
nodename | nodeport | count
-----------+----------+-------
localhost | 57637 | 10
localhost | 57638 | 10
(2 rows)
-- dropping the parent should CASCADE to the children as well
DROP TABLE partitioning_test;
\d+ partitioning_test*

View File

@ -119,9 +119,56 @@ 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...
^
-- citus can also support ALTER TABLE .. ATTACH PARTITION
-- even if the partition is not distributed
CREATE TABLE partitioning_test_2012(id int, time date);
ALTER TABLE partitioning_test ATTACH PARTITION partitioning_test_2012 FOR VALUES FROM ('2012-01-01') TO ('2013-01-01');
ERROR: syntax error at or near "ATTACH"
LINE 1: ALTER TABLE partitioning_test ATTACH PARTITION partitioning_...
^
SELECT
*
FROM
pg_dist_partition
WHERE
logicalrelid IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010', 'partitioning_test_2011', 'partitioning_test_2012')
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', 'partitioning_test_2012')
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', 'partitioning_test_2012') )
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
DROP TABLE partitioning_test;
ERROR: table "partitioning_test" does not exist
\d+ partitioning_test*
Table "public.partitioning_test_2012"
Column | Type | Modifiers | Storage | Stats target | Description
--------+---------+-----------+---------+--------------+-------------
id | integer | | plain | |
time | date | | plain | |

View File

@ -85,6 +85,41 @@ GROUP BY
ORDER BY
1,2,3;
-- citus can also support ALTER TABLE .. ATTACH PARTITION
-- even if the partition is not distributed
CREATE TABLE partitioning_test_2012(id int, time date);
ALTER TABLE partitioning_test ATTACH PARTITION partitioning_test_2012 FOR VALUES FROM ('2012-01-01') TO ('2013-01-01');
SELECT
*
FROM
pg_dist_partition
WHERE
logicalrelid IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010', 'partitioning_test_2011', 'partitioning_test_2012')
ORDER BY 1;
SELECT
logicalrelid, count(*)
FROM pg_dist_shard
WHERE logicalrelid IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010', 'partitioning_test_2011', 'partitioning_test_2012')
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', 'partitioning_test_2012') )
GROUP BY
nodename, nodeport
ORDER BY
1,2,3;
-- dropping the parent should CASCADE to the children as well
DROP TABLE partitioning_test;