Refactor distributed table creation logic

This commit is preperation for introducing distributed partitioned
table support. We want to clean and refactor some code in distributed
table creation logic so that we can handle partitioned tables in more
robust way.
pull/1525/head
Burak Yucesoy 2017-07-27 12:25:18 +03:00
parent 520d74b96d
commit 7769f1d012
12 changed files with 657 additions and 506 deletions

File diff suppressed because it is too large Load Diff

View File

@ -183,7 +183,7 @@ DropShardsFromWorker(WorkerNode *workerNode, Oid relationId, List *shardInterval
} }
} }
if (relationKind == RELKIND_RELATION) if (RegularTable(relationId))
{ {
appendStringInfo(workerCommand, DROP_REGULAR_TABLE_COMMAND, shardNames->data); appendStringInfo(workerCommand, DROP_REGULAR_TABLE_COMMAND, shardNames->data);
} }

View File

@ -721,7 +721,7 @@ ShardStorageType(Oid relationId)
char shardStorageType = 0; char shardStorageType = 0;
char relationType = get_rel_relkind(relationId); char relationType = get_rel_relkind(relationId);
if (relationType == RELKIND_RELATION) if (RegularTable(relationId))
{ {
shardStorageType = SHARD_STORAGE_TABLE; shardStorageType = SHARD_STORAGE_TABLE;
} }

View File

@ -389,7 +389,7 @@ RecreateTableDDLCommandList(Oid relationId)
bool includeSequenceDefaults = false; bool includeSequenceDefaults = false;
/* build appropriate DROP command based on relation kind */ /* build appropriate DROP command based on relation kind */
if (relationKind == RELKIND_RELATION) if (RegularTable(relationId))
{ {
appendStringInfo(dropCommand, DROP_REGULAR_TABLE_COMMAND, appendStringInfo(dropCommand, DROP_REGULAR_TABLE_COMMAND,
qualifiedRelationName); qualifiedRelationName);

View File

@ -36,6 +36,7 @@
#include "distributed/citus_ruleutils.h" #include "distributed/citus_ruleutils.h"
#include "distributed/multi_partitioning_utils.h" #include "distributed/multi_partitioning_utils.h"
#include "distributed/relay_utility.h" #include "distributed/relay_utility.h"
#include "distributed/master_metadata_utility.h"
#include "foreign/foreign.h" #include "foreign/foreign.h"
#include "lib/stringinfo.h" #include "lib/stringinfo.h"
#include "nodes/nodes.h" #include "nodes/nodes.h"
@ -59,7 +60,6 @@
static void AppendOptionListToString(StringInfo stringData, List *options); static void AppendOptionListToString(StringInfo stringData, List *options);
static bool SupportedRelationKind(Relation relation);
static const char * convert_aclright_to_string(int aclright); static const char * convert_aclright_to_string(int aclright);
@ -291,7 +291,6 @@ pg_get_tableschemadef_string(Oid tableRelationId, bool includeSequenceDefaults)
AttrNumber constraintIndex = 0; AttrNumber constraintIndex = 0;
AttrNumber constraintCount = 0; AttrNumber constraintCount = 0;
StringInfoData buffer = { NULL, 0, 0, 0 }; StringInfoData buffer = { NULL, 0, 0, 0 };
bool supportedRelationKind = false;
/* /*
* Instead of retrieving values from system catalogs as other functions in * Instead of retrieving values from system catalogs as other functions in
@ -304,13 +303,7 @@ pg_get_tableschemadef_string(Oid tableRelationId, bool includeSequenceDefaults)
relation = relation_open(tableRelationId, AccessShareLock); relation = relation_open(tableRelationId, AccessShareLock);
relationName = generate_relation_name(tableRelationId, NIL); relationName = generate_relation_name(tableRelationId, NIL);
supportedRelationKind = SupportedRelationKind(relation); EnsureRelationKindSupported(tableRelationId);
if (!supportedRelationKind)
{
ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("%s is not a regular, foreign, or partitioned table",
relationName)));
}
initStringInfo(&buffer); initStringInfo(&buffer);
@ -491,25 +484,33 @@ pg_get_tableschemadef_string(Oid tableRelationId, bool includeSequenceDefaults)
/* /*
* SupportedRelationKind returns true if the given relation is supported as a * EnsureRelationKindSupported errors out if the given relation is not supported
* distributed relation. * as a distributed relation.
*/ */
static bool void
SupportedRelationKind(Relation relation) EnsureRelationKindSupported(Oid relationId)
{ {
char relationKind = relation->rd_rel->relkind; char relationKind = get_rel_relkind(relationId);
bool supportedRelationKind = (relationKind == RELKIND_RELATION || relationKind == bool supportedRelationKind = false;
RELKIND_FOREIGN_TABLE);
#if (PG_VERSION_NUM >= 100000)
supportedRelationKind = supportedRelationKind || relationKind ==
RELKIND_PARTITIONED_TABLE;
#endif
/* Citus doesn't support bare inhereted tables (i.e., not a partition or partitioned table) */ supportedRelationKind = RegularTable(relationId) ||
supportedRelationKind = supportedRelationKind && !(IsChildTable(relation->rd_id) || relationKind == RELKIND_FOREIGN_TABLE;
IsParentTable(relation->rd_id));
return supportedRelationKind; /*
* Citus doesn't support bare inherited tables (i.e., not a partition or
* partitioned table)
*/
supportedRelationKind = supportedRelationKind && !(IsChildTable(relationId) ||
IsParentTable(relationId));
if (!supportedRelationKind)
{
char *relationName = get_rel_name(relationId);
ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("%s is not a regular, foreign or partitioned table",
relationName)));
}
} }
@ -523,15 +524,12 @@ char *
pg_get_tablecolumnoptionsdef_string(Oid tableRelationId) pg_get_tablecolumnoptionsdef_string(Oid tableRelationId)
{ {
Relation relation = NULL; Relation relation = NULL;
char *relationName = NULL;
char relationKind = 0;
TupleDesc tupleDescriptor = NULL; TupleDesc tupleDescriptor = NULL;
AttrNumber attributeIndex = 0; AttrNumber attributeIndex = 0;
List *columnOptionList = NIL; List *columnOptionList = NIL;
ListCell *columnOptionCell = NULL; ListCell *columnOptionCell = NULL;
bool firstOptionPrinted = false; bool firstOptionPrinted = false;
StringInfoData buffer = { NULL, 0, 0, 0 }; StringInfoData buffer = { NULL, 0, 0, 0 };
bool supportedRelationKind = false;
/* /*
* Instead of retrieving values from system catalogs, we open the relation, * Instead of retrieving values from system catalogs, we open the relation,
@ -539,22 +537,8 @@ pg_get_tablecolumnoptionsdef_string(Oid tableRelationId)
* This is primarily to maintain symmetry with pg_get_tableschemadef. * This is primarily to maintain symmetry with pg_get_tableschemadef.
*/ */
relation = relation_open(tableRelationId, AccessShareLock); relation = relation_open(tableRelationId, AccessShareLock);
relationName = generate_relation_name(tableRelationId, NIL);
relationKind = relation->rd_rel->relkind; EnsureRelationKindSupported(tableRelationId);
supportedRelationKind = (relationKind == RELKIND_RELATION || relationKind ==
RELKIND_FOREIGN_TABLE);
#if (PG_VERSION_NUM >= 100000)
supportedRelationKind = supportedRelationKind || relationKind ==
RELKIND_PARTITIONED_TABLE;
#endif
if (!supportedRelationKind)
{
ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("%s is not a regular or foreign table or partitioned",
relationName)));
}
/* /*
* Iterate over the table's columns. If a particular column is not dropped * Iterate over the table's columns. If a particular column is not dropped

View File

@ -904,6 +904,15 @@ ColocatedTableId(Oid colocationId)
ScanKeyData scanKey[1]; ScanKeyData scanKey[1];
int scanKeyCount = 1; int scanKeyCount = 1;
/*
* We may have a distributed table whose colocation id is INVALID_COLOCATION_ID.
* In this case, we do not want to send that table's id as colocated table id.
*/
if (colocationId == INVALID_COLOCATION_ID)
{
return colocatedTableId;
}
ScanKeyInit(&scanKey[0], Anum_pg_dist_partition_colocationid, ScanKeyInit(&scanKey[0], Anum_pg_dist_partition_colocationid,
BTEqualStrategyNumber, F_INT4EQ, ObjectIdGetDatum(colocationId)); BTEqualStrategyNumber, F_INT4EQ, ObjectIdGetDatum(colocationId));

View File

@ -34,6 +34,7 @@ extern char * pg_get_serverdef_string(Oid tableRelationId);
extern char * pg_get_sequencedef_string(Oid sequenceRelid); extern char * pg_get_sequencedef_string(Oid sequenceRelid);
extern Form_pg_sequence pg_get_sequencedef(Oid sequenceRelationId); extern Form_pg_sequence pg_get_sequencedef(Oid sequenceRelationId);
extern char * pg_get_tableschemadef_string(Oid tableRelationId, bool forShardCreation); extern char * pg_get_tableschemadef_string(Oid tableRelationId, bool forShardCreation);
extern void EnsureRelationKindSupported(Oid relationId);
extern char * pg_get_tablecolumnoptionsdef_string(Oid tableRelationId); extern char * pg_get_tablecolumnoptionsdef_string(Oid tableRelationId);
extern void deparse_shard_index_statement(IndexStmt *origStmt, Oid distrelid, extern void deparse_shard_index_statement(IndexStmt *origStmt, Oid distrelid,
int64 shardid, StringInfo buffer); int64 shardid, StringInfo buffer);

View File

@ -139,6 +139,9 @@ extern void UpdateShardPlacementState(uint64 placementId, char shardState);
extern void DeleteShardPlacementRow(uint64 placementId); extern void DeleteShardPlacementRow(uint64 placementId);
extern void UpdateColocationGroupReplicationFactor(uint32 colocationId, extern void UpdateColocationGroupReplicationFactor(uint32 colocationId,
int replicationFactor); int replicationFactor);
extern void CreateDistributedTable(Oid relationId, Var *distributionColumn,
char distributionMethod, char *colocateWithTableName,
bool viaDeprecatedAPI);
extern void CreateTruncateTrigger(Oid relationId); extern void CreateTruncateTrigger(Oid relationId);
/* Remaining metadata utility functions */ /* Remaining metadata utility functions */
@ -147,6 +150,7 @@ extern void EnsureTablePermissions(Oid relationId, AclMode mode);
extern void EnsureTableOwner(Oid relationId); extern void EnsureTableOwner(Oid relationId);
extern void EnsureSuperUser(void); extern void EnsureSuperUser(void);
extern void EnsureReplicationSettings(Oid relationId, char replicationModel); extern void EnsureReplicationSettings(Oid relationId, char replicationModel);
extern bool RegularTable(Oid relationId);
extern bool TableReferenced(Oid relationId); extern bool TableReferenced(Oid relationId);
extern char * ConstructQualifiedShardName(ShardInterval *shardInterval); extern char * ConstructQualifiedShardName(ShardInterval *shardInterval);
extern Datum StringToDatum(char *inputString, Oid dataType); extern Datum StringToDatum(char *inputString, Oid dataType);

View File

@ -48,7 +48,7 @@ DETAIL: Distributed relations must not specify the WITH (OIDS) option in their
ALTER TABLE table_to_distribute SET WITHOUT OIDS; ALTER TABLE table_to_distribute SET WITHOUT OIDS;
-- use an index instead of table name -- use an index instead of table name
SELECT master_create_distributed_table('table_to_distribute_pkey', 'id', 'hash'); SELECT master_create_distributed_table('table_to_distribute_pkey', 'id', 'hash');
ERROR: table_to_distribute_pkey is not a regular or foreign table ERROR: table_to_distribute_pkey is not a regular, foreign or partitioned table
-- use a bad column name -- use a bad column name
SELECT master_create_distributed_table('table_to_distribute', 'bad_column', 'hash'); SELECT master_create_distributed_table('table_to_distribute', 'bad_column', 'hash');
ERROR: column "bad_column" of relation "table_to_distribute" does not exist ERROR: column "bad_column" of relation "table_to_distribute" does not exist

View File

@ -146,7 +146,7 @@ NOTICE: foreign-data wrapper "fake_fdw" does not have an extension defined
-- propagating views is not supported -- propagating views is not supported
CREATE VIEW local_view AS SELECT * FROM simple_table; CREATE VIEW local_view AS SELECT * FROM simple_table;
SELECT table_ddl_command_array('local_view'); SELECT table_ddl_command_array('local_view');
ERROR: public.local_view is not a regular, foreign, or partitioned table ERROR: local_view is not a regular, foreign or partitioned table
-- clean up -- clean up
DROP VIEW IF EXISTS local_view; DROP VIEW IF EXISTS local_view;
DROP FOREIGN TABLE IF EXISTS foreign_table; DROP FOREIGN TABLE IF EXISTS foreign_table;

View File

@ -415,8 +415,8 @@ SELECT table_inherited('date_partitioned_table');
-- also these are not supported -- also these are not supported
SELECT master_get_table_ddl_events('capitals'); SELECT master_get_table_ddl_events('capitals');
ERROR: public.capitals is not a regular, foreign, or partitioned table ERROR: capitals is not a regular, foreign or partitioned table
SELECT master_get_table_ddl_events('cities'); SELECT master_get_table_ddl_events('cities');
ERROR: public.cities is not a regular, foreign, or partitioned table ERROR: cities is not a regular, foreign or partitioned table
-- dropping parents frop the partitions -- dropping parents frop the partitions
DROP TABLE date_partitioned_table, multi_column_partitioned, list_partitioned, partition_parent_schema.parent_table, cities, capitals; DROP TABLE date_partitioned_table, multi_column_partitioned, list_partitioned, partition_parent_schema.parent_table, cities, capitals;

View File

@ -355,9 +355,9 @@ LINE 1: SELECT table_inherited('date_partitioned_table');
^ ^
-- also these are not supported -- also these are not supported
SELECT master_get_table_ddl_events('capitals'); SELECT master_get_table_ddl_events('capitals');
ERROR: public.capitals is not a regular, foreign, or partitioned table ERROR: capitals is not a regular, foreign or partitioned table
SELECT master_get_table_ddl_events('cities'); SELECT master_get_table_ddl_events('cities');
ERROR: public.cities is not a regular, foreign, or partitioned table ERROR: cities is not a regular, foreign or partitioned table
-- dropping parents frop the partitions -- dropping parents frop the partitions
DROP TABLE date_partitioned_table, multi_column_partitioned, list_partitioned, partition_parent_schema.parent_table, cities, capitals; DROP TABLE date_partitioned_table, multi_column_partitioned, list_partitioned, partition_parent_schema.parent_table, cities, capitals;
ERROR: table "date_partitioned_table" does not exist ERROR: table "date_partitioned_table" does not exist