mirror of https://github.com/citusdata/citus.git
Error out on foreign keys with reference tables
We have one replication of reference table for each node. Therefore all problems with replication factor > 1 also applies to reference table. As a solution we will not allow foreign keys on reference tables. It is not possible to define foreign key from, to or between reference tables.pull/1061/head
parent
19b96a17c1
commit
bb9e95e134
|
@ -408,12 +408,14 @@ ErrorIfNotSupportedConstraint(Relation relation, char distributionMethod,
|
|||
List *indexOidList = NULL;
|
||||
ListCell *indexOidCell = NULL;
|
||||
|
||||
/* we first perform check for foreign constraints */
|
||||
ErrorIfNotSupportedForeignConstraint(relation, distributionMethod, distributionColumn,
|
||||
colocationId);
|
||||
|
||||
/*
|
||||
* Citus supports any kind of uniqueness constraints for reference tables
|
||||
* given that they only consist of a single shard and we can simply rely on
|
||||
* Postgres.
|
||||
* TODO: Here we should be erroring out if there exists any foreign keys
|
||||
* from/to a reference table.
|
||||
*/
|
||||
if (distributionMethod == DISTRIBUTE_BY_NONE)
|
||||
{
|
||||
|
@ -499,10 +501,6 @@ ErrorIfNotSupportedConstraint(Relation relation, char distributionMethod,
|
|||
|
||||
index_close(indexDesc, NoLock);
|
||||
}
|
||||
|
||||
/* we also perform check for foreign constraints */
|
||||
ErrorIfNotSupportedForeignConstraint(relation, distributionMethod, distributionColumn,
|
||||
colocationId);
|
||||
}
|
||||
|
||||
|
||||
|
@ -560,6 +558,19 @@ ErrorIfNotSupportedForeignConstraint(Relation relation, char distributionMethod,
|
|||
continue;
|
||||
}
|
||||
|
||||
referencedTableId = constraintForm->confrelid;
|
||||
|
||||
/* we do not support foreign keys for reference tables */
|
||||
if (distributionMethod == DISTRIBUTE_BY_NONE ||
|
||||
(relation->rd_id != referencedTableId &&
|
||||
PartitionMethod(referencedTableId) == DISTRIBUTE_BY_NONE))
|
||||
{
|
||||
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("cannot create foreign key constraint"),
|
||||
errdetail("Foreign key constraints are not allowed from or "
|
||||
"to reference tables.")));
|
||||
}
|
||||
|
||||
/*
|
||||
* ON DELETE SET NULL and ON DELETE SET DEFAULT is not supported. Because we do
|
||||
* not want to set partition column to NULL or default value.
|
||||
|
@ -589,8 +600,6 @@ ErrorIfNotSupportedForeignConstraint(Relation relation, char distributionMethod,
|
|||
" supported in ON UPDATE operation.")));
|
||||
}
|
||||
|
||||
referencedTableId = constraintForm->confrelid;
|
||||
|
||||
/*
|
||||
* Some checks are not meaningful if foreign key references the table itself.
|
||||
* Therefore we will skip those checks.
|
||||
|
|
|
@ -1494,6 +1494,23 @@ ErrorIfUnsupportedAlterTableStmt(AlterTableStmt *alterTableStatement)
|
|||
errhint("You can issue each subcommand separately")));
|
||||
}
|
||||
|
||||
referencingTableId = RangeVarGetRelid(alterTableStatement->relation,
|
||||
lockmode,
|
||||
alterTableStatement->missing_ok);
|
||||
referencedTableId = RangeVarGetRelid(constraint->pktable, lockmode,
|
||||
alterTableStatement->missing_ok);
|
||||
|
||||
/* we do not support foreign keys for reference tables */
|
||||
if (PartitionMethod(referencingTableId) == DISTRIBUTE_BY_NONE ||
|
||||
PartitionMethod(referencedTableId) == DISTRIBUTE_BY_NONE)
|
||||
{
|
||||
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("cannot create foreign key constraint"),
|
||||
errdetail(
|
||||
"Foreign key constraints are not allowed from or "
|
||||
"to reference tables.")));
|
||||
}
|
||||
|
||||
/*
|
||||
* ON DELETE SET NULL and ON DELETE SET DEFAULT is not supported. Because
|
||||
* we do not want to set partition column to NULL or default value.
|
||||
|
@ -1538,12 +1555,6 @@ ErrorIfUnsupportedAlterTableStmt(AlterTableStmt *alterTableStatement)
|
|||
}
|
||||
|
||||
/* to enforce foreign constraints, tables must be co-located */
|
||||
referencingTableId = RangeVarGetRelid(alterTableStatement->relation,
|
||||
lockmode,
|
||||
alterTableStatement->missing_ok);
|
||||
referencedTableId = RangeVarGetRelid(constraint->pktable, lockmode,
|
||||
alterTableStatement->missing_ok);
|
||||
|
||||
if (!TablesColocated(referencingTableId, referencedTableId))
|
||||
{
|
||||
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
|
|
|
@ -773,3 +773,64 @@ SELECT * FROM self_referencing_table2;
|
|||
|
||||
-- we no longer need those tables
|
||||
DROP TABLE self_referencing_table2;
|
||||
-- test reference tables
|
||||
-- test foreign key creation on CREATE TABLE from reference table
|
||||
CREATE TABLE referenced_by_reference_table(id int PRIMARY KEY, other_column int);
|
||||
SELECT create_distributed_table('referenced_by_reference_table', 'id');
|
||||
create_distributed_table
|
||||
--------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
CREATE TABLE reference_table(id int, referencing_column int REFERENCES referenced_by_reference_table(id));
|
||||
SELECT create_reference_table('reference_table');
|
||||
ERROR: cannot create foreign key constraint
|
||||
DETAIL: Foreign key constraints are not allowed from or to reference tables.
|
||||
-- test foreign key creation on CREATE TABLE to reference table
|
||||
DROP TABLE reference_table;
|
||||
CREATE TABLE reference_table(id int PRIMARY KEY, referencing_column int);
|
||||
SELECT create_reference_table('reference_table');
|
||||
create_reference_table
|
||||
------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
CREATE TABLE references_to_reference_table(id int, referencing_column int REFERENCES reference_table(id));
|
||||
SELECT create_distributed_table('references_to_reference_table', 'referencing_column');
|
||||
ERROR: cannot create foreign key constraint
|
||||
DETAIL: Foreign key constraints are not allowed from or to reference tables.
|
||||
-- test foreign key creation on CREATE TABLE from + to reference table
|
||||
CREATE TABLE reference_table2(id int, referencing_column int REFERENCES reference_table(id));
|
||||
SELECT create_reference_table('reference_table2');
|
||||
ERROR: cannot create foreign key constraint
|
||||
DETAIL: Foreign key constraints are not allowed from or to reference tables.
|
||||
-- test foreign key creation on ALTER TABLE from reference table
|
||||
ALTER TABLE reference_table ADD CONSTRAINT fk FOREIGN KEY(referencing_column) REFERENCES referenced_by_reference_table(id);
|
||||
ERROR: cannot create foreign key constraint
|
||||
DETAIL: Foreign key constraints are not allowed from or to reference tables.
|
||||
-- test foreign key creation on ALTER TABLE to reference table
|
||||
DROP TABLE references_to_reference_table;
|
||||
CREATE TABLE references_to_reference_table(id int, referencing_column int);
|
||||
SELECT create_distributed_table('references_to_reference_table', 'referencing_column');
|
||||
create_distributed_table
|
||||
--------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
ALTER TABLE references_to_reference_table ADD CONSTRAINT fk FOREIGN KEY(referencing_column) REFERENCES reference_table(id);
|
||||
ERROR: cannot create foreign key constraint
|
||||
DETAIL: Foreign key constraints are not allowed from or to reference tables.
|
||||
-- test foreign key creation on ALTER TABLE from + to reference table
|
||||
DROP TABLE reference_table2;
|
||||
CREATE TABLE reference_table2(id int, referencing_column int);
|
||||
SELECT create_reference_table('reference_table2');
|
||||
create_reference_table
|
||||
------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
ALTER TABLE reference_table2 ADD CONSTRAINT fk FOREIGN KEY(referencing_column) REFERENCES reference_table(id);
|
||||
ERROR: cannot create foreign key constraint
|
||||
DETAIL: Foreign key constraints are not allowed from or to reference tables.
|
||||
-- we no longer need those tables
|
||||
DROP TABLE referenced_by_reference_table, references_to_reference_table, reference_table, reference_table2;
|
||||
|
|
|
@ -449,3 +449,42 @@ SELECT * FROM self_referencing_table2;
|
|||
|
||||
-- we no longer need those tables
|
||||
DROP TABLE self_referencing_table2;
|
||||
|
||||
|
||||
-- test reference tables
|
||||
-- test foreign key creation on CREATE TABLE from reference table
|
||||
CREATE TABLE referenced_by_reference_table(id int PRIMARY KEY, other_column int);
|
||||
SELECT create_distributed_table('referenced_by_reference_table', 'id');
|
||||
|
||||
CREATE TABLE reference_table(id int, referencing_column int REFERENCES referenced_by_reference_table(id));
|
||||
SELECT create_reference_table('reference_table');
|
||||
|
||||
-- test foreign key creation on CREATE TABLE to reference table
|
||||
DROP TABLE reference_table;
|
||||
CREATE TABLE reference_table(id int PRIMARY KEY, referencing_column int);
|
||||
SELECT create_reference_table('reference_table');
|
||||
|
||||
CREATE TABLE references_to_reference_table(id int, referencing_column int REFERENCES reference_table(id));
|
||||
SELECT create_distributed_table('references_to_reference_table', 'referencing_column');
|
||||
|
||||
-- test foreign key creation on CREATE TABLE from + to reference table
|
||||
CREATE TABLE reference_table2(id int, referencing_column int REFERENCES reference_table(id));
|
||||
SELECT create_reference_table('reference_table2');
|
||||
|
||||
-- test foreign key creation on ALTER TABLE from reference table
|
||||
ALTER TABLE reference_table ADD CONSTRAINT fk FOREIGN KEY(referencing_column) REFERENCES referenced_by_reference_table(id);
|
||||
|
||||
-- test foreign key creation on ALTER TABLE to reference table
|
||||
DROP TABLE references_to_reference_table;
|
||||
CREATE TABLE references_to_reference_table(id int, referencing_column int);
|
||||
SELECT create_distributed_table('references_to_reference_table', 'referencing_column');
|
||||
ALTER TABLE references_to_reference_table ADD CONSTRAINT fk FOREIGN KEY(referencing_column) REFERENCES reference_table(id);
|
||||
|
||||
-- test foreign key creation on ALTER TABLE from + to reference table
|
||||
DROP TABLE reference_table2;
|
||||
CREATE TABLE reference_table2(id int, referencing_column int);
|
||||
SELECT create_reference_table('reference_table2');
|
||||
ALTER TABLE reference_table2 ADD CONSTRAINT fk FOREIGN KEY(referencing_column) REFERENCES reference_table(id);
|
||||
|
||||
-- we no longer need those tables
|
||||
DROP TABLE referenced_by_reference_table, references_to_reference_table, reference_table, reference_table2;
|
||||
|
|
Loading…
Reference in New Issue