mirror of https://github.com/citusdata/citus.git
Fix foreign key non colocated (#4840)
DESCRIPTION: Fix a bug where one could create a foreign key between non-colocated tables Due to the scoping and only setting the variable to true when matched, not false when not matched, it was possible for a foreign key to be created on non-colocated tables. This patch changes the scope and uses an always assign the test result to the variable we prevent users from creating foreign keys between non-colocated tables.release-8.3
parent
6fd6b47601
commit
76608b1307
|
@ -134,10 +134,6 @@ ErrorIfUnsupportedForeignConstraint(Relation relation, char distributionMethod,
|
||||||
int referencedColumnCount = 0;
|
int referencedColumnCount = 0;
|
||||||
bool isNull = false;
|
bool isNull = false;
|
||||||
int attrIdx = 0;
|
int attrIdx = 0;
|
||||||
bool foreignConstraintOnPartitionColumn = false;
|
|
||||||
bool selfReferencingTable = false;
|
|
||||||
bool referencedTableIsAReferenceTable = false;
|
|
||||||
bool referencingColumnsIncludeDistKey = false;
|
|
||||||
|
|
||||||
pgConstraint = heap_open(ConstraintRelationId, AccessShareLock);
|
pgConstraint = heap_open(ConstraintRelationId, AccessShareLock);
|
||||||
ScanKeyInit(&scanKey[0], Anum_pg_constraint_conrelid, BTEqualStrategyNumber, F_OIDEQ,
|
ScanKeyInit(&scanKey[0], Anum_pg_constraint_conrelid, BTEqualStrategyNumber, F_OIDEQ,
|
||||||
|
@ -148,6 +144,10 @@ ErrorIfUnsupportedForeignConstraint(Relation relation, char distributionMethod,
|
||||||
heapTuple = systable_getnext(scanDescriptor);
|
heapTuple = systable_getnext(scanDescriptor);
|
||||||
while (HeapTupleIsValid(heapTuple))
|
while (HeapTupleIsValid(heapTuple))
|
||||||
{
|
{
|
||||||
|
bool foreignConstraintOnPartitionColumn = false;
|
||||||
|
bool selfReferencingTable = false;
|
||||||
|
bool referencedTableIsAReferenceTable = false;
|
||||||
|
bool referencingColumnsIncludeDistKey = false;
|
||||||
Form_pg_constraint constraintForm = (Form_pg_constraint) GETSTRUCT(heapTuple);
|
Form_pg_constraint constraintForm = (Form_pg_constraint) GETSTRUCT(heapTuple);
|
||||||
bool singleReplicatedTable = true;
|
bool singleReplicatedTable = true;
|
||||||
|
|
||||||
|
@ -196,10 +196,8 @@ ErrorIfUnsupportedForeignConstraint(Relation relation, char distributionMethod,
|
||||||
* tables. This is why we make this check under !selfReferencingTable
|
* tables. This is why we make this check under !selfReferencingTable
|
||||||
* and after !IsDistributedTable(referencedTableId).
|
* and after !IsDistributedTable(referencedTableId).
|
||||||
*/
|
*/
|
||||||
if (PartitionMethod(referencedTableId) == DISTRIBUTE_BY_NONE)
|
referencedTableIsAReferenceTable =
|
||||||
{
|
(PartitionMethod(referencedTableId) == DISTRIBUTE_BY_NONE);
|
||||||
referencedTableIsAReferenceTable = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* To enforce foreign constraints, tables must be co-located unless a
|
* To enforce foreign constraints, tables must be co-located unless a
|
||||||
|
|
|
@ -1886,9 +1886,45 @@ ROLLBACK;
|
||||||
DROP TABLE referenced_table CASCADE;
|
DROP TABLE referenced_table CASCADE;
|
||||||
NOTICE: drop cascades to constraint fkey_to_ref on table referencing_table_4
|
NOTICE: drop cascades to constraint fkey_to_ref on table referencing_table_4
|
||||||
DROP TABLE referencing_table;
|
DROP TABLE referencing_table;
|
||||||
|
-- tests specific to an edgecase in citus 8.x where it was possible to create foreign keys
|
||||||
|
-- in between colocation groups due to a bug of foreign key to reference tables
|
||||||
|
CREATE TABLE t1 (a int PRIMARY KEY, b text);
|
||||||
|
CREATE TABLE t2 (a bigint PRIMARY KEY, b text);
|
||||||
|
CREATE TABLE r1 (a int PRIMARY KEY, b text);
|
||||||
|
SELECT create_distributed_table('t1', 'a');
|
||||||
|
create_distributed_table
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT create_distributed_table('t2', 'a');
|
||||||
|
create_distributed_table
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT create_reference_table('r1');
|
||||||
|
create_reference_table
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- this always fails as it should be
|
||||||
|
ALTER TABLE t1 ADD CONSTRAINT c1 FOREIGN KEY (a) REFERENCES t2(a);
|
||||||
|
ERROR: cannot create foreign key constraint since relations are not colocated or not referencing a reference table
|
||||||
|
DETAIL: A distributed table can only have foreign keys if it is referencing another colocated hash distributed table or a reference table
|
||||||
|
-- after we create a foreign key to the reference table, that has a lower order by name,
|
||||||
|
-- we would have been able to create a FK to non-colocated tables
|
||||||
|
ALTER TABLE t1 ADD CONSTRAINT c2 FOREIGN KEY (a) REFERENCES r1(a);
|
||||||
|
ALTER TABLE t1 ADD CONSTRAINT c3 FOREIGN KEY (a) REFERENCES t2(a);
|
||||||
|
ERROR: cannot create foreign key constraint since relations are not colocated or not referencing a reference table
|
||||||
|
DETAIL: A distributed table can only have foreign keys if it is referencing another colocated hash distributed table or a reference table
|
||||||
DROP SCHEMA fkey_reference_table CASCADE;
|
DROP SCHEMA fkey_reference_table CASCADE;
|
||||||
NOTICE: drop cascades to 3 other objects
|
NOTICE: drop cascades to 6 other objects
|
||||||
DETAIL: drop cascades to type foreign_details
|
DETAIL: drop cascades to type foreign_details
|
||||||
drop cascades to view table_fkeys_in_workers
|
drop cascades to view table_fkeys_in_workers
|
||||||
drop cascades to type composite
|
drop cascades to type composite
|
||||||
|
drop cascades to table t1
|
||||||
|
drop cascades to table t2
|
||||||
|
drop cascades to table r1
|
||||||
SET search_path TO DEFAULT;
|
SET search_path TO DEFAULT;
|
||||||
|
|
|
@ -951,5 +951,24 @@ ROLLBACK;
|
||||||
DROP TABLE referenced_table CASCADE;
|
DROP TABLE referenced_table CASCADE;
|
||||||
DROP TABLE referencing_table;
|
DROP TABLE referencing_table;
|
||||||
|
|
||||||
|
-- tests specific to an edgecase in citus 8.x where it was possible to create foreign keys
|
||||||
|
-- in between colocation groups due to a bug of foreign key to reference tables
|
||||||
|
CREATE TABLE t1 (a int PRIMARY KEY, b text);
|
||||||
|
CREATE TABLE t2 (a bigint PRIMARY KEY, b text);
|
||||||
|
CREATE TABLE r1 (a int PRIMARY KEY, b text);
|
||||||
|
|
||||||
|
SELECT create_distributed_table('t1', 'a');
|
||||||
|
SELECT create_distributed_table('t2', 'a');
|
||||||
|
SELECT create_reference_table('r1');
|
||||||
|
|
||||||
|
-- this always fails as it should be
|
||||||
|
ALTER TABLE t1 ADD CONSTRAINT c1 FOREIGN KEY (a) REFERENCES t2(a);
|
||||||
|
|
||||||
|
-- after we create a foreign key to the reference table, that has a lower order by name,
|
||||||
|
-- we would have been able to create a FK to non-colocated tables
|
||||||
|
ALTER TABLE t1 ADD CONSTRAINT c2 FOREIGN KEY (a) REFERENCES r1(a);
|
||||||
|
ALTER TABLE t1 ADD CONSTRAINT c3 FOREIGN KEY (a) REFERENCES t2(a);
|
||||||
|
|
||||||
|
|
||||||
DROP SCHEMA fkey_reference_table CASCADE;
|
DROP SCHEMA fkey_reference_table CASCADE;
|
||||||
SET search_path TO DEFAULT;
|
SET search_path TO DEFAULT;
|
||||||
|
|
Loading…
Reference in New Issue