mirror of https://github.com/citusdata/citus.git
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
parent
ed58a404d5
commit
30d0a65f40
|
@ -42,8 +42,13 @@
|
||||||
#include "utils/syscache.h"
|
#include "utils/syscache.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* controlled via GUC, should be accessed via GetEnableLocalReferenceForeignKeys() */
|
||||||
|
bool EnableLocalReferenceForeignKeys = true;
|
||||||
|
|
||||||
|
|
||||||
/* Local functions forward declarations for unsupported command checks */
|
/* Local functions forward declarations for unsupported command checks */
|
||||||
static void PostprocessCreateTableStmtForeignKeys(CreateStmt *createStatement);
|
static void PostprocessCreateTableStmtForeignKeys(CreateStmt *createStatement);
|
||||||
|
static bool ShouldEnableLocalReferenceForeignKeys(void);
|
||||||
static void PostprocessCreateTableStmtPartitionOf(CreateStmt *createStatement,
|
static void PostprocessCreateTableStmtPartitionOf(CreateStmt *createStatement,
|
||||||
const char *queryString);
|
const char *queryString);
|
||||||
static bool AlterTableDefinesFKeyBetweenPostgresAndNonDistTable(
|
static bool AlterTableDefinesFKeyBetweenPostgresAndNonDistTable(
|
||||||
|
@ -84,6 +89,7 @@ static void SetInterShardDDLTaskRelationShardList(Task *task,
|
||||||
ShardInterval *leftShardInterval,
|
ShardInterval *leftShardInterval,
|
||||||
ShardInterval *rightShardInterval);
|
ShardInterval *rightShardInterval);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We need to run some of the commands sequentially if there is a foreign constraint
|
* We need to run some of the commands sequentially if there is a foreign constraint
|
||||||
* from/to reference table.
|
* from/to reference table.
|
||||||
|
@ -194,6 +200,14 @@ PostprocessCreateTableStmt(CreateStmt *createStatement, const char *queryString)
|
||||||
static void
|
static void
|
||||||
PostprocessCreateTableStmtForeignKeys(CreateStmt *createStatement)
|
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
|
* Relation must exist and it is already locked as standard process utility
|
||||||
* is already executed.
|
* 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
|
* PostprocessCreateTableStmtPartitionOf processes CREATE TABLE ... PARTITION OF
|
||||||
* statements and it checks if user creates the table as a partition of a distributed
|
* 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);
|
leftRelationId = IndexGetRelation(leftRelationId, missingOk);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (processUtilityContext != PROCESS_UTILITY_SUBCOMMAND &&
|
if (ShouldEnableLocalReferenceForeignKeys() &&
|
||||||
CoordinatorAddedAsWorkerNode() &&
|
processUtilityContext != PROCESS_UTILITY_SUBCOMMAND &&
|
||||||
AlterTableDefinesFKeyBetweenPostgresAndNonDistTable(alterTableStatement))
|
AlterTableDefinesFKeyBetweenPostgresAndNonDistTable(alterTableStatement))
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -585,6 +585,18 @@ RegisterCitusConfigVariables(void)
|
||||||
GUC_STANDARD,
|
GUC_STANDARD,
|
||||||
NULL, NULL, NULL);
|
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(
|
DefineCustomBoolVariable(
|
||||||
"citus.enable_single_hash_repartition_joins",
|
"citus.enable_single_hash_repartition_joins",
|
||||||
gettext_noop("Enables single hash repartitioning between hash "
|
gettext_noop("Enables single hash repartitioning between hash "
|
||||||
|
|
|
@ -20,6 +20,11 @@
|
||||||
#include "tcop/dest.h"
|
#include "tcop/dest.h"
|
||||||
#include "tcop/utility.h"
|
#include "tcop/utility.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* controlled via GUC, should be accessed via EnableLocalReferenceForeignKeys() */
|
||||||
|
extern bool EnableLocalReferenceForeignKeys;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* DistributeObjectOps specifies handlers for node/object type pairs.
|
* DistributeObjectOps specifies handlers for node/object type pairs.
|
||||||
* Instances of this type should all be declared in deparse.c.
|
* Instances of this type should all be declared in deparse.c.
|
||||||
|
|
|
@ -391,6 +391,28 @@ BEGIN;
|
||||||
reference_table_1 | n | t
|
reference_table_1 | n | t
|
||||||
(8 rows)
|
(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;
|
ROLLBACK;
|
||||||
-- this errors out as we don't support creating citus local
|
-- this errors out as we don't support creating citus local
|
||||||
-- tables from partitioned tables
|
-- tables from partitioned tables
|
||||||
|
|
|
@ -285,6 +285,26 @@ BEGIN;
|
||||||
ORDER BY tablename;
|
ORDER BY tablename;
|
||||||
ROLLBACK;
|
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
|
-- this errors out as we don't support creating citus local
|
||||||
-- tables from partitioned tables
|
-- tables from partitioned tables
|
||||||
CREATE TABLE part_local_table (col_1 INT REFERENCES reference_table_1(col_1)) PARTITION BY RANGE (col_1);
|
CREATE TABLE part_local_table (col_1 INT REFERENCES reference_table_1(col_1)) PARTITION BY RANGE (col_1);
|
||||||
|
|
Loading…
Reference in New Issue