Add partitioning support for citus local tables

Add/fix tests

Fix creating partitions

Add test for mx - partition creating case

Enable cascading to partitioned tables

Fix mx partition adding test

Fix cascading through fkeys

Style

Disable converting with non-inherited fkeys

Fix detach bug

Early return in case of cascade & Add tests

Style

Fix undistribute_table bug & Fix test outputs

Remove RemovePartitionRelationIds

Test with undistribute_table

Add test for mx+convert+undistribute

Remove redundant usage of CreatePartitionedCitusLocalTable

Add some comments

Introduce bulk functions for generating attach/detach partition commands

Fix: Convert partitioned tables after adding fkey

Change the error message for partitions

Introduce function ErrorIfPartitionTableAddedToMetadata

Polish attach/detach command generation functions

Use time_partitions for testing

Move mx tests to citus_local_tables_mx

Add new partitioned table to cascade test

Add test with time series management UDFs

Fix test output

Fix: Assertion fail on relation access tracking

Style

Refactor creating partitioned citus local tables

Remove CreatePartitionedCitusLocalTable

Style

Error out if converting multi-level table

Revert some old tests

Error out adding partitioned partition

Polish

Polish/address

Fix create table partition of case

Use CascadeOperationForRelationIdList if no cascade needed

Fix create partition bug

Revert / Add new tests to mx

Style

Fix dropping fkey bug

Add test with IF NOT EXISTS

Convert to CLT when doing ATTACH PARTITION

Add comments

Add more tests with time series management

Edit the error message for converting the child

Use OR instead of AND in ErrorIfUnsupportedAlterTableStmt

Edit/improve tests

Disable ddl prop when dropping default column definitions

Disable/enable ddl prop just before/after the command

Add comment

Add sequence test

Add trigger test

Remove NeedCascadeViaForeignKeys

Add one more insert to sequence test

Add comment

Style

Fix test output shard ids

Update comments

Disable creating fkey on partitions

Move partition check to CreateCitusLocalTable

Add comment

Add check for  attachingmulti-level  partition

Add test for pg_constraint

Check pg_dist_partition in tests

Add test inserting on the worker
pull/5296/head
Ahmet Gedemenli 2021-09-16 13:50:34 +03:00
parent 09a070221a
commit d19793c174
24 changed files with 1810 additions and 287 deletions

View File

@ -527,8 +527,8 @@ ConvertTable(TableConversionState *con)
* Acquire ExclusiveLock as UndistributeTable does in order to
* make sure that no modifications happen on the relations.
*/
CascadeOperationForConnectedRelations(con->relationId, ExclusiveLock,
CASCADE_FKEY_UNDISTRIBUTE_TABLE);
CascadeOperationForFkeyConnectedRelations(con->relationId, ExclusiveLock,
CASCADE_FKEY_UNDISTRIBUTE_TABLE);
/*
* Undistributed every foreign key connected relation in our foreign key

View File

@ -33,9 +33,9 @@
static void EnsureSequentialModeForCitusTableCascadeFunction(List *relationIdList);
static List * GetPartitionRelationIds(List *relationIdList);
static void LockRelationsWithLockMode(List *relationIdList, LOCKMODE lockMode);
static List * RemovePartitionRelationIds(List *relationIdList);
static List * GetFKeyCreationCommandsForRelationIdList(List *relationIdList);
static void ErrorIfConvertingMultiLevelPartitionedTable(List *relationIdList);
static void DropRelationIdListForeignKeys(List *relationIdList, int fKeyFlags);
static List * GetRelationDropFkeyCommands(Oid relationId, int fKeyFlags);
static char * GetDropFkeyCascadeCommand(Oid foreignKeyId);
@ -46,17 +46,14 @@ static void ExecuteForeignKeyCreateCommand(const char *commandString,
bool skip_validation);
/*
* CascadeOperationForConnectedRelations executes citus table function specified
* by CascadeOperationType argument on each relation that relation
* with relationId is connected via it's foreign key graph, which includes
* input relation itself.
* Also see CascadeOperationType enum definition for supported
* citus table functions.
* CascadeOperationForFkeyConnectedRelations is a wrapper function which calls
* CascadeOperationForRelationIdList for the foreign key connected relations, for
* the given relationId.
*/
void
CascadeOperationForConnectedRelations(Oid relationId, LOCKMODE lockMode,
CascadeOperationType
cascadeOperationType)
CascadeOperationForFkeyConnectedRelations(Oid relationId, LOCKMODE lockMode,
CascadeOperationType
cascadeOperationType)
{
/*
* As we will operate on foreign key connected relations, here we
@ -72,7 +69,38 @@ CascadeOperationForConnectedRelations(Oid relationId, LOCKMODE lockMode,
return;
}
LockRelationsWithLockMode(fKeyConnectedRelationIdList, lockMode);
CascadeOperationForRelationIdList(fKeyConnectedRelationIdList, lockMode,
cascadeOperationType);
}
/*
* CascadeOperationForRelationIdList executes citus table function specified
* by CascadeOperationType argument on each relation in the relationIdList;
* Also see CascadeOperationType enum definition for supported
* citus table functions.
*/
void
CascadeOperationForRelationIdList(List *relationIdList, LOCKMODE lockMode,
CascadeOperationType
cascadeOperationType)
{
LockRelationsWithLockMode(relationIdList, lockMode);
if (cascadeOperationType == CASCADE_ADD_LOCAL_TABLE_TO_METADATA)
{
/*
* In CreateCitusLocalTable function, this check would never error out,
* since CreateCitusLocalTable gets called with partition relations, *after*
* they are detached.
* Instead, here, it would error out if the user tries to convert a multi-level
* partitioned table, since partitioned table conversions always go through here.
* Also, there can be a multi-level partitioned table, to be cascaded via foreign
* keys, and they are hard to detect in CreateCitusLocalTable.
* Therefore, we put this check here.
*/
ErrorIfConvertingMultiLevelPartitionedTable(relationIdList);
}
/*
* Before removing any partition relations, we should error out here if any
@ -81,25 +109,29 @@ CascadeOperationForConnectedRelations(Oid relationId, LOCKMODE lockMode,
* We should handle this case here as we remove partition relations in this
* function before ExecuteCascadeOperationForRelationIdList.
*/
ErrorIfAnyPartitionRelationInvolvedInNonInheritedFKey(fKeyConnectedRelationIdList);
ErrorIfAnyPartitionRelationInvolvedInNonInheritedFKey(relationIdList);
List *partitonRelationList = GetPartitionRelationIds(relationIdList);
/*
* We shouldn't cascade through foreign keys on partition tables as citus
* table functions already have their own logics to handle partition relations.
* Here we generate detach/attach commands, if there are any partition tables
* in our "relations-to-cascade" list.
*/
List *nonPartitionRelationIdList =
RemovePartitionRelationIds(fKeyConnectedRelationIdList);
List *detachPartitionCommands =
GenerateDetachPartitionCommandRelationIdList(partitonRelationList);
List *attachPartitionCommands =
GenerateAttachPartitionCommandRelationIdList(partitonRelationList);
/*
* Our foreign key subgraph can have distributed tables which might already
* be modified in current transaction. So switch to sequential execution
* before executing any ddl's to prevent erroring out later in this function.
*/
EnsureSequentialModeForCitusTableCascadeFunction(nonPartitionRelationIdList);
EnsureSequentialModeForCitusTableCascadeFunction(relationIdList);
/* store foreign key creation commands before dropping them */
List *fKeyCreationCommands =
GetFKeyCreationCommandsForRelationIdList(nonPartitionRelationIdList);
GetFKeyCreationCommandsForRelationIdList(relationIdList);
/*
* Note that here we only drop referencing foreign keys for each relation.
@ -107,16 +139,43 @@ CascadeOperationForConnectedRelations(Oid relationId, LOCKMODE lockMode,
* relations' referencing foreign keys.
*/
int fKeyFlags = INCLUDE_REFERENCING_CONSTRAINTS | INCLUDE_ALL_TABLE_TYPES;
DropRelationIdListForeignKeys(nonPartitionRelationIdList, fKeyFlags);
ExecuteCascadeOperationForRelationIdList(nonPartitionRelationIdList,
DropRelationIdListForeignKeys(relationIdList, fKeyFlags);
ExecuteAndLogUtilityCommandList(detachPartitionCommands);
ExecuteCascadeOperationForRelationIdList(relationIdList,
cascadeOperationType);
ExecuteAndLogUtilityCommandList(attachPartitionCommands);
/* now recreate foreign keys on tables */
bool skip_validation = true;
ExecuteForeignKeyCreateCommandList(fKeyCreationCommands, skip_validation);
}
/*
* GetPartitionRelationIds returns a list of relation id's by picking
* partition relation id's from given relationIdList.
*/
static List *
GetPartitionRelationIds(List *relationIdList)
{
List *partitionRelationIdList = NIL;
Oid relationId = InvalidOid;
foreach_oid(relationId, relationIdList)
{
if (PartitionTable(relationId))
{
partitionRelationIdList = lappend_oid(partitionRelationIdList, relationId);
}
}
return partitionRelationIdList;
}
/*
* LockRelationsWithLockMode sorts given relationIdList and then acquires
* specified lockMode on those relations.
@ -133,6 +192,36 @@ LockRelationsWithLockMode(List *relationIdList, LOCKMODE lockMode)
}
/*
* ErrorIfConvertingMultiLevelPartitionedTable iterates given relationIdList and checks
* if there's a multi-level partitioned table involved or not. As we currently don't
* support converting multi-level partitioned tables into Citus Local Tables,
* this function errors out for such a case. We detect the multi-level partitioned
* table if one of the relations is both partition and partitioned table.
*/
static void
ErrorIfConvertingMultiLevelPartitionedTable(List *relationIdList)
{
Oid relationId;
foreach_oid(relationId, relationIdList)
{
if (PartitionedTable(relationId) && PartitionTable(relationId))
{
Oid parentRelId = PartitionParentOid(relationId);
char *parentRelationName = get_rel_name(parentRelId);
char *relationName = get_rel_name(relationId);
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("Citus does not support multi-level "
"partitioned tables"),
errdetail("Relation \"%s\" is partitioned table itself so "
"cannot be partition of relation \"%s\".",
relationName, parentRelationName)));
}
}
}
/*
* ErrorIfAnyPartitionRelationInvolvedInNonInheritedFKey searches given
* relationIdList for a partition relation involved in a foreign key relationship
@ -167,30 +256,6 @@ ErrorIfAnyPartitionRelationInvolvedInNonInheritedFKey(List *relationIdList)
}
/*
* RemovePartitionRelationIds returns a list of relation id's by removing
* partition relation id's from given relationIdList.
*/
static List *
RemovePartitionRelationIds(List *relationIdList)
{
List *nonPartitionRelationIdList = NIL;
Oid relationId = InvalidOid;
foreach_oid(relationId, relationIdList)
{
if (PartitionTable(relationId))
{
continue;
}
nonPartitionRelationIdList = lappend_oid(nonPartitionRelationIdList, relationId);
}
return nonPartitionRelationIdList;
}
/*
* EnsureSequentialModeForCitusTableCascadeFunction switches to sequential
* execution mode if needed. If it's not possible, then errors out.
@ -247,7 +312,7 @@ RelationIdListHasReferenceTable(List *relationIdList)
* GetFKeyCreationCommandsForRelationIdList returns a list of DDL commands to
* create foreign keys for each relation in relationIdList.
*/
static List *
List *
GetFKeyCreationCommandsForRelationIdList(List *relationIdList)
{
List *fKeyCreationCommands = NIL;
@ -409,7 +474,7 @@ ExecuteCascadeOperationForRelationIdList(List *relationIdList,
break;
}
case CASCADE_FKEY_ADD_LOCAL_TABLE_TO_METADATA:
case CASCADE_ADD_LOCAL_TABLE_TO_METADATA:
{
if (!IsCitusTable(relationId))
{

View File

@ -30,6 +30,7 @@
#include "distributed/commands.h"
#include "distributed/commands/sequence.h"
#include "distributed/commands/utility_hook.h"
#include "distributed/foreign_key_relationship.h"
#include "distributed/listutils.h"
#include "distributed/local_executor.h"
#include "distributed/metadata_sync.h"
@ -47,6 +48,7 @@
static void citus_add_local_table_to_metadata_internal(Oid relationId,
bool cascadeViaForeignKeys);
static void ErrorIfAddingPartitionTableToMetadata(Oid relationId);
static void ErrorIfUnsupportedCreateCitusLocalTable(Relation relation);
static void ErrorIfUnsupportedCitusLocalTableKind(Oid relationId);
static void ErrorIfUnsupportedCitusLocalColumnDefinition(Relation relation);
@ -223,6 +225,8 @@ CreateCitusLocalTable(Oid relationId, bool cascadeViaForeignKeys)
ErrorIfUnsupportedCreateCitusLocalTable(relation);
ErrorIfAddingPartitionTableToMetadata(relationId);
/*
* We immediately close relation with NoLock right after opening it. This is
* because, in this function, we may execute ALTER TABLE commands modifying
@ -232,15 +236,35 @@ CreateCitusLocalTable(Oid relationId, bool cascadeViaForeignKeys)
*/
relation_close(relation, NoLock);
bool tableHasExternalForeignKeys = TableHasExternalForeignKeys(relationId);
if (tableHasExternalForeignKeys && cascadeViaForeignKeys)
if (TableHasExternalForeignKeys(relationId))
{
if (!cascadeViaForeignKeys)
{
/*
* We do not allow creating citus local table if the table is involved in a
* foreign key relationship with "any other table", unless the option
* cascadeViaForeignKeys is given true.
* Note that we allow self references.
*/
char *qualifiedRelationName = generate_qualified_relation_name(relationId);
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("relation %s is involved in a foreign key "
"relationship with another table",
qualifiedRelationName),
errhint("Use cascade_via_foreign_keys option to add "
"all the relations involved in a foreign key "
"relationship with %s to citus metadata by "
"executing SELECT citus_add_local_table_to_metadata($$%s$$, "
"cascade_via_foreign_keys=>true)",
qualifiedRelationName, qualifiedRelationName)));
}
/*
* By acquiring AccessExclusiveLock, make sure that no modifications happen
* on the relations.
*/
CascadeOperationForConnectedRelations(relationId, lockMode,
CASCADE_FKEY_ADD_LOCAL_TABLE_TO_METADATA);
CascadeOperationForFkeyConnectedRelations(relationId, lockMode,
CASCADE_ADD_LOCAL_TABLE_TO_METADATA);
/*
* We converted every foreign key connected table in our subgraph
@ -248,23 +272,18 @@ CreateCitusLocalTable(Oid relationId, bool cascadeViaForeignKeys)
*/
return;
}
else if (tableHasExternalForeignKeys)
if (PartitionedTable(relationId))
{
/*
* We do not allow creating citus local table if the table is involved in a
* foreign key relationship with "any other table". Note that we allow self
* references.
*/
char *qualifiedRelationName = generate_qualified_relation_name(relationId);
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("relation %s is involved in a foreign key "
"relationship with another table", qualifiedRelationName),
errhint("Use cascade_via_foreign_keys option to add "
"all the relations involved in a foreign key "
"relationship with %s to citus metadata by "
"executing SELECT citus_add_local_table_to_metadata($$%s$$, "
"cascade_via_foreign_keys=>true)",
qualifiedRelationName, qualifiedRelationName)));
List *relationList = PartitionList(relationId);
if (list_length(relationList) > 0)
{
relationList = lappend_oid(relationList, relationId);
CascadeOperationForRelationIdList(relationList, AccessExclusiveLock,
CASCADE_ADD_LOCAL_TABLE_TO_METADATA);
return;
}
}
ObjectAddress tableAddress = { 0 };
@ -333,6 +352,88 @@ CreateCitusLocalTable(Oid relationId, bool cascadeViaForeignKeys)
}
/*
* CreateCitusLocalTablePartitionOf generates and executes the necessary commands
* to create a table as partition of a partitioned Citus Local Table.
* The conversion is done by CreateCitusLocalTable.
*/
void
CreateCitusLocalTablePartitionOf(CreateStmt *createStatement, Oid relationId,
Oid parentRelationId)
{
if (createStatement->partspec)
{
/*
* Since partspec represents "PARTITION BY" clause, being different than
* NULL means that given CreateStmt attempts to create a parent table
* at the same time. That means multi-level partitioning within this
* function's context. We don't support this currently.
*/
char *parentRelationName = get_rel_name(parentRelationId);
char *relationName = get_rel_name(relationId);
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("distributing multi-level partitioned tables "
"is not supported"),
errdetail("Relation \"%s\" is partitioned table itself "
"and it is also partition of relation \"%s\".",
relationName, parentRelationName)));
}
/*
* Since the shell table for the partition is not created yet on MX workers,
* we should disable DDL propagation before the DETACH command, to avoid
* getting an error on the worker.
*/
List *detachCommands = list_make3(DISABLE_DDL_PROPAGATION,
GenerateDetachPartitionCommand(relationId),
ENABLE_DDL_PROPAGATION);
char *attachCommand = GenerateAlterTableAttachPartitionCommand(relationId);
ExecuteAndLogUtilityCommandList(detachCommands);
int fKeyFlags = INCLUDE_REFERENCING_CONSTRAINTS | INCLUDE_ALL_TABLE_TYPES;
/*
* When cascadeViaForeignKeys is false, CreateCitusLocalTable doesn't expect
* any foreign keys on given relation. Note that we don't want to pass
* cascadeViaForeignKeys to be true here since we don't already allow non-inherited
* foreign keys on child relations, and for the inherited ones, we should have already
* cascaded to the other relations when creating a citus local table from parent.
*
* For this reason, we drop inherited foreign keys here, they'll anyway get created
* again with the attach command
*/
DropRelationForeignKeys(relationId, fKeyFlags);
CreateCitusLocalTable(relationId, false);
ExecuteAndLogUtilityCommand(attachCommand);
}
/*
* ErrorIfAddingPartitionTableToMetadata errors out if we try to create the
* citus local table from a partition table.
*/
static void
ErrorIfAddingPartitionTableToMetadata(Oid relationId)
{
if (PartitionTable(relationId))
{
/*
* We do not allow converting only partitions into Citus Local Tables.
* Users should call the UDF citus_add_local_table_to_metadata with the
* parent table; then the whole partitioned table will be converted.
*/
char *relationName = get_rel_name(relationId);
Oid parentRelationId = PartitionParentOid(relationId);
char *parentRelationName = get_rel_name(parentRelationId);
ereport(ERROR, (errmsg("cannot add local table %s to metadata since "
"it is a partition of %s. Instead, add the parent "
"table %s to metadata.",
relationName, parentRelationName,
parentRelationName)));
}
}
/*
* ErrorIfUnsupportedCreateCitusLocalTable errors out if we cannot create the
* citus local table from the relation.
@ -387,20 +488,14 @@ ErrorIfUnsupportedCitusLocalTableKind(Oid relationId)
"relationships", relationName)));
}
if (PartitionTable(relationId))
{
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot add local table \"%s\" to metadata, local tables "
"added to metadata cannot be partition of other tables ",
relationName)));
}
char relationKind = get_rel_relkind(relationId);
if (!(relationKind == RELKIND_RELATION || relationKind == RELKIND_FOREIGN_TABLE))
if (!(relationKind == RELKIND_RELATION || relationKind == RELKIND_FOREIGN_TABLE ||
relationKind == RELKIND_PARTITIONED_TABLE))
{
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot add local table \"%s\" to metadata, only regular "
"tables and foreign tables can be added to citus metadata ",
"tables, partitioned tables and foreign tables"
" can be added to citus metadata ",
relationName)));
}
@ -948,7 +1043,13 @@ DropDefaultColumnDefinition(Oid relationId, char *columnName)
"ALTER TABLE %s ALTER COLUMN %s DROP DEFAULT",
qualifiedRelationName, quotedColumnName);
ExecuteAndLogUtilityCommand(sequenceDropCommand->data);
/*
* We need to disable/enable ddl propagation for this command, to prevent
* sending unnecessary ALTER COLUMN commands for partitions, to MX workers.
*/
ExecuteAndLogUtilityCommandList(list_make3(DISABLE_DDL_PROPAGATION,
sequenceDropCommand->data,
ENABLE_DDL_PROPAGATION));
}
@ -971,7 +1072,15 @@ TransferSequenceOwnership(Oid sequenceId, Oid targetRelationId, char *targetColu
qualifiedSequenceName, qualifiedTargetRelationName,
quotedTargetColumnName);
ExecuteAndLogUtilityCommand(sequenceOwnershipCommand->data);
/*
* We need to disable/enable ddl propagation for this command, to prevent
* sending unnecessary ALTER SEQUENCE commands for partitions, to MX workers.
* Especially for partitioned tables, where the same sequence is used for
* all partitions, this might cause errors.
*/
ExecuteAndLogUtilityCommandList(list_make3(DISABLE_DDL_PROPAGATION,
sequenceOwnershipCommand->data,
ENABLE_DDL_PROPAGATION));
}

View File

@ -78,10 +78,6 @@ static List * GetRelationIdListFromRangeVarList(List *rangeVarList, LOCKMODE loc
static bool AlterTableCommandTypeIsTrigger(AlterTableType alterTableType);
static bool AlterTableDropsForeignKey(AlterTableStmt *alterTableStatement);
static void ErrorIfUnsupportedAlterTableStmt(AlterTableStmt *alterTableStatement);
static void ErrorIfCitusLocalTablePartitionCommand(AlterTableCmd *alterTableCmd,
Oid parentRelationId);
static Oid GetPartitionCommandChildRelationId(AlterTableCmd *alterTableCmd,
bool missingOk);
static List * InterShardDDLTaskList(Oid leftRelationId, Oid rightRelationId,
const char *commandString);
static bool AlterInvolvesPartitionColumn(AlterTableStmt *alterTableStatement,
@ -360,6 +356,13 @@ PostprocessCreateTableStmtPartitionOf(CreateStmt *createStatement, const
*/
if (IsCitusTable(parentRelationId))
{
if (IsCitusTableType(parentRelationId, CITUS_LOCAL_TABLE))
{
CreateCitusLocalTablePartitionOf(createStatement, relationId,
parentRelationId);
return;
}
Var *parentDistributionColumn = DistPartitionKeyOrError(parentRelationId);
char parentDistributionMethod = DISTRIBUTE_BY_HASH;
char *parentRelationName = generate_qualified_relation_name(parentRelationId);
@ -442,6 +445,24 @@ PreprocessAlterTableStmtAttachPartition(AlterTableStmt *alterTableStatement,
if (IsCitusTable(relationId) &&
!IsCitusTable(partitionRelationId))
{
if (IsCitusTableType(relationId, CITUS_LOCAL_TABLE))
{
if (PartitionedTable(partitionRelationId))
{
char *relationName = get_rel_name(partitionRelationId);
char *parentRelationName = get_rel_name(relationId);
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("distributing multi-level partitioned "
"tables is not supported"),
errdetail("Relation \"%s\" is partitioned table "
"itself and it is also partition of "
"relation \"%s\".",
relationName, parentRelationName)));
}
CreateCitusLocalTable(partitionRelationId, false);
return NIL;
}
Var *distributionColumn = DistPartitionKeyOrError(relationId);
char *distributionColumnName = ColumnToColumnName(relationId,
nodeToString(
@ -1113,7 +1134,23 @@ ConvertPostgresLocalTablesToCitusLocalTables(AlterTableStmt *alterTableStatement
PG_TRY();
{
bool cascade = true;
CreateCitusLocalTable(relationId, cascade);
/*
* Withoud this check, we would be erroring out in CreateCitusLocalTable
* for this case anyway. The purpose of this check&error is to provide
* a more meaningful message for the user.
*/
if (PartitionTable(relationId))
{
ereport(ERROR, (errmsg("cannot build foreign key between"
" reference table and a partition"),
errhint("Try using parent table: %s",
get_rel_name(PartitionParentOid(relationId)))));
}
else
{
CreateCitusLocalTable(relationId, cascade);
}
}
PG_CATCH();
{
@ -2477,7 +2514,17 @@ ErrorIfUnsupportedAlterTableStmt(AlterTableStmt *alterTableStatement)
"separately.")));
}
ErrorIfCitusLocalTablePartitionCommand(command, relationId);
if (IsCitusTableType(partitionRelationId, CITUS_LOCAL_TABLE) ||
IsCitusTableType(relationId, CITUS_LOCAL_TABLE))
{
/*
* Citus Local Tables cannot be colocated with other tables.
* If either of two relations is not a Citus Local Table, then we
* don't need to check colocation since CreateCitusLocalTable would
* anyway throw an error.
*/
break;
}
if (IsCitusTable(partitionRelationId) &&
!TablesColocated(relationId, partitionRelationId))
@ -2521,7 +2568,6 @@ ErrorIfUnsupportedAlterTableStmt(AlterTableStmt *alterTableStatement)
"unsupported.")));
}
#endif
ErrorIfCitusLocalTablePartitionCommand(command, relationId);
break;
}
@ -2596,52 +2642,6 @@ ErrorIfUnsupportedAlterTableStmt(AlterTableStmt *alterTableStatement)
}
/*
* ErrorIfCitusLocalTablePartitionCommand errors out if given alter table subcommand is
* an ALTER TABLE ATTACH / DETACH PARTITION command run for a citus local table.
*/
static void
ErrorIfCitusLocalTablePartitionCommand(AlterTableCmd *alterTableCmd, Oid parentRelationId)
{
AlterTableType alterTableType = alterTableCmd->subtype;
if (alterTableType != AT_AttachPartition && alterTableType != AT_DetachPartition)
{
return;
}
bool missingOK = false;
Oid childRelationId = GetPartitionCommandChildRelationId(alterTableCmd, missingOK);
if (!IsCitusTableType(parentRelationId, CITUS_LOCAL_TABLE) &&
!IsCitusTableType(childRelationId, CITUS_LOCAL_TABLE))
{
return;
}
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot execute ATTACH/DETACH PARTITION command as "
"local tables added to metadata cannot be involved in "
"partition relationships with other tables")));
}
/*
* GetPartitionCommandChildRelationId returns child relationId for given
* ALTER TABLE ATTACH / DETACH PARTITION subcommand.
*/
static Oid
GetPartitionCommandChildRelationId(AlterTableCmd *alterTableCmd, bool missingOk)
{
AlterTableType alterTableType PG_USED_FOR_ASSERTS_ONLY = alterTableCmd->subtype;
Assert(alterTableType == AT_AttachPartition || alterTableType == AT_DetachPartition);
PartitionCmd *partitionCommand = (PartitionCmd *) alterTableCmd->def;
RangeVar *childRelationRangeVar = partitionCommand->name;
Oid childRelationId = RangeVarGetRelid(childRelationRangeVar, AccessExclusiveLock,
missingOk);
return childRelationId;
}
/*
* SetupExecutionModeForAlterTable is the function that is responsible
* for two things for practical purpose for not doing the same checks

View File

@ -44,13 +44,14 @@
#include "distributed/commands.h"
#include "distributed/commands/multi_copy.h"
#include "distributed/commands/utility_hook.h" /* IWYU pragma: keep */
#include "distributed/coordinator_protocol.h"
#include "distributed/deparser.h"
#include "distributed/deparse_shard_query.h"
#include "distributed/foreign_key_relationship.h"
#include "distributed/listutils.h"
#include "distributed/local_executor.h"
#include "distributed/maintenanced.h"
#include "distributed/coordinator_protocol.h"
#include "distributed/multi_partitioning_utils.h"
#include "distributed/metadata_cache.h"
#include "distributed/metadata_sync.h"
#include "distributed/multi_executor.h"
@ -713,6 +714,12 @@ UndistributeDisconnectedCitusLocalTables(void)
}
ReleaseSysCache(heapTuple);
if (PartitionTable(citusLocalTableId))
{
/* we skip here, we'll undistribute from the parent if necessary */
continue;
}
if (ConnectedToReferenceTableViaFKey(citusLocalTableId))
{
/* still connected to a reference table, skip it */

View File

@ -1716,15 +1716,10 @@ DetachPartitionCommandList(void)
}
List *partitionList = PartitionList(cacheEntry->relationId);
Oid partitionRelationId = InvalidOid;
foreach_oid(partitionRelationId, partitionList)
{
char *detachPartitionCommand =
GenerateDetachPartitionCommand(partitionRelationId);
detachPartitionCommandList = lappend(detachPartitionCommandList,
detachPartitionCommand);
}
List *detachCommands =
GenerateDetachPartitionCommandRelationIdList(partitionList);
detachPartitionCommandList = list_concat(detachPartitionCommandList,
detachCommands);
}
if (list_length(detachPartitionCommandList) == 0)

View File

@ -227,11 +227,13 @@ PlacementAccessTypeToText(ShardPlacementAccessType accessType)
static void
RecordRelationAccessBase(Oid relationId, ShardPlacementAccessType accessType)
{
/*
* We call this only for reference tables, and we don't support partitioned
* reference tables.
*/
Assert(!PartitionedTable(relationId) && !PartitionTable(relationId));
if (IsCitusTableType(relationId, REFERENCE_TABLE))
{
/*
* We don't support partitioned reference tables.
*/
Assert(!PartitionedTable(relationId) && !PartitionTable(relationId));
}
/* make sure that this is not a conflicting access */
CheckConflictingRelationAccesses(relationId, accessType);

View File

@ -1006,6 +1006,26 @@ GenerateDetachPartitionCommand(Oid partitionTableId)
}
/*
* GenerateDetachPartitionCommandRelationIdList returns the necessary command list to
* detach the given partitions from their parents.
*/
List *
GenerateDetachPartitionCommandRelationIdList(List *relationIds)
{
List *detachPartitionCommands = NIL;
Oid relationId = InvalidOid;
foreach_oid(relationId, relationIds)
{
Assert(PartitionTable(relationId));
char *detachCommand = GenerateDetachPartitionCommand(relationId);
detachPartitionCommands = lappend(detachPartitionCommands, detachCommand);
}
return detachPartitionCommands;
}
/*
* GenereatePartitioningInformation returns the partitioning type and partition column
* for the given parent table in the form of "PARTITION TYPE (partitioning column(s)/expression(s))".
@ -1102,6 +1122,25 @@ GenerateAlterTableAttachPartitionCommand(Oid partitionTableId)
}
/*
* GenerateAttachPartitionCommandRelationIdList returns the necessary command list to
* attach the given partitions to their parents.
*/
List *
GenerateAttachPartitionCommandRelationIdList(List *relationIds)
{
List *attachPartitionCommands = NIL;
Oid relationId = InvalidOid;
foreach_oid(relationId, relationIds)
{
char *attachCommand = GenerateAlterTableAttachPartitionCommand(relationId);
attachPartitionCommands = lappend(attachPartitionCommands, attachCommand);
}
return attachPartitionCommands;
}
/*
* This function heaviliy inspired from RelationBuildPartitionDesc()
* which is avaliable in src/backend/catalog/partition.c.

View File

@ -502,7 +502,8 @@ extern Oid GetTriggerFunctionId(Oid triggerId);
/* cascade_table_operation_for_connected_relations.c */
/*
* Flags that can be passed to CascadeOperationForConnectedRelations to specify
* Flags that can be passed to CascadeOperationForFkeyConnectedRelations, and
* CascadeOperationForRelationIdList to specify
* citus table function to be executed in cascading mode.
*/
typedef enum CascadeOperationType
@ -513,14 +514,18 @@ typedef enum CascadeOperationType
CASCADE_FKEY_UNDISTRIBUTE_TABLE = 1 << 1,
/* execute CreateCitusLocalTable on each relation */
CASCADE_FKEY_ADD_LOCAL_TABLE_TO_METADATA = 1 << 2,
CASCADE_ADD_LOCAL_TABLE_TO_METADATA = 1 << 2,
} CascadeOperationType;
extern void CascadeOperationForConnectedRelations(Oid relationId, LOCKMODE relLockMode,
CascadeOperationType
cascadeOperationType);
extern void CascadeOperationForFkeyConnectedRelations(Oid relationId,
LOCKMODE relLockMode,
CascadeOperationType
cascadeOperationType);
extern void CascadeOperationForRelationIdList(List *relationIdList, LOCKMODE lockMode,
CascadeOperationType cascadeOperationType);
extern void ErrorIfAnyPartitionRelationInvolvedInNonInheritedFKey(List *relationIdList);
extern bool RelationIdListHasReferenceTable(List *relationIdList);
extern List * GetFKeyCreationCommandsForRelationIdList(List *relationIdList);
extern void DropRelationForeignKeys(Oid relationId, int flags);
extern void SetLocalEnableLocalReferenceForeignKeys(bool state);
extern void ExecuteAndLogUtilityCommandList(List *ddlCommandList);
@ -538,5 +543,7 @@ extern void PostprocessVariableSetStmt(VariableSetStmt *setStmt, const char *set
/* create_citus_local_table.c */
extern void CreateCitusLocalTable(Oid relationId, bool cascade);
extern void CreateCitusLocalTablePartitionOf(CreateStmt *createStatement,
Oid relationId, Oid parentRelationId);
#endif /*CITUS_COMMANDS_H */

View File

@ -22,8 +22,10 @@ extern Oid PartitionParentOid(Oid partitionOid);
extern Oid PartitionWithLongestNameRelationId(Oid parentRelationId);
extern List * PartitionList(Oid parentRelationId);
extern char * GenerateDetachPartitionCommand(Oid partitionTableId);
extern List * GenerateDetachPartitionCommandRelationIdList(List *relationIds);
extern char * GenerateAttachShardPartitionCommand(ShardInterval *shardInterval);
extern char * GenerateAlterTableAttachPartitionCommand(Oid partitionTableId);
extern List * GenerateAttachPartitionCommandRelationIdList(List *relationIds);
extern char * GeneratePartitioningInformation(Oid tableId);
extern void FixPartitionConstraintsOnWorkers(Oid relationId);
extern void FixLocalPartitionConstraints(Oid relationId, int64 shardId);

View File

@ -447,7 +447,68 @@ NOTICE: executing the command locally: SELECT value FROM citus_local_table_trig
100
(2 rows)
ROLLBACK;
-- test on partitioned citus local tables
CREATE TABLE par_citus_local_table (val int) PARTITION BY RANGE(val);
CREATE TABLE par_citus_local_table_1 PARTITION OF par_citus_local_table FOR VALUES FROM (1) TO (10000);
CREATE TABLE par_another_citus_local_table (val int unique) PARTITION BY RANGE(val);
CREATE TABLE par_another_citus_local_table_1 PARTITION OF par_another_citus_local_table FOR VALUES FROM (1) TO (10000);
ALTER TABLE par_another_citus_local_table ADD CONSTRAINT fkey_self FOREIGN KEY(val) REFERENCES par_another_citus_local_table(val);
ALTER TABLE par_citus_local_table ADD CONSTRAINT fkey_c_to_c FOREIGN KEY(val) REFERENCES par_another_citus_local_table(val) ON UPDATE CASCADE;
SELECT citus_add_local_table_to_metadata('par_another_citus_local_table', cascade_via_foreign_keys=>true);
NOTICE: executing the command locally: SELECT worker_apply_inter_shard_ddl_command (1507011, 'citus_local_table_triggers', 1507012, 'citus_local_table_triggers', 'ALTER TABLE citus_local_table_triggers.par_another_citus_local_table ATTACH PARTITION citus_local_table_triggers.par_another_citus_local_table_1 FOR VALUES FROM (1) TO (10000);')
NOTICE: executing the command locally: SELECT worker_apply_inter_shard_ddl_command (1507013, 'citus_local_table_triggers', 1507014, 'citus_local_table_triggers', 'ALTER TABLE citus_local_table_triggers.par_citus_local_table ATTACH PARTITION citus_local_table_triggers.par_citus_local_table_1 FOR VALUES FROM (1) TO (10000);')
NOTICE: executing the command locally: SELECT worker_apply_inter_shard_ddl_command (1507011, 'citus_local_table_triggers', 1507011, 'citus_local_table_triggers', 'ALTER TABLE citus_local_table_triggers.par_another_citus_local_table ADD CONSTRAINT fkey_self FOREIGN KEY (val) REFERENCES citus_local_table_triggers.par_another_citus_local_table(val)')
NOTICE: executing the command locally: SELECT worker_apply_inter_shard_ddl_command (1507013, 'citus_local_table_triggers', 1507011, 'citus_local_table_triggers', 'ALTER TABLE citus_local_table_triggers.par_citus_local_table ADD CONSTRAINT fkey_c_to_c FOREIGN KEY (val) REFERENCES citus_local_table_triggers.par_another_citus_local_table(val) ON UPDATE CASCADE')
citus_add_local_table_to_metadata
---------------------------------------------------------------------
(1 row)
CREATE TABLE par_reference_table(val int);
SELECT create_reference_table('par_reference_table');
create_reference_table
---------------------------------------------------------------------
(1 row)
CREATE FUNCTION par_insert_100() RETURNS trigger AS $par_insert_100$
BEGIN
INSERT INTO par_reference_table VALUES (100);
RETURN NEW;
END;
$par_insert_100$ LANGUAGE plpgsql;
BEGIN;
CREATE TRIGGER par_insert_100_trigger
AFTER TRUNCATE ON par_another_citus_local_table
FOR EACH STATEMENT EXECUTE FUNCTION par_insert_100();
CREATE TRIGGER insert_100_trigger
AFTER TRUNCATE ON par_citus_local_table
FOR EACH STATEMENT EXECUTE FUNCTION par_insert_100();
TRUNCATE par_another_citus_local_table CASCADE;
NOTICE: truncate cascades to table "par_citus_local_table"
NOTICE: truncate cascades to table "par_citus_local_table_1"
NOTICE: executing the command locally: INSERT INTO citus_local_table_triggers.par_reference_table_1507015 (val) VALUES (100)
NOTICE: executing the command locally: TRUNCATE TABLE citus_local_table_triggers.par_another_citus_local_table_xxxxx CASCADE
NOTICE: truncate cascades to table "par_citus_local_table_xxxxx"
NOTICE: truncate cascades to table "par_citus_local_table_1_xxxxx"
NOTICE: executing the command locally: TRUNCATE TABLE citus_local_table_triggers.par_another_citus_local_table_1_xxxxx CASCADE
NOTICE: truncate cascades to table "par_citus_local_table_xxxxx"
NOTICE: truncate cascades to table "par_citus_local_table_1_xxxxx"
NOTICE: truncate cascades to table "par_another_citus_local_table_xxxxx"
NOTICE: executing the command locally: INSERT INTO citus_local_table_triggers.par_reference_table_1507015 (val) VALUES (100)
NOTICE: executing the command locally: TRUNCATE TABLE citus_local_table_triggers.par_citus_local_table_xxxxx CASCADE
NOTICE: executing the command locally: TRUNCATE TABLE citus_local_table_triggers.par_citus_local_table_1_xxxxx CASCADE
-- we should see two rows with "100"
SELECT * FROM par_reference_table;
NOTICE: executing the command locally: SELECT val FROM citus_local_table_triggers.par_reference_table_1507015 par_reference_table
val
---------------------------------------------------------------------
100
100
(2 rows)
ROLLBACK;
-- cleanup at exit
DROP SCHEMA citus_local_table_triggers, "interesting!schema" CASCADE;
NOTICE: drop cascades to 13 other objects
NOTICE: drop cascades to 20 other objects

View File

@ -123,50 +123,6 @@ SELECT create_distributed_table('distributed_table', 'a');
-- cannot create citus local table from an existing citus table
SELECT citus_add_local_table_to_metadata('distributed_table');
ERROR: table "distributed_table" is already distributed
-- partitioned table tests --
CREATE TABLE partitioned_table(a int, b int) PARTITION BY RANGE (a);
CREATE TABLE partitioned_table_1 PARTITION OF partitioned_table FOR VALUES FROM (0) TO (10);
CREATE TABLE partitioned_table_2 PARTITION OF partitioned_table FOR VALUES FROM (10) TO (20);
-- cannot create partitioned citus local tables
SELECT citus_add_local_table_to_metadata('partitioned_table');
ERROR: cannot add local table "partitioned_table" to metadata, only regular tables and foreign tables can be added to citus metadata
BEGIN;
CREATE TABLE citus_local_table PARTITION OF partitioned_table FOR VALUES FROM (20) TO (30);
-- cannot create citus local table as a partition of a local table
SELECT citus_add_local_table_to_metadata('citus_local_table');
ERROR: cannot add local table "citus_local_table" to metadata, local tables added to metadata cannot be partition of other tables
ROLLBACK;
BEGIN;
CREATE TABLE citus_local_table (a int, b int);
SELECT citus_add_local_table_to_metadata('citus_local_table');
citus_add_local_table_to_metadata
---------------------------------------------------------------------
(1 row)
-- cannot create citus local table as a partition of a local table
-- via ALTER TABLE commands as well
ALTER TABLE partitioned_table ATTACH PARTITION citus_local_table FOR VALUES FROM (20) TO (30);
ERROR: non-distributed tables cannot have distributed partitions
ROLLBACK;
BEGIN;
SELECT create_distributed_table('partitioned_table', 'a');
create_distributed_table
---------------------------------------------------------------------
(1 row)
CREATE TABLE citus_local_table (a int, b int);
SELECT citus_add_local_table_to_metadata('citus_local_table');
citus_add_local_table_to_metadata
---------------------------------------------------------------------
(1 row)
-- cannot attach citus local table to a partitioned distributed table
ALTER TABLE partitioned_table ATTACH PARTITION citus_local_table FOR VALUES FROM (20) TO (30);
ERROR: cannot execute ATTACH/DETACH PARTITION command as local tables added to metadata cannot be involved in partition relationships with other tables
ROLLBACK;
-- show that we do not support inheritance relationships --
CREATE TABLE parent_table (a int, b text);
CREATE TABLE child_table () INHERITS (parent_table);
@ -203,11 +159,11 @@ BEGIN;
(1 row)
INSERT INTO citus_local_table_3 VALUES (1);
NOTICE: executing the command locally: INSERT INTO citus_local_tables_test_schema.citus_local_table_3_1504024 (value) VALUES (1)
NOTICE: executing the command locally: UPDATE citus_local_tables_test_schema.citus_local_table_3_1504024 citus_local_table_3 SET value = (value OPERATOR(pg_catalog.+) 1)
NOTICE: executing the command locally: INSERT INTO citus_local_tables_test_schema.citus_local_table_3_1504010 (value) VALUES (1)
NOTICE: executing the command locally: UPDATE citus_local_tables_test_schema.citus_local_table_3_1504010 citus_local_table_3 SET value = (value OPERATOR(pg_catalog.+) 1)
-- show that trigger is executed only once, we should see "2" (not "3")
SELECT * FROM citus_local_table_3;
NOTICE: executing the command locally: SELECT value FROM citus_local_tables_test_schema.citus_local_table_3_1504024 citus_local_table_3
NOTICE: executing the command locally: SELECT value FROM citus_local_tables_test_schema.citus_local_table_3_1504010 citus_local_table_3
value
---------------------------------------------------------------------
2
@ -334,13 +290,13 @@ ERROR: relation "citus_local_table_1" is a local table
SELECT get_shard_id_for_distribution_column('citus_local_table_1', 'not_checking_this_arg_for_non_dist_tables');
get_shard_id_for_distribution_column
---------------------------------------------------------------------
1504027
1504013
(1 row)
SELECT get_shard_id_for_distribution_column('citus_local_table_1');
get_shard_id_for_distribution_column
---------------------------------------------------------------------
1504027
1504013
(1 row)
-- master_copy_shard_placement is not supported
@ -352,7 +308,7 @@ BEGIN;
SELECT undistribute_table('citus_local_table_1');
NOTICE: creating a new table for citus_local_tables_test_schema.citus_local_table_1
NOTICE: moving the data of citus_local_tables_test_schema.citus_local_table_1
NOTICE: executing the command locally: SELECT a FROM citus_local_tables_test_schema.citus_local_table_1_1504027 citus_local_table_1
NOTICE: executing the command locally: SELECT a FROM citus_local_tables_test_schema.citus_local_table_1_1504013 citus_local_table_1
NOTICE: dropping the old citus_local_tables_test_schema.citus_local_table_1
NOTICE: executing the command locally: DROP TABLE IF EXISTS citus_local_tables_test_schema.citus_local_table_1_xxxxx CASCADE
NOTICE: renaming the new table to citus_local_tables_test_schema.citus_local_table_1
@ -395,7 +351,7 @@ SELECT citus_add_local_table_to_metadata('"CiTUS!LocalTables"."LocalTabLE.1!?!"'
-- drop the table before creating it when the search path is set
SET search_path to "CiTUS!LocalTables" ;
DROP TABLE "LocalTabLE.1!?!";
NOTICE: executing the command locally: DROP TABLE IF EXISTS "CiTUS!LocalTables"."LocalTabLE.1!?!_1504035" CASCADE
NOTICE: executing the command locally: DROP TABLE IF EXISTS "CiTUS!LocalTables"."LocalTabLE.1!?!_1504021" CASCADE
-- have a custom type in the local table
CREATE TYPE local_type AS (key int, value jsonb);
-- create btree_gist for GiST index
@ -445,10 +401,10 @@ SELECT citus_add_local_table_to_metadata('"LocalTabLE.1!?!9012345678901234567890
-- create some objects after citus_add_local_table_to_metadata
CREATE INDEX "my!Index2" ON "LocalTabLE.1!?!9012345678901234567890123456789012345678901234567890123456789"(id) WITH ( fillfactor = 90 ) WHERE id < 20;
NOTICE: identifier "LocalTabLE.1!?!9012345678901234567890123456789012345678901234567890123456789" will be truncated to "LocalTabLE.1!?!901234567890123456789012345678901234567890123456"
NOTICE: executing the command locally: CREATE INDEX "my!Index2_1504036" ON "CiTUS!LocalTables"."LocalTabLE.1!?!9012345678901234567890123456789_7e923997_1504036" USING btree (id ) WITH (fillfactor = '90' )WHERE (id < 20)
NOTICE: executing the command locally: CREATE INDEX "my!Index2_1504022" ON "CiTUS!LocalTables"."LocalTabLE.1!?!9012345678901234567890123456789_7e923997_1504022" USING btree (id ) WITH (fillfactor = '90' )WHERE (id < 20)
CREATE UNIQUE INDEX uniqueIndex2 ON "LocalTabLE.1!?!9012345678901234567890123456789012345678901234567890123456789"(id);
NOTICE: identifier "LocalTabLE.1!?!9012345678901234567890123456789012345678901234567890123456789" will be truncated to "LocalTabLE.1!?!901234567890123456789012345678901234567890123456"
NOTICE: executing the command locally: CREATE UNIQUE INDEX uniqueindex2_1504036 ON "CiTUS!LocalTables"."LocalTabLE.1!?!9012345678901234567890123456789_7e923997_1504036" USING btree (id )
NOTICE: executing the command locally: CREATE UNIQUE INDEX uniqueindex2_1504022 ON "CiTUS!LocalTables"."LocalTabLE.1!?!9012345678901234567890123456789_7e923997_1504022" USING btree (id )
---------------------------------------------------------------------
---- utility command execution ----
---------------------------------------------------------------------
@ -537,7 +493,7 @@ CREATE TABLE local_table_4 (
b int references local_table_4(a));
NOTICE: executing the command locally: SELECT worker_apply_inter_shard_ddl_command (xxxxx, 'citus_local_tables_test_schema', xxxxx, 'citus_local_tables_test_schema', 'ALTER TABLE citus_local_tables_test_schema.local_table_4 ADD CONSTRAINT local_table_4_a_fkey FOREIGN KEY (a) REFERENCES citus_local_tables_test_schema.citus_local_table_1(a)')
ALTER TABLE citus_local_table_1 ADD COLUMN b int NOT NULL;
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1504027, 'citus_local_tables_test_schema', 'ALTER TABLE citus_local_table_1 ADD COLUMN b int NOT NULL;')
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1504013, 'citus_local_tables_test_schema', 'ALTER TABLE citus_local_table_1 ADD COLUMN b int NOT NULL;')
-- show that we added column with NOT NULL
SELECT table_name, column_name, is_nullable
FROM INFORMATION_SCHEMA.COLUMNS
@ -546,11 +502,11 @@ ORDER BY 1;
table_name | column_name | is_nullable
---------------------------------------------------------------------
citus_local_table_1 | b | NO
citus_local_table_1_1504027 | b | NO
citus_local_table_1_1504013 | b | NO
(2 rows)
ALTER TABLE citus_local_table_1 ADD CONSTRAINT unique_a_b UNIQUE (a, b);
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1504027, 'citus_local_tables_test_schema', 'ALTER TABLE citus_local_table_1 ADD CONSTRAINT unique_a_b UNIQUE (a, b);')
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1504013, 'citus_local_tables_test_schema', 'ALTER TABLE citus_local_table_1 ADD CONSTRAINT unique_a_b UNIQUE (a, b);')
-- show that we defined unique constraints
SELECT conrelid::regclass, conname, conkey
FROM pg_constraint
@ -558,12 +514,12 @@ WHERE conrelid::regclass::text LIKE 'citus_local_table_1%' AND contype = 'u'
ORDER BY 1;
conrelid | conname | conkey
---------------------------------------------------------------------
citus_local_table_1_1504027 | unique_a_b_1504027 | {1,2}
citus_local_table_1_1504013 | unique_a_b_1504013 | {1,2}
citus_local_table_1 | unique_a_b | {1,2}
(2 rows)
CREATE UNIQUE INDEX citus_local_table_1_idx ON citus_local_table_1(b);
NOTICE: executing the command locally: CREATE UNIQUE INDEX citus_local_table_1_idx_1504027 ON citus_local_tables_test_schema.citus_local_table_1_1504027 USING btree (b )
NOTICE: executing the command locally: CREATE UNIQUE INDEX citus_local_table_1_idx_1504013 ON citus_local_tables_test_schema.citus_local_table_1_1504013 USING btree (b )
-- show that we successfully defined the unique index
SELECT indexrelid::regclass, indrelid::regclass, indkey
FROM pg_index
@ -572,7 +528,7 @@ ORDER BY 1;
indexrelid | indrelid | indkey
---------------------------------------------------------------------
unique_a_b | citus_local_table_1 | 1 2
unique_a_b_1504027 | citus_local_table_1_1504027 | 1 2
unique_a_b_1504013 | citus_local_table_1_1504013 | 1 2
(2 rows)
-- test creating citus local table with an index from non-default schema
@ -580,7 +536,7 @@ CREATE SCHEMA "test_\'index_schema";
CREATE TABLE "test_\'index_schema".testindex (a int, b int);
CREATE INDEX ind ON "test_\'index_schema".testindex (a);
ALTER TABLE "test_\'index_schema".testindex ADD CONSTRAINT fkey_to_dummy_ref FOREIGN KEY (a) REFERENCES dummy_reference_table(a);
NOTICE: executing the command locally: SELECT worker_apply_inter_shard_ddl_command (1504040, E'test_\\''index_schema', 1504037, 'citus_local_tables_test_schema', E'ALTER TABLE "test_\\''index_schema".testindex ADD CONSTRAINT fkey_to_dummy_ref FOREIGN KEY (a) REFERENCES dummy_reference_table(a);')
NOTICE: executing the command locally: SELECT worker_apply_inter_shard_ddl_command (1504026, E'test_\\''index_schema', 1504023, 'citus_local_tables_test_schema', E'ALTER TABLE "test_\\''index_schema".testindex ADD CONSTRAINT fkey_to_dummy_ref FOREIGN KEY (a) REFERENCES dummy_reference_table(a);')
SELECT COUNT(*)=2 FROM pg_indexes WHERE tablename LIKE 'testindex%' AND indexname LIKE 'ind%';
?column?
---------------------------------------------------------------------
@ -605,7 +561,7 @@ DROP TABLE citus_local_table_1, citus_local_table_2, distributed_table, local_ta
NOTICE: executing the command locally: DROP TABLE IF EXISTS citus_local_tables_test_schema.local_table_4_xxxxx CASCADE
NOTICE: executing the command locally: DROP TABLE IF EXISTS citus_local_tables_test_schema.reference_table_xxxxx CASCADE
NOTICE: executing the command locally: DROP TABLE IF EXISTS citus_local_tables_test_schema.local_table_xxxxx CASCADE
NOTICE: drop cascades to constraint fkey_c_to_local_1504027 on table citus_local_tables_test_schema.citus_local_table_1_1504027
NOTICE: drop cascades to constraint fkey_c_to_local_1504013 on table citus_local_tables_test_schema.citus_local_table_1_1504013
NOTICE: executing the command locally: DROP TABLE IF EXISTS citus_local_tables_test_schema.citus_local_table_2_xxxxx CASCADE
NOTICE: executing the command locally: DROP TABLE IF EXISTS citus_local_tables_test_schema.citus_local_table_1_xxxxx CASCADE
-- test some other udf's with citus local tables
@ -793,7 +749,7 @@ CREATE STATISTICS stx1 ON a, b FROM test_citus_local_table_with_stats;
ALTER TABLE test_citus_local_table_with_stats ADD CONSTRAINT fkey_to_dummy_ref FOREIGN KEY (a) REFERENCES dummy_reference_table(a);
NOTICE: executing the command locally: SELECT worker_apply_inter_shard_ddl_command (xxxxx, 'citus_local_tables_test_schema', xxxxx, 'citus_local_tables_test_schema', 'ALTER TABLE test_citus_local_table_with_stats ADD CONSTRAINT fkey_to_dummy_ref FOREIGN KEY (a) REFERENCES dummy_reference_table(a);')
CREATE STATISTICS "CiTUS!LocalTables"."Bad\'StatName" ON a, b FROM test_citus_local_table_with_stats;
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1504044, 'citus_local_tables_test_schema', E'CREATE STATISTICS "CiTUS!LocalTables"."Bad\\''StatName" ON a, b FROM citus_local_tables_test_schema.test_citus_local_table_with_stats')
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1504030, 'citus_local_tables_test_schema', E'CREATE STATISTICS "CiTUS!LocalTables"."Bad\\''StatName" ON a, b FROM citus_local_tables_test_schema.test_citus_local_table_with_stats')
SELECT COUNT(*)=4 FROM pg_statistic_ext WHERE stxname LIKE 'stx1%' or stxname LIKE 'Bad\\''StatName%' ;
?column?
---------------------------------------------------------------------
@ -814,6 +770,205 @@ NOTICE: truncate cascades to table "referencing_table_xxxxxxx"
NOTICE: executing the command locally: TRUNCATE TABLE citus_local_tables_test_schema.referencing_table_xxxxx CASCADE
RESET client_min_messages;
\set VERBOSITY terse
-- test for partitioned tables
SET client_min_messages TO ERROR;
-- verify we can convert partitioned tables into Citus Local Tables
CREATE TABLE partitioned (user_id int, time timestamp with time zone, data jsonb, PRIMARY KEY (user_id, time )) PARTITION BY RANGE ("time");
CREATE TABLE partition1 PARTITION OF partitioned FOR VALUES FROM ('2018-04-13 00:00:00+00') TO ('2018-04-14 00:00:00+00');
CREATE TABLE partition2 PARTITION OF partitioned FOR VALUES FROM ('2018-04-14 00:00:00+00') TO ('2018-04-15 00:00:00+00');
SELECT citus_add_local_table_to_metadata('partitioned');
citus_add_local_table_to_metadata
---------------------------------------------------------------------
(1 row)
-- partitions added after the conversion get converted into CLT as well
CREATE TABLE partition3 PARTITION OF partitioned FOR VALUES FROM ('2018-04-15 00:00:00+00') TO ('2018-04-16 00:00:00+00');
--verify partitioning hierarchy is preserved after conversion
select inhrelid::regclass from pg_inherits where inhparent='partitioned'::regclass order by 1;
inhrelid
---------------------------------------------------------------------
partition1
partition2
partition3
(3 rows)
SELECT partition, from_value, to_value, access_method
FROM time_partitions
WHERE partition::text LIKE '%partition%'
ORDER BY partition::text;
partition | from_value | to_value | access_method
---------------------------------------------------------------------
partition1 | Thu Apr 12 17:00:00 2018 PDT | Fri Apr 13 17:00:00 2018 PDT | heap
partition1_1504031 | Thu Apr 12 17:00:00 2018 PDT | Fri Apr 13 17:00:00 2018 PDT | heap
partition2 | Fri Apr 13 17:00:00 2018 PDT | Sat Apr 14 17:00:00 2018 PDT | heap
partition2_1504032 | Fri Apr 13 17:00:00 2018 PDT | Sat Apr 14 17:00:00 2018 PDT | heap
partition3 | Sat Apr 14 17:00:00 2018 PDT | Sun Apr 15 17:00:00 2018 PDT | heap
partition3_1504034 | Sat Apr 14 17:00:00 2018 PDT | Sun Apr 15 17:00:00 2018 PDT | heap
(6 rows)
-- undistribute succesfully
SELECT undistribute_table('partitioned');
undistribute_table
---------------------------------------------------------------------
(1 row)
-- verify the partitioning hierarchy is preserved after undistributing
select inhrelid::regclass from pg_inherits where inhparent='partitioned'::regclass order by 1;
inhrelid
---------------------------------------------------------------------
partition1
partition2
partition3
(3 rows)
-- verify table is undistributed
SELECT relname FROM pg_class WHERE relname LIKE 'partition3%' AND relnamespace IN
(SELECT oid FROM pg_namespace WHERE nspname = 'citus_local_tables_test_schema')
ORDER BY relname;
relname
---------------------------------------------------------------------
partition3
partition3_pkey
(2 rows)
-- drop successfully
DROP TABLE partitioned;
-- test creating distributed tables from partitioned citus local tables
CREATE TABLE partitioned_distributed (a INT UNIQUE) PARTITION BY RANGE(a);
CREATE TABLE partitioned_distributed_1 PARTITION OF partitioned_distributed FOR VALUES FROM (1) TO (4);
CREATE TABLE partitioned_distributed_2 PARTITION OF partitioned_distributed FOR VALUES FROM (5) TO (8);
SELECT citus_add_local_table_to_metadata('partitioned_distributed');
citus_add_local_table_to_metadata
---------------------------------------------------------------------
(1 row)
SELECT create_distributed_table('partitioned_distributed','a');
create_distributed_table
---------------------------------------------------------------------
(1 row)
\c - - - :worker_1_port
SELECT relname FROM pg_class
WHERE relname LIKE 'partitioned_distributed%'
AND relnamespace IN (SELECT oid FROM pg_namespace WHERE nspname = 'citus_local_tables_test_schema')
ORDER BY relname;
relname
---------------------------------------------------------------------
partitioned_distributed_1504038
partitioned_distributed_1504040
partitioned_distributed_1_1504042
partitioned_distributed_1_1504044
partitioned_distributed_1_a_key_1504042
partitioned_distributed_1_a_key_1504044
partitioned_distributed_2_1504046
partitioned_distributed_2_1504048
partitioned_distributed_2_a_key_1504046
partitioned_distributed_2_a_key_1504048
partitioned_distributed_a_key_1504038
partitioned_distributed_a_key_1504040
(12 rows)
\c - - - :master_port
SET search_path TO citus_local_tables_test_schema;
-- error out if converting multi-level partitioned table
CREATE TABLE multi_par (id text, country text) PARTITION BY RANGE (id);
ALTER TABLE multi_par ADD CONSTRAINT unique_constraint UNIQUE (id, country);
CREATE TABLE multi_par_a_to_i PARTITION OF multi_par FOR VALUES FROM ('a') TO ('j');
-- multi-level partitioning
CREATE TABLE multi_par_j_to_r PARTITION OF multi_par FOR VALUES FROM ('j') TO ('s') PARTITION BY LIST (country);
CREATE TABLE multi_par_j_to_r_japan PARTITION OF multi_par_j_to_r FOR VALUES IN ('japan');
-- these two should error out
SELECT citus_add_local_table_to_metadata('multi_par');
ERROR: Citus does not support multi-level partitioned tables
SELECT citus_add_local_table_to_metadata('multi_par',cascade_via_foreign_keys=>true);
ERROR: Citus does not support multi-level partitioned tables
-- should error out when cascading via fkeys as well
CREATE TABLE cas_1 (a text, b text);
ALTER TABLE cas_1 ADD CONSTRAINT unique_constraint_2 UNIQUE (a, b);
ALTER TABLE cas_1 ADD CONSTRAINT fkey_to_multi_parti FOREIGN KEY (a,b) REFERENCES multi_par(id, country);
SELECT citus_add_local_table_to_metadata('cas_1');
ERROR: relation citus_local_tables_test_schema.cas_1 is involved in a foreign key relationship with another table
SELECT citus_add_local_table_to_metadata('cas_1', cascade_via_foreign_keys=>true);
ERROR: Citus does not support multi-level partitioned tables
SELECT create_reference_table('cas_1');
ERROR: Citus does not support multi-level partitioned tables
ALTER TABLE cas_1 DROP CONSTRAINT fkey_to_multi_parti;
SELECT create_reference_table('cas_1');
create_reference_table
---------------------------------------------------------------------
(1 row)
ALTER TABLE cas_1 ADD CONSTRAINT fkey_to_multi_parti FOREIGN KEY (a,b) REFERENCES multi_par(id, country);
ERROR: Citus does not support multi-level partitioned tables
-- undistribute tables to avoid unnecessary log messages later
select undistribute_table('citus_local_table_4', cascade_via_foreign_keys=>true);
NOTICE: creating a new table for citus_local_tables_test_schema.citus_local_table_4
NOTICE: moving the data of citus_local_tables_test_schema.citus_local_table_4
NOTICE: dropping the old citus_local_tables_test_schema.citus_local_table_4
NOTICE: renaming the new table to citus_local_tables_test_schema.citus_local_table_4
undistribute_table
---------------------------------------------------------------------
(1 row)
select undistribute_table('referencing_table', cascade_via_foreign_keys=>true);
NOTICE: creating a new table for citus_local_tables_test_schema.referencing_table
NOTICE: moving the data of citus_local_tables_test_schema.referencing_table
NOTICE: dropping the old citus_local_tables_test_schema.referencing_table
NOTICE: renaming the new table to citus_local_tables_test_schema.referencing_table
NOTICE: creating a new table for citus_local_tables_test_schema.referenced_table
NOTICE: moving the data of citus_local_tables_test_schema.referenced_table
NOTICE: dropping the old citus_local_tables_test_schema.referenced_table
NOTICE: renaming the new table to citus_local_tables_test_schema.referenced_table
undistribute_table
---------------------------------------------------------------------
(1 row)
-- test dropping fkey
CREATE TABLE parent_2_child_1 (a int);
CREATE TABLE parent_1_child_1 (a int);
CREATE TABLE parent_2 (a INT UNIQUE) PARTITION BY RANGE(a);
CREATE TABLE parent_1 (a INT UNIQUE) PARTITION BY RANGE(a);
alter table parent_1 attach partition parent_1_child_1 default ;
alter table parent_2 attach partition parent_2_child_1 default ;
CREATE TABLE ref_table(a int unique);
alter table parent_1 add constraint fkey_test_drop foreign key(a) references ref_table(a);
alter table parent_2 add constraint fkey1 foreign key(a) references ref_table(a);
alter table parent_1 add constraint fkey2 foreign key(a) references parent_2(a);
SELECT create_reference_table('ref_table');
create_reference_table
---------------------------------------------------------------------
(1 row)
alter table parent_1 drop constraint fkey_test_drop;
select count(*) from pg_constraint where conname = 'fkey_test_drop';
count
---------------------------------------------------------------------
0
(1 row)
-- verify we still preserve the child-parent hierarchy after all conversions
-- check the shard partition
select inhrelid::regclass from pg_inherits where (select inhparent::regclass::text) ~ '^parent_1_\d{7}$' order by 1;
inhrelid
---------------------------------------------------------------------
parent_1_child_1_1190085
(1 row)
-- check the shell partition
select inhrelid::regclass from pg_inherits where inhparent='parent_1'::regclass order by 1;
inhrelid
---------------------------------------------------------------------
parent_1_child_1
(1 row)
-- cleanup at exit
SET client_min_messages TO ERROR;
DROP SCHEMA citus_local_tables_test_schema, "CiTUS!LocalTables", "test_\'index_schema" CASCADE;
NOTICE: drop cascades to 27 other objects

View File

@ -239,6 +239,412 @@ SELECT stxname FROM pg_statistic_ext ORDER BY stxname;
\c - - - :master_port
SET search_path TO citus_local_tables_mx;
-- undistribute old tables to prevent unnecessary undistribute logs later
SELECT undistribute_table('citus_local_table', cascade_via_foreign_keys=>true);
NOTICE: creating a new table for citus_local_tables_mx.citus_local_table
NOTICE: moving the data of citus_local_tables_mx.citus_local_table
NOTICE: dropping the old citus_local_tables_mx.citus_local_table
NOTICE: renaming the new table to citus_local_tables_mx.citus_local_table
undistribute_table
---------------------------------------------------------------------
(1 row)
SELECT undistribute_table('citus_local_table_3', cascade_via_foreign_keys=>true);
NOTICE: creating a new table for citus_local_tables_mx.citus_local_table_3
NOTICE: moving the data of citus_local_tables_mx.citus_local_table_3
NOTICE: dropping the old citus_local_tables_mx.citus_local_table_3
NOTICE: renaming the new table to citus_local_tables_mx.citus_local_table_3
NOTICE: creating a new table for citus_local_tables_mx.citus_local_table_4
NOTICE: moving the data of citus_local_tables_mx.citus_local_table_4
NOTICE: dropping the old citus_local_tables_mx.citus_local_table_4
NOTICE: renaming the new table to citus_local_tables_mx.citus_local_table_4
undistribute_table
---------------------------------------------------------------------
(1 row)
SELECT undistribute_table('citus_local_table_stats', cascade_via_foreign_keys=>true);
NOTICE: creating a new table for citus_local_tables_mx.citus_local_table_stats
NOTICE: moving the data of citus_local_tables_mx.citus_local_table_stats
NOTICE: dropping the old citus_local_tables_mx.citus_local_table_stats
NOTICE: renaming the new table to citus_local_tables_mx.citus_local_table_stats
undistribute_table
---------------------------------------------------------------------
(1 row)
-- verify that mx nodes have the shell table for partitioned citus local tables
CREATE TABLE local_table_fkey(a INT UNIQUE);
CREATE TABLE local_table_fkey2(a INT UNIQUE);
CREATE TABLE partitioned_mx (a INT UNIQUE) PARTITION BY RANGE(a);
ALTER TABLE partitioned_mx ADD CONSTRAINT fkey_to_local FOREIGN KEY (a) REFERENCES local_table_fkey(a);
CREATE TABLE IF NOT EXISTS partitioned_mx_1 PARTITION OF partitioned_mx FOR VALUES FROM (1) TO (4);
CREATE TABLE partitioned_mx_2 (a INT UNIQUE);
ALTER TABLE partitioned_mx ATTACH PARTITION partitioned_mx_2 FOR VALUES FROM (5) TO (8);
SELECT create_reference_table('local_table_fkey');
create_reference_table
---------------------------------------------------------------------
(1 row)
CREATE TABLE partitioned_mx_3 (a INT UNIQUE);
ALTER TABLE partitioned_mx ATTACH PARTITION partitioned_mx_3 FOR VALUES FROM (9) TO (12);
-- these should error out since multi-level partitioned citus local tables are not supported
CREATE TABLE IF NOT EXISTS partitioned_mx_4 PARTITION OF partitioned_mx FOR VALUES FROM (13) TO (16) PARTITION BY RANGE (a);
ERROR: distributing multi-level partitioned tables is not supported
BEGIN;
CREATE TABLE partitioned_mx_4(a INT UNIQUE) PARTITION BY RANGE (a);
alter table partitioned_mx attach partition partitioned_mx_4 FOR VALUES FROM (13) TO (16);
ERROR: distributing multi-level partitioned tables is not supported
END;
CREATE TABLE multi_level_p (a INT UNIQUE) PARTITION BY RANGE (a);
CREATE TABLE IF NOT EXISTS multi_level_c PARTITION OF multi_level_p FOR VALUES FROM (13) TO (16) PARTITION BY RANGE (a);
select citus_add_local_table_to_metadata('multi_level_p'); --errors
ERROR: Citus does not support multi-level partitioned tables
select citus_add_local_table_to_metadata('multi_level_p', true); --errors
ERROR: Citus does not support multi-level partitioned tables
-- try attaching a partition with an external foreign key
CREATE TABLE partitioned_mx_4 (a INT UNIQUE);
ALTER TABLE partitioned_mx_4 ADD CONSTRAINT fkey_not_inherited FOREIGN KEY (a) REFERENCES local_table_fkey2(a);
-- these two should error out
ALTER TABLE partitioned_mx ATTACH PARTITION partitioned_mx_4 FOR VALUES FROM (13) TO (16);
ERROR: relation citus_local_tables_mx.partitioned_mx_4 is involved in a foreign key relationship with another table
ALTER TABLE partitioned_mx ATTACH PARTITION partitioned_mx_4 default;
ERROR: relation citus_local_tables_mx.partitioned_mx_4 is involved in a foreign key relationship with another table
SELECT
nmsp_parent.nspname AS parent_schema,
parent.relname AS parent,
nmsp_child.nspname AS child_schema,
child.relname AS child
FROM pg_inherits
JOIN pg_class parent ON pg_inherits.inhparent = parent.oid
JOIN pg_class child ON pg_inherits.inhrelid = child.oid
JOIN pg_namespace nmsp_parent ON nmsp_parent.oid = parent.relnamespace
JOIN pg_namespace nmsp_child ON nmsp_child.oid = child.relnamespace
WHERE parent.relname='partitioned_mx'
ORDER BY child;
parent_schema | parent | child_schema | child
---------------------------------------------------------------------
citus_local_tables_mx | partitioned_mx | citus_local_tables_mx | partitioned_mx_1
citus_local_tables_mx | partitioned_mx | citus_local_tables_mx | partitioned_mx_2
citus_local_tables_mx | partitioned_mx | citus_local_tables_mx | partitioned_mx_3
(3 rows)
\c - - - :worker_1_port
SELECT relname FROM pg_class WHERE relname LIKE 'partitioned_mx%' ORDER BY relname;
relname
---------------------------------------------------------------------
partitioned_mx
partitioned_mx_1
partitioned_mx_1_a_key
partitioned_mx_2
partitioned_mx_2_a_key
partitioned_mx_3
partitioned_mx_3_a_key
partitioned_mx_a_key
(8 rows)
SELECT
nmsp_parent.nspname AS parent_schema,
parent.relname AS parent,
nmsp_child.nspname AS child_schema,
child.relname AS child
FROM pg_inherits
JOIN pg_class parent ON pg_inherits.inhparent = parent.oid
JOIN pg_class child ON pg_inherits.inhrelid = child.oid
JOIN pg_namespace nmsp_parent ON nmsp_parent.oid = parent.relnamespace
JOIN pg_namespace nmsp_child ON nmsp_child.oid = child.relnamespace
WHERE parent.relname='partitioned_mx'
ORDER BY child;
parent_schema | parent | child_schema | child
---------------------------------------------------------------------
citus_local_tables_mx | partitioned_mx | citus_local_tables_mx | partitioned_mx_1
citus_local_tables_mx | partitioned_mx | citus_local_tables_mx | partitioned_mx_2
citus_local_tables_mx | partitioned_mx | citus_local_tables_mx | partitioned_mx_3
(3 rows)
\c - - - :master_port
SET search_path TO citus_local_tables_mx;
SET client_min_messages TO ERROR;
DROP TABLE partitioned_mx;
RESET client_min_messages;
-- test cascading via foreign keys
CREATE TABLE cas_1 (a INT UNIQUE);
CREATE TABLE cas_par (a INT UNIQUE) PARTITION BY RANGE(a);
CREATE TABLE cas_par_1 PARTITION OF cas_par FOR VALUES FROM (1) TO (4);
CREATE TABLE cas_par_2 PARTITION OF cas_par FOR VALUES FROM (5) TO (8);
ALTER TABLE cas_par_1 ADD CONSTRAINT fkey_cas_test_1 FOREIGN KEY (a) REFERENCES cas_1(a);
CREATE TABLE cas_par2 (a INT UNIQUE) PARTITION BY RANGE(a);
CREATE TABLE cas_par2_1 PARTITION OF cas_par2 FOR VALUES FROM (1) TO (4);
CREATE TABLE cas_par2_2 PARTITION OF cas_par2 FOR VALUES FROM (5) TO (8);
ALTER TABLE cas_par2_1 ADD CONSTRAINT fkey_cas_test_2 FOREIGN KEY (a) REFERENCES cas_1(a);
CREATE TABLE cas_par3 (a INT UNIQUE) PARTITION BY RANGE(a);
CREATE TABLE cas_par3_1 PARTITION OF cas_par3 FOR VALUES FROM (1) TO (4);
CREATE TABLE cas_par3_2 PARTITION OF cas_par3 FOR VALUES FROM (5) TO (8);
-- these two should error out as we should call the conversion from the parent
SELECT citus_add_local_table_to_metadata('cas_par2_2');
ERROR: cannot add local table cas_par2_2 to metadata since it is a partition of cas_par2. Instead, add the parent table cas_par2 to metadata.
SELECT citus_add_local_table_to_metadata('cas_par2_2', cascade_via_foreign_keys=>true);
ERROR: cannot add local table cas_par2_2 to metadata since it is a partition of cas_par2. Instead, add the parent table cas_par2 to metadata.
-- these two should error out as the foreign keys are not inherited from the parent
SELECT citus_add_local_table_to_metadata('cas_par2');
ERROR: cannot cascade operation via foreign keys as partition table citus_local_tables_mx.cas_par2_1 involved in a foreign key relationship that is not inherited from it's parent table
SELECT citus_add_local_table_to_metadata('cas_par2', cascade_via_foreign_keys=>true);
ERROR: cannot cascade operation via foreign keys as partition table citus_local_tables_mx.cas_par2_1 involved in a foreign key relationship that is not inherited from it's parent table
-- drop the foreign keys and establish them again using the parent table
ALTER TABLE cas_par_1 DROP CONSTRAINT fkey_cas_test_1;
ALTER TABLE cas_par2_1 DROP CONSTRAINT fkey_cas_test_2;
ALTER TABLE cas_par ADD CONSTRAINT fkey_cas_test_1 FOREIGN KEY (a) REFERENCES cas_1(a);
ALTER TABLE cas_par2 ADD CONSTRAINT fkey_cas_test_2 FOREIGN KEY (a) REFERENCES cas_1(a);
ALTER TABLE cas_par3 ADD CONSTRAINT fkey_cas_test_3 FOREIGN KEY (a) REFERENCES cas_par(a);
-- this should error out as cascade_via_foreign_keys is not set to true
SELECT citus_add_local_table_to_metadata('cas_par2');
ERROR: relation citus_local_tables_mx.cas_par2 is involved in a foreign key relationship with another table
-- this should work
SELECT citus_add_local_table_to_metadata('cas_par2', cascade_via_foreign_keys=>true);
citus_add_local_table_to_metadata
---------------------------------------------------------------------
(1 row)
-- verify the partitioning hierarchy is preserved
select inhrelid::regclass from pg_inherits where inhparent='cas_par'::regclass order by 1;
inhrelid
---------------------------------------------------------------------
cas_par_1
cas_par_2
(2 rows)
-- verify the fkeys + fkeys with shard ids are created
select conname from pg_constraint where conname like 'fkey_cas_test%' order by conname;
conname
---------------------------------------------------------------------
fkey_cas_test_1
fkey_cas_test_1
fkey_cas_test_1
fkey_cas_test_1_1330008
fkey_cas_test_1_1330008
fkey_cas_test_1_1330008
fkey_cas_test_2
fkey_cas_test_2
fkey_cas_test_2
fkey_cas_test_2_1330006
fkey_cas_test_2_1330006
fkey_cas_test_2_1330006
fkey_cas_test_3
fkey_cas_test_3
fkey_cas_test_3
fkey_cas_test_3_1330013
fkey_cas_test_3_1330013
fkey_cas_test_3_1330013
(18 rows)
-- when all partitions are converted, there should be 40 tables and indexes
-- the individual names are not much relevant, so we only print the count
SELECT count(*) FROM pg_class WHERE relname LIKE 'cas\_%' AND relnamespace IN
(SELECT oid FROM pg_namespace WHERE nspname = 'citus_local_tables_mx');
count
---------------------------------------------------------------------
40
(1 row)
-- verify on the mx worker
\c - - - :worker_1_port
-- on worker, there should be 20, since the shards are created only on the coordinator
SELECT count(*) FROM pg_class WHERE relname LIKE 'cas\_%' AND relnamespace IN
(SELECT oid FROM pg_namespace WHERE nspname = 'citus_local_tables_mx');
count
---------------------------------------------------------------------
20
(1 row)
-- verify that the shell foreign keys are created on the worker as well
select conname from pg_constraint where conname like 'fkey_cas_test%' order by conname;
conname
---------------------------------------------------------------------
fkey_cas_test_1
fkey_cas_test_1
fkey_cas_test_1
fkey_cas_test_2
fkey_cas_test_2
fkey_cas_test_2
fkey_cas_test_3
fkey_cas_test_3
fkey_cas_test_3
(9 rows)
\c - - - :master_port
SET search_path TO citus_local_tables_mx;
-- undistribute table
-- this one should error out since we don't set the cascade option as true
SELECT undistribute_table('cas_par2');
ERROR: cannot complete operation because table cas_par2 has a foreign key
-- this one should work
SET client_min_messages TO WARNING;
SELECT undistribute_table('cas_par2', cascade_via_foreign_keys=>true);
undistribute_table
---------------------------------------------------------------------
(1 row)
-- verify the partitioning hierarchy is preserved
select inhrelid::regclass from pg_inherits where inhparent='cas_par'::regclass order by 1;
inhrelid
---------------------------------------------------------------------
cas_par_1
cas_par_2
(2 rows)
-- verify that the foreign keys with shard ids are gone, due to undistribution
select conname from pg_constraint where conname like 'fkey_cas_test%' order by conname;
conname
---------------------------------------------------------------------
fkey_cas_test_1
fkey_cas_test_1
fkey_cas_test_1
fkey_cas_test_2
fkey_cas_test_2
fkey_cas_test_2
fkey_cas_test_3
fkey_cas_test_3
fkey_cas_test_3
(9 rows)
-- add a non-inherited fkey and verify it fails when trying to convert
ALTER TABLE cas_par2_1 ADD CONSTRAINT fkey_cas_test_3 FOREIGN KEY (a) REFERENCES cas_1(a);
SELECT citus_add_local_table_to_metadata('cas_par2', cascade_via_foreign_keys=>true);
ERROR: cannot cascade operation via foreign keys as partition table citus_local_tables_mx.cas_par2_1 involved in a foreign key relationship that is not inherited from it's parent table
-- verify undistribute_table works proper for the mx worker
\c - - - :worker_1_port
SELECT relname FROM pg_class WHERE relname LIKE 'cas\_%' ORDER BY relname;
relname
---------------------------------------------------------------------
(0 rows)
\c - - - :master_port
SET search_path TO citus_local_tables_mx;
CREATE TABLE date_partitioned_citus_local_table_seq( measureid bigserial, eventdate date, measure_data jsonb, PRIMARY KEY (measureid, eventdate)) PARTITION BY RANGE(eventdate);
SELECT create_time_partitions('date_partitioned_citus_local_table_seq', INTERVAL '1 month', '2022-01-01', '2021-01-01');
create_time_partitions
---------------------------------------------------------------------
t
(1 row)
SELECT citus_add_local_table_to_metadata('date_partitioned_citus_local_table_seq');
citus_add_local_table_to_metadata
---------------------------------------------------------------------
(1 row)
DROP TABLE date_partitioned_citus_local_table_seq;
-- test sequences
CREATE TABLE par_citus_local_seq(measureid bigserial, val int) PARTITION BY RANGE(val);
CREATE TABLE par_citus_local_seq_1 PARTITION OF par_citus_local_seq FOR VALUES FROM (1) TO (4);
SELECT citus_add_local_table_to_metadata('par_citus_local_seq');
citus_add_local_table_to_metadata
---------------------------------------------------------------------
(1 row)
INSERT INTO par_citus_local_seq (val) VALUES (1) RETURNING *;
measureid | val
---------------------------------------------------------------------
1 | 1
(1 row)
INSERT INTO par_citus_local_seq (val) VALUES (2) RETURNING *;
measureid | val
---------------------------------------------------------------------
2 | 2
(1 row)
\c - - - :worker_1_port
-- insert on the worker
INSERT INTO citus_local_tables_mx.par_citus_local_seq (val) VALUES (1) RETURNING *;
measureid | val
---------------------------------------------------------------------
3940649673949185 | 1
(1 row)
\c - - - :master_port
SET search_path TO citus_local_tables_mx;
INSERT INTO par_citus_local_seq (val) VALUES (2) RETURNING *;
measureid | val
---------------------------------------------------------------------
3 | 2
(1 row)
SELECT undistribute_table('par_citus_local_seq');
NOTICE: converting the partitions of citus_local_tables_mx.par_citus_local_seq
NOTICE: creating a new table for citus_local_tables_mx.par_citus_local_seq_1
NOTICE: moving the data of citus_local_tables_mx.par_citus_local_seq_1
NOTICE: dropping the old citus_local_tables_mx.par_citus_local_seq_1
NOTICE: renaming the new table to citus_local_tables_mx.par_citus_local_seq_1
NOTICE: creating a new table for citus_local_tables_mx.par_citus_local_seq
NOTICE: dropping the old citus_local_tables_mx.par_citus_local_seq
NOTICE: renaming the new table to citus_local_tables_mx.par_citus_local_seq
undistribute_table
---------------------------------------------------------------------
(1 row)
INSERT INTO par_citus_local_seq (val) VALUES (3) RETURNING *;
measureid | val
---------------------------------------------------------------------
4 | 3
(1 row)
SELECT measureid FROM par_citus_local_seq ORDER BY measureid;
measureid
---------------------------------------------------------------------
1
2
3
4
3940649673949185
(5 rows)
-- test adding invalid foreign key to partition table
CREATE TABLE citus_local_parent_1 (a INT UNIQUE) PARTITION BY RANGE(a);
CREATE TABLE citus_local_parent_2 (a INT UNIQUE) PARTITION BY RANGE(a);
CREATE TABLE citus_local_plain (a INT UNIQUE);
CREATE TABLE ref (a INT UNIQUE);
SELECT create_reference_table('ref');
create_reference_table
---------------------------------------------------------------------
(1 row)
alter table citus_local_parent_1 add foreign key (a) references citus_local_parent_2(a);
alter table citus_local_plain add foreign key (a) references citus_local_parent_2(a);
CREATE TABLE citus_local_parent_1_child_1 PARTITION OF citus_local_parent_1 FOR VALUES FROM (3) TO (5);
CREATE TABLE citus_local_parent_1_child_2 PARTITION OF citus_local_parent_1 FOR VALUES FROM (30) TO (50);
CREATE TABLE citus_local_parent_2_child_1 PARTITION OF citus_local_parent_2 FOR VALUES FROM (40) TO (60);
-- this one should error out, since we cannot convert it to citus local table,
-- as citus local table partitions cannot have non-inherited foreign keys
alter table citus_local_parent_1_child_1 add foreign key(a) references ref(a);
ERROR: cannot build foreign key between reference table and a partition
-- this should work
alter table citus_local_parent_1 add constraint fkey_to_drop_test foreign key(a) references ref(a);
-- this should undistribute the table, and the entries should be gone from pg_dist_partition
select logicalrelid from pg_dist_partition where logicalrelid::text like 'citus_local_parent%';
logicalrelid
---------------------------------------------------------------------
citus_local_parent_1
citus_local_parent_2
citus_local_parent_2_child_1
citus_local_parent_1_child_1
citus_local_parent_1_child_2
(5 rows)
set client_min_messages to error;
alter table citus_local_parent_1 drop constraint fkey_to_drop_test;
select logicalrelid from pg_dist_partition where logicalrelid::text like 'citus_local_parent%';
logicalrelid
---------------------------------------------------------------------
(0 rows)
SELECT master_remove_distributed_table_metadata_from_workers('citus_local_table_4'::regclass::oid, 'citus_local_tables_mx', 'citus_local_table_4');
master_remove_distributed_table_metadata_from_workers
---------------------------------------------------------------------
@ -259,4 +665,3 @@ $$);
-- cleanup at exit
DROP SCHEMA citus_local_tables_mx CASCADE;
NOTICE: drop cascades to 19 other objects

View File

@ -116,11 +116,12 @@ BEGIN;
ROLLBACK;
BEGIN;
CREATE TABLE partitioned_table (col_1 INT REFERENCES local_table_1 (col_1)) PARTITION BY RANGE (col_1);
-- now that we introduced a partitioned table into our foreign key subgraph,
-- citus_add_local_table_to_metadata(cascade_via_foreign_keys) would fail for
-- partitioned_table as citus_add_local_table_to_metadata doesn't support partitioned tables
SELECT citus_add_local_table_to_metadata('local_table_2', cascade_via_foreign_keys=>true);
ERROR: cannot add local table "partitioned_table" to metadata, only regular tables and foreign tables can be added to citus metadata
citus_add_local_table_to_metadata
---------------------------------------------------------------------
(1 row)
ROLLBACK;
BEGIN;
DROP TABLE local_table_2;

View File

@ -99,10 +99,9 @@ CREATE TABLE partitioned_table_1_100_200 PARTITION OF partitioned_table_1 FOR VA
CREATE TABLE partitioned_table_1_200_300 PARTITION OF partitioned_table_1 FOR VALUES FROM (200) TO (300);
INSERT INTO partitioned_table_1 SELECT i FROM generate_series(195, 205) i;
ALTER TABLE partitioned_table_1 ADD CONSTRAINT fkey_8 FOREIGN KEY (col_1) REFERENCES local_table_4(col_1);
-- now that we attached partitioned table to graph below errors out
-- since we cannot create citus local table from partitioned tables
BEGIN;
ALTER TABLE reference_table_1 ADD CONSTRAINT fkey_9 FOREIGN KEY (col_1) REFERENCES local_table_1(col_1);
ERROR: cannot add local table "partitioned_table_1" to metadata, only regular tables and foreign tables can be added to citus metadata
ROLLBACK;
ALTER TABLE partitioned_table_1 DROP CONSTRAINT fkey_8;
BEGIN;
-- now that we detached partitioned table from graph, succeeds
@ -329,7 +328,7 @@ BEGIN;
-- show that we validate foreign key constraints, errors out
INSERT INTO local_table_5 VALUES (300);
ERROR: insert or update on table "local_table_5_1518070" violates foreign key constraint "local_table_5_col_1_fkey1_1518070"
ERROR: insert or update on table "local_table_5_1518073" violates foreign key constraint "local_table_5_col_1_fkey1_1518073"
ROLLBACK;
BEGIN;
CREATE SCHEMA another_schema_fkeys_between_local_ref;
@ -620,10 +619,9 @@ ORDER BY tablename;
reference_table_1 | n | t
(7 rows)
-- this errors out as we don't support creating citus local
-- tables from partitioned tables
BEGIN;
CREATE TABLE part_local_table (col_1 INT REFERENCES reference_table_1(col_1)) PARTITION BY RANGE (col_1);
ERROR: cannot add local table "part_local_table" to metadata, only regular tables and foreign tables can be added to citus metadata
ROLLBACK;
-- they fail as col_99 does not exist
CREATE TABLE local_table_5 (col_1 INT, FOREIGN KEY (col_99) REFERENCES reference_table_1(col_1));
ERROR: column "col_99" referenced in foreign key constraint does not exist

View File

@ -3763,6 +3763,306 @@ BEGIN;
ROLLBACK;
DROP TABLE pi_table;
-- 6) test with citus local table
select 1 from citus_add_node('localhost', :master_port, groupid=>0);
NOTICE: Replicating reference table "orders_reference" to the node localhost:xxxxx
NOTICE: Replicating reference table "customer" to the node localhost:xxxxx
NOTICE: Replicating reference table "nation" to the node localhost:xxxxx
NOTICE: Replicating reference table "part" to the node localhost:xxxxx
NOTICE: Replicating reference table "supplier" to the node localhost:xxxxx
NOTICE: Replicating reference table "users_ref_test_table" to the node localhost:xxxxx
NOTICE: Replicating reference table "events_reference_table" to the node localhost:xxxxx
NOTICE: Replicating reference table "users_reference_table" to the node localhost:xxxxx
?column?
---------------------------------------------------------------------
1
(1 row)
CREATE TABLE date_partitioned_citus_local_table(
measureid integer,
eventdate date,
measure_data jsonb) PARTITION BY RANGE(eventdate);
SELECT citus_add_local_table_to_metadata('date_partitioned_citus_local_table');
citus_add_local_table_to_metadata
---------------------------------------------------------------------
(1 row)
-- test interval must be multiple days for date partitioned table
SELECT create_time_partitions('date_partitioned_citus_local_table', INTERVAL '6 hours', '2022-01-01', '2021-01-01');
ERROR: partition interval of date partitioned table must be day or multiple days
CONTEXT: PL/pgSQL function get_missing_time_partition_ranges(regclass,interval,timestamp with time zone,timestamp with time zone) line XX at RAISE
PL/pgSQL function create_time_partitions(regclass,interval,timestamp with time zone,timestamp with time zone) line XX at FOR over SELECT rows
SELECT create_time_partitions('date_partitioned_citus_local_table', INTERVAL '1 week 1 day 1 hour', '2022-01-01', '2021-01-01');
ERROR: partition interval of date partitioned table must be day or multiple days
CONTEXT: PL/pgSQL function get_missing_time_partition_ranges(regclass,interval,timestamp with time zone,timestamp with time zone) line XX at RAISE
PL/pgSQL function create_time_partitions(regclass,interval,timestamp with time zone,timestamp with time zone) line XX at FOR over SELECT rows
-- test with various intervals
BEGIN;
SELECT create_time_partitions('date_partitioned_citus_local_table', INTERVAL '1 day', '2021-02-01', '2021-01-01');
create_time_partitions
---------------------------------------------------------------------
t
(1 row)
SELECT * FROM time_partitions WHERE parent_table = 'date_partitioned_citus_local_table'::regclass ORDER BY 3;
parent_table | partition_column | partition | from_value | to_value | access_method
---------------------------------------------------------------------
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_01 | 01-01-2021 | 01-02-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_02 | 01-02-2021 | 01-03-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_03 | 01-03-2021 | 01-04-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_04 | 01-04-2021 | 01-05-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_05 | 01-05-2021 | 01-06-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_06 | 01-06-2021 | 01-07-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_07 | 01-07-2021 | 01-08-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_08 | 01-08-2021 | 01-09-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_09 | 01-09-2021 | 01-10-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_10 | 01-10-2021 | 01-11-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_11 | 01-11-2021 | 01-12-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_12 | 01-12-2021 | 01-13-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_13 | 01-13-2021 | 01-14-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_14 | 01-14-2021 | 01-15-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_15 | 01-15-2021 | 01-16-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_16 | 01-16-2021 | 01-17-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_17 | 01-17-2021 | 01-18-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_18 | 01-18-2021 | 01-19-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_19 | 01-19-2021 | 01-20-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_20 | 01-20-2021 | 01-21-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_21 | 01-21-2021 | 01-22-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_22 | 01-22-2021 | 01-23-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_23 | 01-23-2021 | 01-24-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_24 | 01-24-2021 | 01-25-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_25 | 01-25-2021 | 01-26-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_26 | 01-26-2021 | 01-27-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_27 | 01-27-2021 | 01-28-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_28 | 01-28-2021 | 01-29-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_29 | 01-29-2021 | 01-30-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_30 | 01-30-2021 | 01-31-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_31 | 01-31-2021 | 02-01-2021 | heap
(31 rows)
ROLLBACK;
BEGIN;
SELECT create_time_partitions('date_partitioned_citus_local_table', INTERVAL '1 week', '2022-01-01', '2021-01-01');
create_time_partitions
---------------------------------------------------------------------
t
(1 row)
SELECT * FROM time_partitions WHERE parent_table = 'date_partitioned_citus_local_table'::regclass ORDER BY 3;
parent_table | partition_column | partition | from_value | to_value | access_method
---------------------------------------------------------------------
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2020w53 | 12-28-2020 | 01-04-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021w01 | 01-04-2021 | 01-11-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021w02 | 01-11-2021 | 01-18-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021w03 | 01-18-2021 | 01-25-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021w04 | 01-25-2021 | 02-01-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021w05 | 02-01-2021 | 02-08-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021w06 | 02-08-2021 | 02-15-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021w07 | 02-15-2021 | 02-22-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021w08 | 02-22-2021 | 03-01-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021w09 | 03-01-2021 | 03-08-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021w10 | 03-08-2021 | 03-15-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021w11 | 03-15-2021 | 03-22-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021w12 | 03-22-2021 | 03-29-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021w13 | 03-29-2021 | 04-05-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021w14 | 04-05-2021 | 04-12-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021w15 | 04-12-2021 | 04-19-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021w16 | 04-19-2021 | 04-26-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021w17 | 04-26-2021 | 05-03-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021w18 | 05-03-2021 | 05-10-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021w19 | 05-10-2021 | 05-17-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021w20 | 05-17-2021 | 05-24-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021w21 | 05-24-2021 | 05-31-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021w22 | 05-31-2021 | 06-07-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021w23 | 06-07-2021 | 06-14-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021w24 | 06-14-2021 | 06-21-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021w25 | 06-21-2021 | 06-28-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021w26 | 06-28-2021 | 07-05-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021w27 | 07-05-2021 | 07-12-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021w28 | 07-12-2021 | 07-19-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021w29 | 07-19-2021 | 07-26-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021w30 | 07-26-2021 | 08-02-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021w31 | 08-02-2021 | 08-09-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021w32 | 08-09-2021 | 08-16-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021w33 | 08-16-2021 | 08-23-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021w34 | 08-23-2021 | 08-30-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021w35 | 08-30-2021 | 09-06-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021w36 | 09-06-2021 | 09-13-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021w37 | 09-13-2021 | 09-20-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021w38 | 09-20-2021 | 09-27-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021w39 | 09-27-2021 | 10-04-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021w40 | 10-04-2021 | 10-11-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021w41 | 10-11-2021 | 10-18-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021w42 | 10-18-2021 | 10-25-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021w43 | 10-25-2021 | 11-01-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021w44 | 11-01-2021 | 11-08-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021w45 | 11-08-2021 | 11-15-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021w46 | 11-15-2021 | 11-22-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021w47 | 11-22-2021 | 11-29-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021w48 | 11-29-2021 | 12-06-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021w49 | 12-06-2021 | 12-13-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021w50 | 12-13-2021 | 12-20-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021w51 | 12-20-2021 | 12-27-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021w52 | 12-27-2021 | 01-03-2022 | heap
(53 rows)
ROLLBACK;
set client_min_messages to error;
DROP TABLE date_partitioned_citus_local_table;
-- also test with foreign key
CREATE TABLE date_partitioned_citus_local_table(
measureid integer,
eventdate date,
measure_data jsonb, PRIMARY KEY (measureid, eventdate)) PARTITION BY RANGE(eventdate);
SELECT citus_add_local_table_to_metadata('date_partitioned_citus_local_table');
citus_add_local_table_to_metadata
---------------------------------------------------------------------
(1 row)
-- test interval must be multiple days for date partitioned table
SELECT create_time_partitions('date_partitioned_citus_local_table', INTERVAL '1 day', '2021-02-01', '2021-01-01');
create_time_partitions
---------------------------------------------------------------------
t
(1 row)
CREATE TABLE date_partitioned_citus_local_table_2(
measureid integer,
eventdate date,
measure_data jsonb, PRIMARY KEY (measureid, eventdate)) PARTITION BY RANGE(eventdate);
SELECT citus_add_local_table_to_metadata('date_partitioned_citus_local_table_2');
citus_add_local_table_to_metadata
---------------------------------------------------------------------
(1 row)
ALTER TABLE date_partitioned_citus_local_table_2 ADD CONSTRAINT fkey_1 FOREIGN KEY (measureid, eventdate) REFERENCES date_partitioned_citus_local_table(measureid, eventdate);
SELECT create_time_partitions('date_partitioned_citus_local_table_2', INTERVAL '1 day', '2021-02-01', '2021-01-01');
create_time_partitions
---------------------------------------------------------------------
t
(1 row)
-- after the above work, these should also work for creating new partitions
BEGIN;
SELECT create_time_partitions('date_partitioned_citus_local_table', INTERVAL '1 day', '2021-03-01', '2021-02-01');
create_time_partitions
---------------------------------------------------------------------
t
(1 row)
SELECT * FROM time_partitions WHERE parent_table = 'date_partitioned_citus_local_table'::regclass ORDER BY 3;
parent_table | partition_column | partition | from_value | to_value | access_method
---------------------------------------------------------------------
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_01 | 01-01-2021 | 01-02-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_02 | 01-02-2021 | 01-03-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_03 | 01-03-2021 | 01-04-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_04 | 01-04-2021 | 01-05-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_05 | 01-05-2021 | 01-06-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_06 | 01-06-2021 | 01-07-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_07 | 01-07-2021 | 01-08-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_08 | 01-08-2021 | 01-09-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_09 | 01-09-2021 | 01-10-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_10 | 01-10-2021 | 01-11-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_11 | 01-11-2021 | 01-12-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_12 | 01-12-2021 | 01-13-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_13 | 01-13-2021 | 01-14-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_14 | 01-14-2021 | 01-15-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_15 | 01-15-2021 | 01-16-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_16 | 01-16-2021 | 01-17-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_17 | 01-17-2021 | 01-18-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_18 | 01-18-2021 | 01-19-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_19 | 01-19-2021 | 01-20-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_20 | 01-20-2021 | 01-21-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_21 | 01-21-2021 | 01-22-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_22 | 01-22-2021 | 01-23-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_23 | 01-23-2021 | 01-24-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_24 | 01-24-2021 | 01-25-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_25 | 01-25-2021 | 01-26-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_26 | 01-26-2021 | 01-27-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_27 | 01-27-2021 | 01-28-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_28 | 01-28-2021 | 01-29-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_29 | 01-29-2021 | 01-30-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_30 | 01-30-2021 | 01-31-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_31 | 01-31-2021 | 02-01-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_02_01 | 02-01-2021 | 02-02-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_02_02 | 02-02-2021 | 02-03-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_02_03 | 02-03-2021 | 02-04-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_02_04 | 02-04-2021 | 02-05-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_02_05 | 02-05-2021 | 02-06-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_02_06 | 02-06-2021 | 02-07-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_02_07 | 02-07-2021 | 02-08-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_02_08 | 02-08-2021 | 02-09-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_02_09 | 02-09-2021 | 02-10-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_02_10 | 02-10-2021 | 02-11-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_02_11 | 02-11-2021 | 02-12-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_02_12 | 02-12-2021 | 02-13-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_02_13 | 02-13-2021 | 02-14-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_02_14 | 02-14-2021 | 02-15-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_02_15 | 02-15-2021 | 02-16-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_02_16 | 02-16-2021 | 02-17-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_02_17 | 02-17-2021 | 02-18-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_02_18 | 02-18-2021 | 02-19-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_02_19 | 02-19-2021 | 02-20-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_02_20 | 02-20-2021 | 02-21-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_02_21 | 02-21-2021 | 02-22-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_02_22 | 02-22-2021 | 02-23-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_02_23 | 02-23-2021 | 02-24-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_02_24 | 02-24-2021 | 02-25-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_02_25 | 02-25-2021 | 02-26-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_02_26 | 02-26-2021 | 02-27-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_02_27 | 02-27-2021 | 02-28-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_02_28 | 02-28-2021 | 03-01-2021 | heap
(59 rows)
ROLLBACK;
BEGIN;
SELECT create_time_partitions('date_partitioned_citus_local_table_2', INTERVAL '1 day', '2021-03-01', '2021-02-01');
create_time_partitions
---------------------------------------------------------------------
t
(1 row)
SELECT * FROM time_partitions WHERE parent_table = 'date_partitioned_citus_local_table'::regclass ORDER BY 3;
parent_table | partition_column | partition | from_value | to_value | access_method
---------------------------------------------------------------------
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_01 | 01-01-2021 | 01-02-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_02 | 01-02-2021 | 01-03-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_03 | 01-03-2021 | 01-04-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_04 | 01-04-2021 | 01-05-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_05 | 01-05-2021 | 01-06-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_06 | 01-06-2021 | 01-07-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_07 | 01-07-2021 | 01-08-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_08 | 01-08-2021 | 01-09-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_09 | 01-09-2021 | 01-10-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_10 | 01-10-2021 | 01-11-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_11 | 01-11-2021 | 01-12-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_12 | 01-12-2021 | 01-13-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_13 | 01-13-2021 | 01-14-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_14 | 01-14-2021 | 01-15-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_15 | 01-15-2021 | 01-16-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_16 | 01-16-2021 | 01-17-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_17 | 01-17-2021 | 01-18-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_18 | 01-18-2021 | 01-19-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_19 | 01-19-2021 | 01-20-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_20 | 01-20-2021 | 01-21-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_21 | 01-21-2021 | 01-22-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_22 | 01-22-2021 | 01-23-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_23 | 01-23-2021 | 01-24-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_24 | 01-24-2021 | 01-25-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_25 | 01-25-2021 | 01-26-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_26 | 01-26-2021 | 01-27-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_27 | 01-27-2021 | 01-28-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_28 | 01-28-2021 | 01-29-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_29 | 01-29-2021 | 01-30-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_30 | 01-30-2021 | 01-31-2021 | heap
date_partitioned_citus_local_table | eventdate | date_partitioned_citus_local_table_p2021_01_31 | 01-31-2021 | 02-01-2021 | heap
(31 rows)
ROLLBACK;
set client_min_messages to notice;
-- c) test drop_old_time_partitions
-- 1) test with date partitioned table
CREATE TABLE date_partitioned_table_to_exp (event_date date, event int) partition by range (event_date);
@ -3875,6 +4175,46 @@ SELECT partition FROM time_partitions WHERE parent_table = '"test !/ \n _dist_12
\set VERBOSITY default
DROP TABLE "test !/ \n _dist_123_table_exp";
-- 4) test with citus local tables
CREATE TABLE date_partitioned_table_to_exp (event_date date, event int) partition by range (event_date);
SELECT citus_add_local_table_to_metadata('date_partitioned_table_to_exp');
citus_add_local_table_to_metadata
---------------------------------------------------------------------
(1 row)
CREATE TABLE date_partitioned_table_to_exp_d00 PARTITION OF date_partitioned_table_to_exp FOR VALUES FROM ('2000-01-01') TO ('2009-12-31');
CREATE TABLE date_partitioned_table_to_exp_d10 PARTITION OF date_partitioned_table_to_exp FOR VALUES FROM ('2010-01-01') TO ('2019-12-31');
CREATE TABLE date_partitioned_table_to_exp_d20 PARTITION OF date_partitioned_table_to_exp FOR VALUES FROM ('2020-01-01') TO ('2029-12-31');
\set VERBOSITY terse
-- expire no partitions
CALL drop_old_time_partitions('date_partitioned_table_to_exp', '1999-01-01');
SELECT partition FROM time_partitions WHERE parent_table = 'date_partitioned_table_to_exp'::regclass ORDER BY partition::text;
partition
---------------------------------------------------------------------
date_partitioned_table_to_exp_d00
date_partitioned_table_to_exp_d10
date_partitioned_table_to_exp_d20
(3 rows)
-- expire 2 old partitions
CALL drop_old_time_partitions('date_partitioned_table_to_exp', '2021-01-01');
NOTICE: dropping date_partitioned_table_to_exp_d00 with start time 01-01-2000 and end time 12-31-2009
NOTICE: dropping date_partitioned_table_to_exp_d10 with start time 01-01-2010 and end time 12-31-2019
SELECT partition FROM time_partitions WHERE parent_table = 'date_partitioned_table_to_exp'::regclass ORDER BY partition::text;
partition
---------------------------------------------------------------------
date_partitioned_table_to_exp_d20
(1 row)
\set VERBOSITY default
DROP TABLE date_partitioned_table_to_exp;
SELECT citus_remove_node('localhost', :master_port);
citus_remove_node
---------------------------------------------------------------------
(1 row)
-- d) invalid tables for helper UDFs
CREATE TABLE multiple_partition_column_table(
event_id bigserial,
@ -3986,10 +4326,12 @@ NOTICE: dropping metadata on the node (localhost,57637)
(1 row)
DROP SCHEMA partitioning_schema CASCADE;
NOTICE: drop cascades to 4 other objects
NOTICE: drop cascades to 6 other objects
DETAIL: drop cascades to table partitioning_schema."schema-test"
drop cascades to table partitioning_schema.another_distributed_table
drop cascades to table partitioning_schema.distributed_parent_table
drop cascades to table partitioning_schema.date_partitioned_citus_local_table
drop cascades to table partitioning_schema.date_partitioned_citus_local_table_2
drop cascades to table partitioning_schema.part_table_with_very_long_name
RESET search_path;
DROP TABLE IF EXISTS

View File

@ -1289,14 +1289,6 @@ ALTER TABLE citus_local_table_1 ADD CONSTRAINT fkey_4 FOREIGN KEY (col_1) REFERE
ALTER TABLE partitioned_table_1 ADD CONSTRAINT fkey_5 FOREIGN KEY (col_1) REFERENCES reference_table_1(col_2);
SELECT undistribute_table('partitioned_table_1', cascade_via_foreign_keys=>true);
NOTICE: converting the partitions of single_node.partitioned_table_1
NOTICE: creating a new table for single_node.partitioned_table_1_100_200
NOTICE: moving the data of single_node.partitioned_table_1_100_200
NOTICE: dropping the old single_node.partitioned_table_1_100_200
NOTICE: renaming the new table to single_node.partitioned_table_1_100_200
NOTICE: creating a new table for single_node.partitioned_table_1_200_300
NOTICE: moving the data of single_node.partitioned_table_1_200_300
NOTICE: dropping the old single_node.partitioned_table_1_200_300
NOTICE: renaming the new table to single_node.partitioned_table_1_200_300
NOTICE: creating a new table for single_node.partitioned_table_1
NOTICE: dropping the old single_node.partitioned_table_1
NOTICE: renaming the new table to single_node.partitioned_table_1
@ -1312,6 +1304,14 @@ NOTICE: creating a new table for single_node.citus_local_table_1
NOTICE: moving the data of single_node.citus_local_table_1
NOTICE: dropping the old single_node.citus_local_table_1
NOTICE: renaming the new table to single_node.citus_local_table_1
NOTICE: creating a new table for single_node.partitioned_table_1_100_200
NOTICE: moving the data of single_node.partitioned_table_1_100_200
NOTICE: dropping the old single_node.partitioned_table_1_100_200
NOTICE: renaming the new table to single_node.partitioned_table_1_100_200
NOTICE: creating a new table for single_node.partitioned_table_1_200_300
NOTICE: moving the data of single_node.partitioned_table_1_200_300
NOTICE: dropping the old single_node.partitioned_table_1_200_300
NOTICE: renaming the new table to single_node.partitioned_table_1_200_300
undistribute_table
---------------------------------------------------------------------

View File

@ -382,12 +382,12 @@ BEGIN;
ORDER BY 1,2,3;
conname | conrelid | confrelid
---------------------------------------------------------------------
fkey_10 | partitioned_table_2 | reference_table_3
fkey_10 | partitioned_table_2_100_200 | reference_table_3
fkey_10 | partitioned_table_2_200_300 | reference_table_3
fkey_10 | partitioned_table_2 | reference_table_3
fkey_9 | partitioned_table_1 | reference_table_3
fkey_9 | partitioned_table_1_100_200 | reference_table_3
fkey_9 | partitioned_table_1_200_300 | reference_table_3
fkey_9 | partitioned_table_1 | reference_table_3
(6 rows)
ROLLBACK;

View File

@ -301,5 +301,40 @@ BEGIN;
SELECT * FROM reference_table;
ROLLBACK;
-- test on partitioned citus local tables
CREATE TABLE par_citus_local_table (val int) PARTITION BY RANGE(val);
CREATE TABLE par_citus_local_table_1 PARTITION OF par_citus_local_table FOR VALUES FROM (1) TO (10000);
CREATE TABLE par_another_citus_local_table (val int unique) PARTITION BY RANGE(val);
CREATE TABLE par_another_citus_local_table_1 PARTITION OF par_another_citus_local_table FOR VALUES FROM (1) TO (10000);
ALTER TABLE par_another_citus_local_table ADD CONSTRAINT fkey_self FOREIGN KEY(val) REFERENCES par_another_citus_local_table(val);
ALTER TABLE par_citus_local_table ADD CONSTRAINT fkey_c_to_c FOREIGN KEY(val) REFERENCES par_another_citus_local_table(val) ON UPDATE CASCADE;
SELECT citus_add_local_table_to_metadata('par_another_citus_local_table', cascade_via_foreign_keys=>true);
CREATE TABLE par_reference_table(val int);
SELECT create_reference_table('par_reference_table');
CREATE FUNCTION par_insert_100() RETURNS trigger AS $par_insert_100$
BEGIN
INSERT INTO par_reference_table VALUES (100);
RETURN NEW;
END;
$par_insert_100$ LANGUAGE plpgsql;
BEGIN;
CREATE TRIGGER par_insert_100_trigger
AFTER TRUNCATE ON par_another_citus_local_table
FOR EACH STATEMENT EXECUTE FUNCTION par_insert_100();
CREATE TRIGGER insert_100_trigger
AFTER TRUNCATE ON par_citus_local_table
FOR EACH STATEMENT EXECUTE FUNCTION par_insert_100();
TRUNCATE par_another_citus_local_table CASCADE;
-- we should see two rows with "100"
SELECT * FROM par_reference_table;
ROLLBACK;
-- cleanup at exit
DROP SCHEMA citus_local_table_triggers, "interesting!schema" CASCADE;

View File

@ -93,42 +93,6 @@ SELECT create_distributed_table('distributed_table', 'a');
-- cannot create citus local table from an existing citus table
SELECT citus_add_local_table_to_metadata('distributed_table');
-- partitioned table tests --
CREATE TABLE partitioned_table(a int, b int) PARTITION BY RANGE (a);
CREATE TABLE partitioned_table_1 PARTITION OF partitioned_table FOR VALUES FROM (0) TO (10);
CREATE TABLE partitioned_table_2 PARTITION OF partitioned_table FOR VALUES FROM (10) TO (20);
-- cannot create partitioned citus local tables
SELECT citus_add_local_table_to_metadata('partitioned_table');
BEGIN;
CREATE TABLE citus_local_table PARTITION OF partitioned_table FOR VALUES FROM (20) TO (30);
-- cannot create citus local table as a partition of a local table
SELECT citus_add_local_table_to_metadata('citus_local_table');
ROLLBACK;
BEGIN;
CREATE TABLE citus_local_table (a int, b int);
SELECT citus_add_local_table_to_metadata('citus_local_table');
-- cannot create citus local table as a partition of a local table
-- via ALTER TABLE commands as well
ALTER TABLE partitioned_table ATTACH PARTITION citus_local_table FOR VALUES FROM (20) TO (30);
ROLLBACK;
BEGIN;
SELECT create_distributed_table('partitioned_table', 'a');
CREATE TABLE citus_local_table (a int, b int);
SELECT citus_add_local_table_to_metadata('citus_local_table');
-- cannot attach citus local table to a partitioned distributed table
ALTER TABLE partitioned_table ATTACH PARTITION citus_local_table FOR VALUES FROM (20) TO (30);
ROLLBACK;
-- show that we do not support inheritance relationships --
CREATE TABLE parent_table (a int, b text);
@ -539,5 +503,95 @@ TRUNCATE referenced_table CASCADE;
RESET client_min_messages;
\set VERBOSITY terse
-- test for partitioned tables
SET client_min_messages TO ERROR;
-- verify we can convert partitioned tables into Citus Local Tables
CREATE TABLE partitioned (user_id int, time timestamp with time zone, data jsonb, PRIMARY KEY (user_id, time )) PARTITION BY RANGE ("time");
CREATE TABLE partition1 PARTITION OF partitioned FOR VALUES FROM ('2018-04-13 00:00:00+00') TO ('2018-04-14 00:00:00+00');
CREATE TABLE partition2 PARTITION OF partitioned FOR VALUES FROM ('2018-04-14 00:00:00+00') TO ('2018-04-15 00:00:00+00');
SELECT citus_add_local_table_to_metadata('partitioned');
-- partitions added after the conversion get converted into CLT as well
CREATE TABLE partition3 PARTITION OF partitioned FOR VALUES FROM ('2018-04-15 00:00:00+00') TO ('2018-04-16 00:00:00+00');
--verify partitioning hierarchy is preserved after conversion
select inhrelid::regclass from pg_inherits where inhparent='partitioned'::regclass order by 1;
SELECT partition, from_value, to_value, access_method
FROM time_partitions
WHERE partition::text LIKE '%partition%'
ORDER BY partition::text;
-- undistribute succesfully
SELECT undistribute_table('partitioned');
-- verify the partitioning hierarchy is preserved after undistributing
select inhrelid::regclass from pg_inherits where inhparent='partitioned'::regclass order by 1;
-- verify table is undistributed
SELECT relname FROM pg_class WHERE relname LIKE 'partition3%' AND relnamespace IN
(SELECT oid FROM pg_namespace WHERE nspname = 'citus_local_tables_test_schema')
ORDER BY relname;
-- drop successfully
DROP TABLE partitioned;
-- test creating distributed tables from partitioned citus local tables
CREATE TABLE partitioned_distributed (a INT UNIQUE) PARTITION BY RANGE(a);
CREATE TABLE partitioned_distributed_1 PARTITION OF partitioned_distributed FOR VALUES FROM (1) TO (4);
CREATE TABLE partitioned_distributed_2 PARTITION OF partitioned_distributed FOR VALUES FROM (5) TO (8);
SELECT citus_add_local_table_to_metadata('partitioned_distributed');
SELECT create_distributed_table('partitioned_distributed','a');
\c - - - :worker_1_port
SELECT relname FROM pg_class
WHERE relname LIKE 'partitioned_distributed%'
AND relnamespace IN (SELECT oid FROM pg_namespace WHERE nspname = 'citus_local_tables_test_schema')
ORDER BY relname;
\c - - - :master_port
SET search_path TO citus_local_tables_test_schema;
-- error out if converting multi-level partitioned table
CREATE TABLE multi_par (id text, country text) PARTITION BY RANGE (id);
ALTER TABLE multi_par ADD CONSTRAINT unique_constraint UNIQUE (id, country);
CREATE TABLE multi_par_a_to_i PARTITION OF multi_par FOR VALUES FROM ('a') TO ('j');
-- multi-level partitioning
CREATE TABLE multi_par_j_to_r PARTITION OF multi_par FOR VALUES FROM ('j') TO ('s') PARTITION BY LIST (country);
CREATE TABLE multi_par_j_to_r_japan PARTITION OF multi_par_j_to_r FOR VALUES IN ('japan');
-- these two should error out
SELECT citus_add_local_table_to_metadata('multi_par');
SELECT citus_add_local_table_to_metadata('multi_par',cascade_via_foreign_keys=>true);
-- should error out when cascading via fkeys as well
CREATE TABLE cas_1 (a text, b text);
ALTER TABLE cas_1 ADD CONSTRAINT unique_constraint_2 UNIQUE (a, b);
ALTER TABLE cas_1 ADD CONSTRAINT fkey_to_multi_parti FOREIGN KEY (a,b) REFERENCES multi_par(id, country);
SELECT citus_add_local_table_to_metadata('cas_1');
SELECT citus_add_local_table_to_metadata('cas_1', cascade_via_foreign_keys=>true);
SELECT create_reference_table('cas_1');
ALTER TABLE cas_1 DROP CONSTRAINT fkey_to_multi_parti;
SELECT create_reference_table('cas_1');
ALTER TABLE cas_1 ADD CONSTRAINT fkey_to_multi_parti FOREIGN KEY (a,b) REFERENCES multi_par(id, country);
-- undistribute tables to avoid unnecessary log messages later
select undistribute_table('citus_local_table_4', cascade_via_foreign_keys=>true);
select undistribute_table('referencing_table', cascade_via_foreign_keys=>true);
-- test dropping fkey
CREATE TABLE parent_2_child_1 (a int);
CREATE TABLE parent_1_child_1 (a int);
CREATE TABLE parent_2 (a INT UNIQUE) PARTITION BY RANGE(a);
CREATE TABLE parent_1 (a INT UNIQUE) PARTITION BY RANGE(a);
alter table parent_1 attach partition parent_1_child_1 default ;
alter table parent_2 attach partition parent_2_child_1 default ;
CREATE TABLE ref_table(a int unique);
alter table parent_1 add constraint fkey_test_drop foreign key(a) references ref_table(a);
alter table parent_2 add constraint fkey1 foreign key(a) references ref_table(a);
alter table parent_1 add constraint fkey2 foreign key(a) references parent_2(a);
SELECT create_reference_table('ref_table');
alter table parent_1 drop constraint fkey_test_drop;
select count(*) from pg_constraint where conname = 'fkey_test_drop';
-- verify we still preserve the child-parent hierarchy after all conversions
-- check the shard partition
select inhrelid::regclass from pg_inherits where (select inhparent::regclass::text) ~ '^parent_1_\d{7}$' order by 1;
-- check the shell partition
select inhrelid::regclass from pg_inherits where inhparent='parent_1'::regclass order by 1;
-- cleanup at exit
SET client_min_messages TO ERROR;
DROP SCHEMA citus_local_tables_test_schema, "CiTUS!LocalTables", "test_\'index_schema" CASCADE;

View File

@ -168,6 +168,180 @@ SELECT stxname FROM pg_statistic_ext ORDER BY stxname;
\c - - - :master_port
SET search_path TO citus_local_tables_mx;
-- undistribute old tables to prevent unnecessary undistribute logs later
SELECT undistribute_table('citus_local_table', cascade_via_foreign_keys=>true);
SELECT undistribute_table('citus_local_table_3', cascade_via_foreign_keys=>true);
SELECT undistribute_table('citus_local_table_stats', cascade_via_foreign_keys=>true);
-- verify that mx nodes have the shell table for partitioned citus local tables
CREATE TABLE local_table_fkey(a INT UNIQUE);
CREATE TABLE local_table_fkey2(a INT UNIQUE);
CREATE TABLE partitioned_mx (a INT UNIQUE) PARTITION BY RANGE(a);
ALTER TABLE partitioned_mx ADD CONSTRAINT fkey_to_local FOREIGN KEY (a) REFERENCES local_table_fkey(a);
CREATE TABLE IF NOT EXISTS partitioned_mx_1 PARTITION OF partitioned_mx FOR VALUES FROM (1) TO (4);
CREATE TABLE partitioned_mx_2 (a INT UNIQUE);
ALTER TABLE partitioned_mx ATTACH PARTITION partitioned_mx_2 FOR VALUES FROM (5) TO (8);
SELECT create_reference_table('local_table_fkey');
CREATE TABLE partitioned_mx_3 (a INT UNIQUE);
ALTER TABLE partitioned_mx ATTACH PARTITION partitioned_mx_3 FOR VALUES FROM (9) TO (12);
-- these should error out since multi-level partitioned citus local tables are not supported
CREATE TABLE IF NOT EXISTS partitioned_mx_4 PARTITION OF partitioned_mx FOR VALUES FROM (13) TO (16) PARTITION BY RANGE (a);
BEGIN;
CREATE TABLE partitioned_mx_4(a INT UNIQUE) PARTITION BY RANGE (a);
alter table partitioned_mx attach partition partitioned_mx_4 FOR VALUES FROM (13) TO (16);
END;
CREATE TABLE multi_level_p (a INT UNIQUE) PARTITION BY RANGE (a);
CREATE TABLE IF NOT EXISTS multi_level_c PARTITION OF multi_level_p FOR VALUES FROM (13) TO (16) PARTITION BY RANGE (a);
select citus_add_local_table_to_metadata('multi_level_p'); --errors
select citus_add_local_table_to_metadata('multi_level_p', true); --errors
-- try attaching a partition with an external foreign key
CREATE TABLE partitioned_mx_4 (a INT UNIQUE);
ALTER TABLE partitioned_mx_4 ADD CONSTRAINT fkey_not_inherited FOREIGN KEY (a) REFERENCES local_table_fkey2(a);
-- these two should error out
ALTER TABLE partitioned_mx ATTACH PARTITION partitioned_mx_4 FOR VALUES FROM (13) TO (16);
ALTER TABLE partitioned_mx ATTACH PARTITION partitioned_mx_4 default;
SELECT
nmsp_parent.nspname AS parent_schema,
parent.relname AS parent,
nmsp_child.nspname AS child_schema,
child.relname AS child
FROM pg_inherits
JOIN pg_class parent ON pg_inherits.inhparent = parent.oid
JOIN pg_class child ON pg_inherits.inhrelid = child.oid
JOIN pg_namespace nmsp_parent ON nmsp_parent.oid = parent.relnamespace
JOIN pg_namespace nmsp_child ON nmsp_child.oid = child.relnamespace
WHERE parent.relname='partitioned_mx'
ORDER BY child;
\c - - - :worker_1_port
SELECT relname FROM pg_class WHERE relname LIKE 'partitioned_mx%' ORDER BY relname;
SELECT
nmsp_parent.nspname AS parent_schema,
parent.relname AS parent,
nmsp_child.nspname AS child_schema,
child.relname AS child
FROM pg_inherits
JOIN pg_class parent ON pg_inherits.inhparent = parent.oid
JOIN pg_class child ON pg_inherits.inhrelid = child.oid
JOIN pg_namespace nmsp_parent ON nmsp_parent.oid = parent.relnamespace
JOIN pg_namespace nmsp_child ON nmsp_child.oid = child.relnamespace
WHERE parent.relname='partitioned_mx'
ORDER BY child;
\c - - - :master_port
SET search_path TO citus_local_tables_mx;
SET client_min_messages TO ERROR;
DROP TABLE partitioned_mx;
RESET client_min_messages;
-- test cascading via foreign keys
CREATE TABLE cas_1 (a INT UNIQUE);
CREATE TABLE cas_par (a INT UNIQUE) PARTITION BY RANGE(a);
CREATE TABLE cas_par_1 PARTITION OF cas_par FOR VALUES FROM (1) TO (4);
CREATE TABLE cas_par_2 PARTITION OF cas_par FOR VALUES FROM (5) TO (8);
ALTER TABLE cas_par_1 ADD CONSTRAINT fkey_cas_test_1 FOREIGN KEY (a) REFERENCES cas_1(a);
CREATE TABLE cas_par2 (a INT UNIQUE) PARTITION BY RANGE(a);
CREATE TABLE cas_par2_1 PARTITION OF cas_par2 FOR VALUES FROM (1) TO (4);
CREATE TABLE cas_par2_2 PARTITION OF cas_par2 FOR VALUES FROM (5) TO (8);
ALTER TABLE cas_par2_1 ADD CONSTRAINT fkey_cas_test_2 FOREIGN KEY (a) REFERENCES cas_1(a);
CREATE TABLE cas_par3 (a INT UNIQUE) PARTITION BY RANGE(a);
CREATE TABLE cas_par3_1 PARTITION OF cas_par3 FOR VALUES FROM (1) TO (4);
CREATE TABLE cas_par3_2 PARTITION OF cas_par3 FOR VALUES FROM (5) TO (8);
-- these two should error out as we should call the conversion from the parent
SELECT citus_add_local_table_to_metadata('cas_par2_2');
SELECT citus_add_local_table_to_metadata('cas_par2_2', cascade_via_foreign_keys=>true);
-- these two should error out as the foreign keys are not inherited from the parent
SELECT citus_add_local_table_to_metadata('cas_par2');
SELECT citus_add_local_table_to_metadata('cas_par2', cascade_via_foreign_keys=>true);
-- drop the foreign keys and establish them again using the parent table
ALTER TABLE cas_par_1 DROP CONSTRAINT fkey_cas_test_1;
ALTER TABLE cas_par2_1 DROP CONSTRAINT fkey_cas_test_2;
ALTER TABLE cas_par ADD CONSTRAINT fkey_cas_test_1 FOREIGN KEY (a) REFERENCES cas_1(a);
ALTER TABLE cas_par2 ADD CONSTRAINT fkey_cas_test_2 FOREIGN KEY (a) REFERENCES cas_1(a);
ALTER TABLE cas_par3 ADD CONSTRAINT fkey_cas_test_3 FOREIGN KEY (a) REFERENCES cas_par(a);
-- this should error out as cascade_via_foreign_keys is not set to true
SELECT citus_add_local_table_to_metadata('cas_par2');
-- this should work
SELECT citus_add_local_table_to_metadata('cas_par2', cascade_via_foreign_keys=>true);
-- verify the partitioning hierarchy is preserved
select inhrelid::regclass from pg_inherits where inhparent='cas_par'::regclass order by 1;
-- verify the fkeys + fkeys with shard ids are created
select conname from pg_constraint where conname like 'fkey_cas_test%' order by conname;
-- when all partitions are converted, there should be 40 tables and indexes
-- the individual names are not much relevant, so we only print the count
SELECT count(*) FROM pg_class WHERE relname LIKE 'cas\_%' AND relnamespace IN
(SELECT oid FROM pg_namespace WHERE nspname = 'citus_local_tables_mx');
-- verify on the mx worker
\c - - - :worker_1_port
-- on worker, there should be 20, since the shards are created only on the coordinator
SELECT count(*) FROM pg_class WHERE relname LIKE 'cas\_%' AND relnamespace IN
(SELECT oid FROM pg_namespace WHERE nspname = 'citus_local_tables_mx');
-- verify that the shell foreign keys are created on the worker as well
select conname from pg_constraint where conname like 'fkey_cas_test%' order by conname;
\c - - - :master_port
SET search_path TO citus_local_tables_mx;
-- undistribute table
-- this one should error out since we don't set the cascade option as true
SELECT undistribute_table('cas_par2');
-- this one should work
SET client_min_messages TO WARNING;
SELECT undistribute_table('cas_par2', cascade_via_foreign_keys=>true);
-- verify the partitioning hierarchy is preserved
select inhrelid::regclass from pg_inherits where inhparent='cas_par'::regclass order by 1;
-- verify that the foreign keys with shard ids are gone, due to undistribution
select conname from pg_constraint where conname like 'fkey_cas_test%' order by conname;
-- add a non-inherited fkey and verify it fails when trying to convert
ALTER TABLE cas_par2_1 ADD CONSTRAINT fkey_cas_test_3 FOREIGN KEY (a) REFERENCES cas_1(a);
SELECT citus_add_local_table_to_metadata('cas_par2', cascade_via_foreign_keys=>true);
-- verify undistribute_table works proper for the mx worker
\c - - - :worker_1_port
SELECT relname FROM pg_class WHERE relname LIKE 'cas\_%' ORDER BY relname;
\c - - - :master_port
SET search_path TO citus_local_tables_mx;
CREATE TABLE date_partitioned_citus_local_table_seq( measureid bigserial, eventdate date, measure_data jsonb, PRIMARY KEY (measureid, eventdate)) PARTITION BY RANGE(eventdate);
SELECT create_time_partitions('date_partitioned_citus_local_table_seq', INTERVAL '1 month', '2022-01-01', '2021-01-01');
SELECT citus_add_local_table_to_metadata('date_partitioned_citus_local_table_seq');
DROP TABLE date_partitioned_citus_local_table_seq;
-- test sequences
CREATE TABLE par_citus_local_seq(measureid bigserial, val int) PARTITION BY RANGE(val);
CREATE TABLE par_citus_local_seq_1 PARTITION OF par_citus_local_seq FOR VALUES FROM (1) TO (4);
SELECT citus_add_local_table_to_metadata('par_citus_local_seq');
INSERT INTO par_citus_local_seq (val) VALUES (1) RETURNING *;
INSERT INTO par_citus_local_seq (val) VALUES (2) RETURNING *;
\c - - - :worker_1_port
-- insert on the worker
INSERT INTO citus_local_tables_mx.par_citus_local_seq (val) VALUES (1) RETURNING *;
\c - - - :master_port
SET search_path TO citus_local_tables_mx;
INSERT INTO par_citus_local_seq (val) VALUES (2) RETURNING *;
SELECT undistribute_table('par_citus_local_seq');
INSERT INTO par_citus_local_seq (val) VALUES (3) RETURNING *;
SELECT measureid FROM par_citus_local_seq ORDER BY measureid;
-- test adding invalid foreign key to partition table
CREATE TABLE citus_local_parent_1 (a INT UNIQUE) PARTITION BY RANGE(a);
CREATE TABLE citus_local_parent_2 (a INT UNIQUE) PARTITION BY RANGE(a);
CREATE TABLE citus_local_plain (a INT UNIQUE);
CREATE TABLE ref (a INT UNIQUE);
SELECT create_reference_table('ref');
alter table citus_local_parent_1 add foreign key (a) references citus_local_parent_2(a);
alter table citus_local_plain add foreign key (a) references citus_local_parent_2(a);
CREATE TABLE citus_local_parent_1_child_1 PARTITION OF citus_local_parent_1 FOR VALUES FROM (3) TO (5);
CREATE TABLE citus_local_parent_1_child_2 PARTITION OF citus_local_parent_1 FOR VALUES FROM (30) TO (50);
CREATE TABLE citus_local_parent_2_child_1 PARTITION OF citus_local_parent_2 FOR VALUES FROM (40) TO (60);
-- this one should error out, since we cannot convert it to citus local table,
-- as citus local table partitions cannot have non-inherited foreign keys
alter table citus_local_parent_1_child_1 add foreign key(a) references ref(a);
-- this should work
alter table citus_local_parent_1 add constraint fkey_to_drop_test foreign key(a) references ref(a);
-- this should undistribute the table, and the entries should be gone from pg_dist_partition
select logicalrelid from pg_dist_partition where logicalrelid::text like 'citus_local_parent%';
set client_min_messages to error;
alter table citus_local_parent_1 drop constraint fkey_to_drop_test;
select logicalrelid from pg_dist_partition where logicalrelid::text like 'citus_local_parent%';
SELECT master_remove_distributed_table_metadata_from_workers('citus_local_table_4'::regclass::oid, 'citus_local_tables_mx', 'citus_local_table_4');
-- both workers should print 0 as master_remove_distributed_table_metadata_from_workers
@ -176,6 +350,5 @@ SELECT run_command_on_workers(
$$
SELECT count(*) FROM pg_catalog.pg_tables WHERE tablename='citus_local_table_4'
$$);
-- cleanup at exit
DROP SCHEMA citus_local_tables_mx CASCADE;

View File

@ -76,9 +76,6 @@ ROLLBACK;
BEGIN;
CREATE TABLE partitioned_table (col_1 INT REFERENCES local_table_1 (col_1)) PARTITION BY RANGE (col_1);
-- now that we introduced a partitioned table into our foreign key subgraph,
-- citus_add_local_table_to_metadata(cascade_via_foreign_keys) would fail for
-- partitioned_table as citus_add_local_table_to_metadata doesn't support partitioned tables
SELECT citus_add_local_table_to_metadata('local_table_2', cascade_via_foreign_keys=>true);
ROLLBACK;

View File

@ -82,11 +82,9 @@ CREATE TABLE partitioned_table_1_200_300 PARTITION OF partitioned_table_1 FOR VA
INSERT INTO partitioned_table_1 SELECT i FROM generate_series(195, 205) i;
ALTER TABLE partitioned_table_1 ADD CONSTRAINT fkey_8 FOREIGN KEY (col_1) REFERENCES local_table_4(col_1);
-- now that we attached partitioned table to graph below errors out
-- since we cannot create citus local table from partitioned tables
BEGIN;
ALTER TABLE reference_table_1 ADD CONSTRAINT fkey_9 FOREIGN KEY (col_1) REFERENCES local_table_1(col_1);
ROLLBACK;
ALTER TABLE partitioned_table_1 DROP CONSTRAINT fkey_8;
BEGIN;
@ -405,9 +403,9 @@ SELECT logicalrelid::text AS tablename, partmethod, repmodel FROM pg_dist_partit
WHERE logicalrelid::text IN (SELECT tablename FROM pg_tables WHERE schemaname='fkeys_between_local_ref')
ORDER BY tablename;
-- this errors out as we don't support creating citus local
-- tables from partitioned tables
BEGIN;
CREATE TABLE part_local_table (col_1 INT REFERENCES reference_table_1(col_1)) PARTITION BY RANGE (col_1);
ROLLBACK;
-- they fail as col_99 does not exist
CREATE TABLE local_table_5 (col_1 INT, FOREIGN KEY (col_99) REFERENCES reference_table_1(col_1));

View File

@ -1785,6 +1785,61 @@ ROLLBACK;
DROP TABLE pi_table;
-- 6) test with citus local table
select 1 from citus_add_node('localhost', :master_port, groupid=>0);
CREATE TABLE date_partitioned_citus_local_table(
measureid integer,
eventdate date,
measure_data jsonb) PARTITION BY RANGE(eventdate);
SELECT citus_add_local_table_to_metadata('date_partitioned_citus_local_table');
-- test interval must be multiple days for date partitioned table
SELECT create_time_partitions('date_partitioned_citus_local_table', INTERVAL '6 hours', '2022-01-01', '2021-01-01');
SELECT create_time_partitions('date_partitioned_citus_local_table', INTERVAL '1 week 1 day 1 hour', '2022-01-01', '2021-01-01');
-- test with various intervals
BEGIN;
SELECT create_time_partitions('date_partitioned_citus_local_table', INTERVAL '1 day', '2021-02-01', '2021-01-01');
SELECT * FROM time_partitions WHERE parent_table = 'date_partitioned_citus_local_table'::regclass ORDER BY 3;
ROLLBACK;
BEGIN;
SELECT create_time_partitions('date_partitioned_citus_local_table', INTERVAL '1 week', '2022-01-01', '2021-01-01');
SELECT * FROM time_partitions WHERE parent_table = 'date_partitioned_citus_local_table'::regclass ORDER BY 3;
ROLLBACK;
set client_min_messages to error;
DROP TABLE date_partitioned_citus_local_table;
-- also test with foreign key
CREATE TABLE date_partitioned_citus_local_table(
measureid integer,
eventdate date,
measure_data jsonb, PRIMARY KEY (measureid, eventdate)) PARTITION BY RANGE(eventdate);
SELECT citus_add_local_table_to_metadata('date_partitioned_citus_local_table');
-- test interval must be multiple days for date partitioned table
SELECT create_time_partitions('date_partitioned_citus_local_table', INTERVAL '1 day', '2021-02-01', '2021-01-01');
CREATE TABLE date_partitioned_citus_local_table_2(
measureid integer,
eventdate date,
measure_data jsonb, PRIMARY KEY (measureid, eventdate)) PARTITION BY RANGE(eventdate);
SELECT citus_add_local_table_to_metadata('date_partitioned_citus_local_table_2');
ALTER TABLE date_partitioned_citus_local_table_2 ADD CONSTRAINT fkey_1 FOREIGN KEY (measureid, eventdate) REFERENCES date_partitioned_citus_local_table(measureid, eventdate);
SELECT create_time_partitions('date_partitioned_citus_local_table_2', INTERVAL '1 day', '2021-02-01', '2021-01-01');
-- after the above work, these should also work for creating new partitions
BEGIN;
SELECT create_time_partitions('date_partitioned_citus_local_table', INTERVAL '1 day', '2021-03-01', '2021-02-01');
SELECT * FROM time_partitions WHERE parent_table = 'date_partitioned_citus_local_table'::regclass ORDER BY 3;
ROLLBACK;
BEGIN;
SELECT create_time_partitions('date_partitioned_citus_local_table_2', INTERVAL '1 day', '2021-03-01', '2021-02-01');
SELECT * FROM time_partitions WHERE parent_table = 'date_partitioned_citus_local_table'::regclass ORDER BY 3;
ROLLBACK;
set client_min_messages to notice;
-- c) test drop_old_time_partitions
-- 1) test with date partitioned table
CREATE TABLE date_partitioned_table_to_exp (event_date date, event int) partition by range (event_date);
@ -1858,6 +1913,29 @@ SELECT partition FROM time_partitions WHERE parent_table = '"test !/ \n _dist_12
\set VERBOSITY default
DROP TABLE "test !/ \n _dist_123_table_exp";
-- 4) test with citus local tables
CREATE TABLE date_partitioned_table_to_exp (event_date date, event int) partition by range (event_date);
SELECT citus_add_local_table_to_metadata('date_partitioned_table_to_exp');
CREATE TABLE date_partitioned_table_to_exp_d00 PARTITION OF date_partitioned_table_to_exp FOR VALUES FROM ('2000-01-01') TO ('2009-12-31');
CREATE TABLE date_partitioned_table_to_exp_d10 PARTITION OF date_partitioned_table_to_exp FOR VALUES FROM ('2010-01-01') TO ('2019-12-31');
CREATE TABLE date_partitioned_table_to_exp_d20 PARTITION OF date_partitioned_table_to_exp FOR VALUES FROM ('2020-01-01') TO ('2029-12-31');
\set VERBOSITY terse
-- expire no partitions
CALL drop_old_time_partitions('date_partitioned_table_to_exp', '1999-01-01');
SELECT partition FROM time_partitions WHERE parent_table = 'date_partitioned_table_to_exp'::regclass ORDER BY partition::text;
-- expire 2 old partitions
CALL drop_old_time_partitions('date_partitioned_table_to_exp', '2021-01-01');
SELECT partition FROM time_partitions WHERE parent_table = 'date_partitioned_table_to_exp'::regclass ORDER BY partition::text;
\set VERBOSITY default
DROP TABLE date_partitioned_table_to_exp;
SELECT citus_remove_node('localhost', :master_port);
-- d) invalid tables for helper UDFs
CREATE TABLE multiple_partition_column_table(
event_id bigserial,