Adds citus.enable_local_reference_table_foreign_keys

When enabled any foreign keys between local tables and reference
tables supported by converting the local table to a citus local
table.

When the coordinator is not in the metadata, the logic is disabled
as foreign keys are not allowed in this configuration.
pull/4480/head
Onder Kalaci 2021-01-14 19:41:21 +03:00
parent ed58a404d5
commit 30d0a65f40
5 changed files with 94 additions and 2 deletions

View File

@ -42,8 +42,13 @@
#include "utils/syscache.h"
/* controlled via GUC, should be accessed via GetEnableLocalReferenceForeignKeys() */
bool EnableLocalReferenceForeignKeys = true;
/* Local functions forward declarations for unsupported command checks */
static void PostprocessCreateTableStmtForeignKeys(CreateStmt *createStatement);
static bool ShouldEnableLocalReferenceForeignKeys(void);
static void PostprocessCreateTableStmtPartitionOf(CreateStmt *createStatement,
const char *queryString);
static bool AlterTableDefinesFKeyBetweenPostgresAndNonDistTable(
@ -84,6 +89,7 @@ static void SetInterShardDDLTaskRelationShardList(Task *task,
ShardInterval *leftShardInterval,
ShardInterval *rightShardInterval);
/*
* We need to run some of the commands sequentially if there is a foreign constraint
* from/to reference table.
@ -194,6 +200,14 @@ PostprocessCreateTableStmt(CreateStmt *createStatement, const char *queryString)
static void
PostprocessCreateTableStmtForeignKeys(CreateStmt *createStatement)
{
if (!ShouldEnableLocalReferenceForeignKeys())
{
/*
* Either the user disabled foreign keys from/to local/reference tables
* or the coordinator is not in the metadata */
return;
}
/*
* Relation must exist and it is already locked as standard process utility
* is already executed.
@ -227,6 +241,25 @@ PostprocessCreateTableStmtForeignKeys(CreateStmt *createStatement)
}
/*
* ShouldEnableLocalReferenceForeignKeys is a wrapper around getting the GUC
* EnableLocalReferenceForeignKeys. If the coordinator is not added
* to the metadata, the function returns false. Else, the function returns
* the value set by the user
*
*/
static bool
ShouldEnableLocalReferenceForeignKeys(void)
{
if (!EnableLocalReferenceForeignKeys)
{
return false;
}
return CoordinatorAddedAsWorkerNode();
}
/*
* PostprocessCreateTableStmtPartitionOf processes CREATE TABLE ... PARTITION OF
* statements and it checks if user creates the table as a partition of a distributed
@ -412,8 +445,8 @@ PreprocessAlterTableStmt(Node *node, const char *alterTableCommand,
leftRelationId = IndexGetRelation(leftRelationId, missingOk);
}
if (processUtilityContext != PROCESS_UTILITY_SUBCOMMAND &&
CoordinatorAddedAsWorkerNode() &&
if (ShouldEnableLocalReferenceForeignKeys() &&
processUtilityContext != PROCESS_UTILITY_SUBCOMMAND &&
AlterTableDefinesFKeyBetweenPostgresAndNonDistTable(alterTableStatement))
{
/*

View File

@ -585,6 +585,18 @@ RegisterCitusConfigVariables(void)
GUC_STANDARD,
NULL, NULL, NULL);
DefineCustomBoolVariable(
"citus.enable_local_reference_table_foreign_keys",
gettext_noop("Enables foreign keys from/to local tables"),
gettext_noop("When enabled, foreign keys between local tables and reference "
"tables supported."),
&EnableLocalReferenceForeignKeys,
true,
PGC_USERSET,
GUC_STANDARD,
NULL, NULL, NULL);
DefineCustomBoolVariable(
"citus.enable_single_hash_repartition_joins",
gettext_noop("Enables single hash repartitioning between hash "

View File

@ -20,6 +20,11 @@
#include "tcop/dest.h"
#include "tcop/utility.h"
/* controlled via GUC, should be accessed via EnableLocalReferenceForeignKeys() */
extern bool EnableLocalReferenceForeignKeys;
/*
* DistributeObjectOps specifies handlers for node/object type pairs.
* Instances of this type should all be declared in deparse.c.

View File

@ -391,6 +391,28 @@ BEGIN;
reference_table_1 | n | t
(8 rows)
ROLLBACK;
BEGIN;
-- disable foreign keys to reference tables
SET LOCAL citus.enable_local_reference_table_foreign_keys TO false;
CREATE TABLE local_table_6 (col_1 INT PRIMARY KEY);
ALTER TABLE local_table_2 ADD CONSTRAINT fkey_11 FOREIGN KEY (col_1) REFERENCES reference_table_1(col_1) ON DELETE CASCADE;
CREATE TABLE local_table_5 (
col_1 INT UNIQUE REFERENCES local_table_6(col_1),
col_2 INT REFERENCES local_table_3(col_1),
FOREIGN KEY (col_1) REFERENCES local_table_5(col_1),
FOREIGN KEY (col_1) REFERENCES reference_table_1(col_1));
-- Now show none of local_table_5 & 6 to should be converted to citus local tables
-- as it is disabled
SELECT logicalrelid::text AS tablename, partmethod, repmodel FROM pg_dist_partition
WHERE logicalrelid::text IN (SELECT tablename FROM pg_tables WHERE schemaname='fkeys_between_local_ref')
ORDER BY tablename;
tablename | partmethod | repmodel
---------------------------------------------------------------------
distributed_table | h | c
reference_table_1 | n | t
(2 rows)
ROLLBACK;
-- this errors out as we don't support creating citus local
-- tables from partitioned tables

View File

@ -285,6 +285,26 @@ BEGIN;
ORDER BY tablename;
ROLLBACK;
BEGIN;
-- disable foreign keys to reference tables
SET LOCAL citus.enable_local_reference_table_foreign_keys TO false;
CREATE TABLE local_table_6 (col_1 INT PRIMARY KEY);
ALTER TABLE local_table_2 ADD CONSTRAINT fkey_11 FOREIGN KEY (col_1) REFERENCES reference_table_1(col_1) ON DELETE CASCADE;
CREATE TABLE local_table_5 (
col_1 INT UNIQUE REFERENCES local_table_6(col_1),
col_2 INT REFERENCES local_table_3(col_1),
FOREIGN KEY (col_1) REFERENCES local_table_5(col_1),
FOREIGN KEY (col_1) REFERENCES reference_table_1(col_1));
-- Now show none of local_table_5 & 6 to should be converted to citus local tables
-- as it is disabled
SELECT logicalrelid::text AS tablename, partmethod, repmodel FROM pg_dist_partition
WHERE logicalrelid::text IN (SELECT tablename FROM pg_tables WHERE schemaname='fkeys_between_local_ref')
ORDER BY tablename;
ROLLBACK;
-- this errors out as we don't support creating citus local
-- tables from partitioned tables
CREATE TABLE part_local_table (col_1 INT REFERENCES reference_table_1(col_1)) PARTITION BY RANGE (col_1);