mirror of https://github.com/citusdata/citus.git
Not allow ON DELETE/UPDATE SET DEFAULT actions on columns that default to sequences (#6340)
Given that we drop DEFAULT nextval('sequence') expressions from
shard relation columns, allowing `ON DELETE/UPDATE SET DEFAULT`
on such columns might cause inserting NULL values as a result
of a delete/update operation.
For this reason, we disallow ON DELETE/UPDATE SET DEFAULT actions
on columns that default to sequences.
DESCRIPTION: Disallows having ON DELETE/UPDATE SET DEFAULT actions on
columns that default to sequences
Fixes #6339.
(cherry picked from commit a868cc049a
)
Conflicts:
src/test/regress/expected/pg15.out
src/test/regress/sql/pg15.sql
valgrind-problem
parent
53ec5abb75
commit
b9e4364acc
|
@ -23,12 +23,14 @@
|
||||||
#include "catalog/pg_type.h"
|
#include "catalog/pg_type.h"
|
||||||
#include "distributed/colocation_utils.h"
|
#include "distributed/colocation_utils.h"
|
||||||
#include "distributed/commands.h"
|
#include "distributed/commands.h"
|
||||||
|
#include "distributed/commands/sequence.h"
|
||||||
#include "distributed/coordinator_protocol.h"
|
#include "distributed/coordinator_protocol.h"
|
||||||
#include "distributed/listutils.h"
|
#include "distributed/listutils.h"
|
||||||
#include "distributed/coordinator_protocol.h"
|
#include "distributed/coordinator_protocol.h"
|
||||||
#include "distributed/multi_join_order.h"
|
#include "distributed/multi_join_order.h"
|
||||||
#include "distributed/namespace_utils.h"
|
#include "distributed/namespace_utils.h"
|
||||||
#include "distributed/reference_table_utils.h"
|
#include "distributed/reference_table_utils.h"
|
||||||
|
#include "distributed/utils/array_type.h"
|
||||||
#include "distributed/version_compat.h"
|
#include "distributed/version_compat.h"
|
||||||
#include "miscadmin.h"
|
#include "miscadmin.h"
|
||||||
#include "utils/builtins.h"
|
#include "utils/builtins.h"
|
||||||
|
@ -57,6 +59,8 @@ typedef bool (*CheckRelationFunc)(Oid);
|
||||||
/* Local functions forward declarations */
|
/* Local functions forward declarations */
|
||||||
static void EnsureReferencingTableNotReplicated(Oid referencingTableId);
|
static void EnsureReferencingTableNotReplicated(Oid referencingTableId);
|
||||||
static void EnsureSupportedFKeyOnDistKey(Form_pg_constraint constraintForm);
|
static void EnsureSupportedFKeyOnDistKey(Form_pg_constraint constraintForm);
|
||||||
|
static bool ForeignKeySetsNextValColumnToDefault(HeapTuple pgConstraintTuple);
|
||||||
|
static List * ForeignKeyGetDefaultingAttrs(HeapTuple pgConstraintTuple);
|
||||||
static void EnsureSupportedFKeyBetweenCitusLocalAndRefTable(Form_pg_constraint
|
static void EnsureSupportedFKeyBetweenCitusLocalAndRefTable(Form_pg_constraint
|
||||||
constraintForm,
|
constraintForm,
|
||||||
char
|
char
|
||||||
|
@ -256,6 +260,23 @@ ErrorIfUnsupportedForeignConstraintExists(Relation relation, char referencingDis
|
||||||
referencedReplicationModel = referencingReplicationModel;
|
referencedReplicationModel = referencingReplicationModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Given that we drop DEFAULT nextval('sequence') expressions from
|
||||||
|
* shard relation columns, allowing ON DELETE/UPDATE SET DEFAULT
|
||||||
|
* on such columns causes inserting NULL values to referencing relation
|
||||||
|
* as a result of a delete/update operation on referenced relation.
|
||||||
|
*
|
||||||
|
* For this reason, we disallow ON DELETE/UPDATE SET DEFAULT actions
|
||||||
|
* on columns that default to sequences.
|
||||||
|
*/
|
||||||
|
if (ForeignKeySetsNextValColumnToDefault(heapTuple))
|
||||||
|
{
|
||||||
|
ereport(ERROR, (errmsg("cannot create foreign key constraint "
|
||||||
|
"since Citus does not support ON DELETE "
|
||||||
|
"/ UPDATE SET DEFAULT actions on the "
|
||||||
|
"columns that default to sequences")));
|
||||||
|
}
|
||||||
|
|
||||||
bool referencingIsCitusLocalOrRefTable =
|
bool referencingIsCitusLocalOrRefTable =
|
||||||
(referencingDistMethod == DISTRIBUTE_BY_NONE);
|
(referencingDistMethod == DISTRIBUTE_BY_NONE);
|
||||||
bool referencedIsCitusLocalOrRefTable =
|
bool referencedIsCitusLocalOrRefTable =
|
||||||
|
@ -358,6 +379,104 @@ ErrorIfUnsupportedForeignConstraintExists(Relation relation, char referencingDis
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ForeignKeySetsNextValColumnToDefault returns true if at least one of the
|
||||||
|
* columns specified in ON DELETE / UPDATE SET DEFAULT clauses default to
|
||||||
|
* nextval().
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
ForeignKeySetsNextValColumnToDefault(HeapTuple pgConstraintTuple)
|
||||||
|
{
|
||||||
|
Form_pg_constraint pgConstraintForm =
|
||||||
|
(Form_pg_constraint) GETSTRUCT(pgConstraintTuple);
|
||||||
|
|
||||||
|
List *setDefaultAttrs = ForeignKeyGetDefaultingAttrs(pgConstraintTuple);
|
||||||
|
AttrNumber setDefaultAttr = InvalidAttrNumber;
|
||||||
|
foreach_int(setDefaultAttr, setDefaultAttrs)
|
||||||
|
{
|
||||||
|
if (ColumnDefaultsToNextVal(pgConstraintForm->conrelid, setDefaultAttr))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ForeignKeyGetDefaultingAttrs returns a list of AttrNumbers
|
||||||
|
* might be set to default ON DELETE or ON UPDATE.
|
||||||
|
*
|
||||||
|
* For example; if the foreign key has SET DEFAULT clause for
|
||||||
|
* both actions, then returns a superset of the attributes that
|
||||||
|
* might be set to DEFAULT on either of those actions.
|
||||||
|
*/
|
||||||
|
static List *
|
||||||
|
ForeignKeyGetDefaultingAttrs(HeapTuple pgConstraintTuple)
|
||||||
|
{
|
||||||
|
bool isNull = false;
|
||||||
|
Datum referencingColumnsDatum = SysCacheGetAttr(CONSTROID, pgConstraintTuple,
|
||||||
|
Anum_pg_constraint_conkey, &isNull);
|
||||||
|
if (isNull)
|
||||||
|
{
|
||||||
|
ereport(ERROR, (errmsg("got NULL conkey from catalog")));
|
||||||
|
}
|
||||||
|
|
||||||
|
List *referencingColumns =
|
||||||
|
IntegerArrayTypeToList(DatumGetArrayTypeP(referencingColumnsDatum));
|
||||||
|
|
||||||
|
Form_pg_constraint pgConstraintForm =
|
||||||
|
(Form_pg_constraint) GETSTRUCT(pgConstraintTuple);
|
||||||
|
if (pgConstraintForm->confupdtype == FKCONSTR_ACTION_SETDEFAULT)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Postgres doesn't allow specifying SET DEFAULT for a subset of
|
||||||
|
* the referencing columns for ON UPDATE action, so in that case
|
||||||
|
* we return all referencing columns regardless of what ON DELETE
|
||||||
|
* action says.
|
||||||
|
*/
|
||||||
|
return referencingColumns;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pgConstraintForm->confdeltype != FKCONSTR_ACTION_SETDEFAULT)
|
||||||
|
{
|
||||||
|
return NIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
List *onDeleteSetDefColumnList = NIL;
|
||||||
|
#if PG_VERSION_NUM >= PG_VERSION_15
|
||||||
|
Datum onDeleteSetDefColumnsDatum = SysCacheGetAttr(CONSTROID, pgConstraintTuple,
|
||||||
|
Anum_pg_constraint_confdelsetcols,
|
||||||
|
&isNull);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* confdelsetcols being NULL means that "ON DELETE SET DEFAULT" doesn't
|
||||||
|
* specify which subset of columns should be set to DEFAULT, so fetching
|
||||||
|
* NULL from the catalog is also possible.
|
||||||
|
*/
|
||||||
|
if (!isNull)
|
||||||
|
{
|
||||||
|
onDeleteSetDefColumnList =
|
||||||
|
IntegerArrayTypeToList(DatumGetArrayTypeP(onDeleteSetDefColumnsDatum));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (list_length(onDeleteSetDefColumnList) == 0)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* That means that all referencing columns need to be set to
|
||||||
|
* DEFAULT.
|
||||||
|
*/
|
||||||
|
return referencingColumns;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return onDeleteSetDefColumnList;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* EnsureSupportedFKeyBetweenCitusLocalAndRefTable is a helper function that
|
* EnsureSupportedFKeyBetweenCitusLocalAndRefTable is a helper function that
|
||||||
* takes a foreign key constraint form for a foreign key between two citus
|
* takes a foreign key constraint form for a foreign key between two citus
|
||||||
|
|
|
@ -1172,5 +1172,108 @@ SELECT create_distributed_table ('dropfkeytest2', 'x', colocate_with:='none');
|
||||||
|
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
|
CREATE TABLE set_on_default_test_referenced(
|
||||||
|
col_1 int, col_2 int, col_3 int, col_4 int,
|
||||||
|
unique (col_1, col_3)
|
||||||
|
);
|
||||||
|
SELECT create_reference_table('set_on_default_test_referenced');
|
||||||
|
create_reference_table
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
CREATE TABLE set_on_default_test_referencing(
|
||||||
|
col_1 int, col_2 int, col_3 serial, col_4 int,
|
||||||
|
FOREIGN KEY(col_1, col_3)
|
||||||
|
REFERENCES set_on_default_test_referenced(col_1, col_3)
|
||||||
|
ON UPDATE SET DEFAULT
|
||||||
|
);
|
||||||
|
-- from distributed / reference to reference, fkey exists before calling the UDFs
|
||||||
|
SELECT create_distributed_table('set_on_default_test_referencing', 'col_1');
|
||||||
|
ERROR: cannot create foreign key constraint since Citus does not support ON DELETE / UPDATE SET DEFAULT actions on the columns that default to sequences
|
||||||
|
SELECT create_reference_table('set_on_default_test_referencing');
|
||||||
|
ERROR: cannot create foreign key constraint since Citus does not support ON DELETE / UPDATE SET DEFAULT actions on the columns that default to sequences
|
||||||
|
DROP TABLE set_on_default_test_referencing;
|
||||||
|
CREATE TABLE set_on_default_test_referencing(
|
||||||
|
col_1 serial, col_2 int, col_3 int, col_4 int
|
||||||
|
);
|
||||||
|
SELECT create_reference_table('set_on_default_test_referencing');
|
||||||
|
create_reference_table
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- from reference to reference, fkey doesn't exist before calling the UDFs
|
||||||
|
ALTER TABLE set_on_default_test_referencing ADD CONSTRAINT fkey
|
||||||
|
FOREIGN KEY(col_1, col_3) REFERENCES set_on_default_test_referenced(col_1, col_3)
|
||||||
|
ON DELETE SET DEFAULT;
|
||||||
|
ERROR: cannot create foreign key constraint since Citus does not support ON DELETE / UPDATE SET DEFAULT actions on the columns that default to sequences
|
||||||
|
DROP TABLE set_on_default_test_referencing;
|
||||||
|
CREATE TABLE set_on_default_test_referencing(
|
||||||
|
col_1 int, col_2 serial, col_3 int, col_4 bigserial
|
||||||
|
);
|
||||||
|
SELECT create_reference_table('set_on_default_test_referencing');
|
||||||
|
create_reference_table
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- ok since referencing columns are not based on sequences
|
||||||
|
ALTER TABLE set_on_default_test_referencing ADD CONSTRAINT fkey
|
||||||
|
FOREIGN KEY(col_1, col_3) REFERENCES set_on_default_test_referenced(col_1, col_3)
|
||||||
|
ON DELETE SET DEFAULT;
|
||||||
|
DROP TABLE set_on_default_test_referencing;
|
||||||
|
CREATE SEQUENCE test_sequence;
|
||||||
|
CREATE TABLE set_on_default_test_referencing(
|
||||||
|
col_1 int, col_2 int, col_3 int DEFAULT nextval('test_sequence'), col_4 int
|
||||||
|
);
|
||||||
|
SELECT create_distributed_table('set_on_default_test_referencing', 'col_1');
|
||||||
|
create_distributed_table
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- from distributed to reference, fkey doesn't exist before calling the UDFs
|
||||||
|
ALTER TABLE set_on_default_test_referencing ADD CONSTRAINT fkey
|
||||||
|
FOREIGN KEY(col_1, col_3) REFERENCES set_on_default_test_referenced(col_1, col_3)
|
||||||
|
ON DELETE SET DEFAULT ON UPDATE SET DEFAULT;
|
||||||
|
ERROR: cannot create foreign key constraint since Citus does not support ON DELETE / UPDATE SET DEFAULT actions on the columns that default to sequences
|
||||||
|
DROP TABLE set_on_default_test_referenced;
|
||||||
|
CREATE TABLE set_on_default_test_referenced(
|
||||||
|
col_1 int, col_2 int, col_3 int, col_4 int,
|
||||||
|
unique (col_1, col_3)
|
||||||
|
);
|
||||||
|
SELECT create_distributed_table('set_on_default_test_referenced', 'col_1');
|
||||||
|
create_distributed_table
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
DROP TABLE set_on_default_test_referencing;
|
||||||
|
CREATE TABLE set_on_default_test_referencing(
|
||||||
|
col_1 bigserial, col_2 int, col_3 int DEFAULT nextval('test_sequence'), col_4 int,
|
||||||
|
FOREIGN KEY(col_1, col_3)
|
||||||
|
REFERENCES set_on_default_test_referenced(col_1, col_3)
|
||||||
|
ON DELETE SET DEFAULT
|
||||||
|
);
|
||||||
|
-- from distributed to distributed, fkey exists before calling the UDFs
|
||||||
|
SELECT create_distributed_table('set_on_default_test_referencing', 'col_1');
|
||||||
|
ERROR: cannot create foreign key constraint since Citus does not support ON DELETE / UPDATE SET DEFAULT actions on the columns that default to sequences
|
||||||
|
DROP TABLE set_on_default_test_referencing;
|
||||||
|
CREATE TABLE set_on_default_test_referencing(
|
||||||
|
col_1 int DEFAULT nextval('test_sequence'), col_2 int, col_3 int, col_4 int
|
||||||
|
);
|
||||||
|
SELECT create_distributed_table('set_on_default_test_referencing', 'col_1');
|
||||||
|
create_distributed_table
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- from distributed to distributed, fkey doesn't exist before calling the UDFs
|
||||||
|
ALTER TABLE set_on_default_test_referencing ADD CONSTRAINT fkey
|
||||||
|
FOREIGN KEY(col_1, col_3) REFERENCES set_on_default_test_referenced(col_1, col_3)
|
||||||
|
ON DELETE SET DEFAULT;
|
||||||
|
ERROR: cannot create foreign key constraint since Citus does not support ON DELETE / UPDATE SET DEFAULT actions on the columns that default to sequences
|
||||||
-- we no longer need those tables
|
-- we no longer need those tables
|
||||||
DROP TABLE referenced_by_reference_table, references_to_reference_table, reference_table, reference_table_second, referenced_local_table, self_referencing_reference_table, dropfkeytest2;
|
DROP TABLE referenced_by_reference_table, references_to_reference_table, reference_table, reference_table_second, referenced_local_table, self_referencing_reference_table, dropfkeytest2,
|
||||||
|
set_on_default_test_referenced, set_on_default_test_referencing;
|
||||||
|
|
|
@ -930,6 +930,72 @@ WARNING: not propagating CLUSTER command for partitioned table to worker nodes
|
||||||
HINT: Provide a child partition table names in order to CLUSTER distributed partitioned tables.
|
HINT: Provide a child partition table names in order to CLUSTER distributed partitioned tables.
|
||||||
-- verify that we can still cluster the partition tables now since replication factor is 1
|
-- verify that we can still cluster the partition tables now since replication factor is 1
|
||||||
CLUSTER sale_newyork_repl_factor_1 USING sale_newyork_repl_factor_1_pkey;
|
CLUSTER sale_newyork_repl_factor_1 USING sale_newyork_repl_factor_1_pkey;
|
||||||
|
CREATE TABLE set_on_default_test_referenced(
|
||||||
|
col_1 int, col_2 int, col_3 int, col_4 int,
|
||||||
|
unique (col_1, col_3)
|
||||||
|
);
|
||||||
|
SELECT create_reference_table('set_on_default_test_referenced');
|
||||||
|
create_reference_table
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
CREATE TABLE set_on_default_test_referencing(
|
||||||
|
col_1 int, col_2 int, col_3 serial, col_4 int,
|
||||||
|
FOREIGN KEY(col_1, col_3)
|
||||||
|
REFERENCES set_on_default_test_referenced(col_1, col_3)
|
||||||
|
ON DELETE SET DEFAULT (col_1)
|
||||||
|
ON UPDATE SET DEFAULT
|
||||||
|
);
|
||||||
|
-- should error since col_3 defaults to a sequence
|
||||||
|
SELECT create_reference_table('set_on_default_test_referencing');
|
||||||
|
ERROR: cannot create foreign key constraint since Citus does not support ON DELETE / UPDATE SET DEFAULT actions on the columns that default to sequences
|
||||||
|
DROP TABLE set_on_default_test_referencing;
|
||||||
|
CREATE TABLE set_on_default_test_referencing(
|
||||||
|
col_1 int, col_2 int, col_3 serial, col_4 int,
|
||||||
|
FOREIGN KEY(col_1, col_3)
|
||||||
|
REFERENCES set_on_default_test_referenced(col_1, col_3)
|
||||||
|
ON DELETE SET DEFAULT (col_1)
|
||||||
|
);
|
||||||
|
-- should not error since this doesn't set any sequence based columns to default
|
||||||
|
SELECT create_reference_table('set_on_default_test_referencing');
|
||||||
|
create_reference_table
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
INSERT INTO set_on_default_test_referenced (col_1, col_3) VALUES (1, 1);
|
||||||
|
INSERT INTO set_on_default_test_referencing (col_1, col_3) VALUES (1, 1);
|
||||||
|
DELETE FROM set_on_default_test_referenced;
|
||||||
|
SELECT * FROM set_on_default_test_referencing ORDER BY 1,2;
|
||||||
|
col_1 | col_2 | col_3 | col_4
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
| | 1 |
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
DROP TABLE set_on_default_test_referencing;
|
||||||
|
SET client_min_messages to ERROR;
|
||||||
|
SELECT 1 FROM citus_add_node('localhost', :master_port, groupId => 0);
|
||||||
|
?column?
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
1
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
RESET client_min_messages;
|
||||||
|
-- should error since col_3 defaults to a sequence
|
||||||
|
CREATE TABLE set_on_default_test_referencing(
|
||||||
|
col_1 int, col_2 int, col_3 serial, col_4 int,
|
||||||
|
FOREIGN KEY(col_1, col_3)
|
||||||
|
REFERENCES set_on_default_test_referenced(col_1, col_3)
|
||||||
|
ON DELETE SET DEFAULT (col_3)
|
||||||
|
);
|
||||||
|
ERROR: cannot create foreign key constraint since Citus does not support ON DELETE / UPDATE SET DEFAULT actions on the columns that default to sequences
|
||||||
|
SELECT 1 FROM citus_remove_node('localhost', :master_port);
|
||||||
|
?column?
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
1
|
||||||
|
(1 row)
|
||||||
|
|
||||||
-- Clean up
|
-- Clean up
|
||||||
RESET citus.shard_replication_factor;
|
RESET citus.shard_replication_factor;
|
||||||
\set VERBOSITY terse
|
\set VERBOSITY terse
|
||||||
|
|
|
@ -250,6 +250,52 @@ BEGIN;
|
||||||
CREATE TABLE referencing_table(id int, ref_id int, FOREIGN KEY(ref_id) REFERENCES referenced_table(id) ON DELETE SET DEFAULT);
|
CREATE TABLE referencing_table(id int, ref_id int, FOREIGN KEY(ref_id) REFERENCES referenced_table(id) ON DELETE SET DEFAULT);
|
||||||
ERROR: cannot switch local execution status from local execution disabled to local execution enabled since it can cause visibility problems in the current transaction
|
ERROR: cannot switch local execution status from local execution disabled to local execution enabled since it can cause visibility problems in the current transaction
|
||||||
ROLLBACK;
|
ROLLBACK;
|
||||||
|
CREATE TABLE set_on_default_test_referenced(
|
||||||
|
col_1 int, col_2 int, col_3 int, col_4 int,
|
||||||
|
unique (col_1, col_3)
|
||||||
|
);
|
||||||
|
SELECT create_reference_table('set_on_default_test_referenced');
|
||||||
|
create_reference_table
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- from citus local to reference - 1
|
||||||
|
CREATE TABLE set_on_default_test_referencing(
|
||||||
|
col_1 int, col_2 int, col_3 serial, col_4 int,
|
||||||
|
FOREIGN KEY(col_1, col_3)
|
||||||
|
REFERENCES set_on_default_test_referenced(col_1, col_3)
|
||||||
|
ON UPDATE SET DEFAULT
|
||||||
|
);
|
||||||
|
ERROR: cannot create foreign key constraint since Citus does not support ON DELETE / UPDATE SET DEFAULT actions on the columns that default to sequences
|
||||||
|
CREATE TABLE set_on_default_test_referencing(
|
||||||
|
col_1 serial, col_2 int, col_3 int, col_4 int
|
||||||
|
);
|
||||||
|
-- from citus local to reference - 2
|
||||||
|
ALTER TABLE set_on_default_test_referencing ADD CONSTRAINT fkey
|
||||||
|
FOREIGN KEY(col_1, col_3) REFERENCES set_on_default_test_referenced(col_1, col_3)
|
||||||
|
ON DELETE SET DEFAULT;
|
||||||
|
ERROR: cannot create foreign key constraint since Citus does not support ON DELETE / UPDATE SET DEFAULT actions on the columns that default to sequences
|
||||||
|
DROP TABLE set_on_default_test_referencing, set_on_default_test_referenced;
|
||||||
|
NOTICE: executing the command locally: DROP TABLE IF EXISTS ref_citus_local_fkeys.set_on_default_test_referenced_xxxxx CASCADE
|
||||||
|
CREATE TABLE set_on_default_test_referenced(
|
||||||
|
col_1 int, col_2 int, col_3 int, col_4 int,
|
||||||
|
unique (col_1, col_3)
|
||||||
|
);
|
||||||
|
SELECT citus_add_local_table_to_metadata('set_on_default_test_referenced');
|
||||||
|
citus_add_local_table_to_metadata
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- from citus local to citus local
|
||||||
|
CREATE TABLE set_on_default_test_referencing(
|
||||||
|
col_1 int, col_2 int, col_3 serial, col_4 int,
|
||||||
|
FOREIGN KEY(col_1, col_3)
|
||||||
|
REFERENCES set_on_default_test_referenced(col_1, col_3)
|
||||||
|
ON DELETE SET DEFAULT
|
||||||
|
);
|
||||||
|
ERROR: cannot create foreign key constraint since Citus does not support ON DELETE / UPDATE SET DEFAULT actions on the columns that default to sequences
|
||||||
-- cleanup at exit
|
-- cleanup at exit
|
||||||
DROP SCHEMA ref_citus_local_fkeys CASCADE;
|
DROP SCHEMA ref_citus_local_fkeys CASCADE;
|
||||||
NOTICE: drop cascades to 6 other objects
|
NOTICE: drop cascades to 8 other objects
|
||||||
|
|
|
@ -696,5 +696,87 @@ DROP TABLE dropfkeytest1 CASCADE;
|
||||||
-- this should work
|
-- this should work
|
||||||
SELECT create_distributed_table ('dropfkeytest2', 'x', colocate_with:='none');
|
SELECT create_distributed_table ('dropfkeytest2', 'x', colocate_with:='none');
|
||||||
|
|
||||||
|
CREATE TABLE set_on_default_test_referenced(
|
||||||
|
col_1 int, col_2 int, col_3 int, col_4 int,
|
||||||
|
unique (col_1, col_3)
|
||||||
|
);
|
||||||
|
SELECT create_reference_table('set_on_default_test_referenced');
|
||||||
|
|
||||||
|
CREATE TABLE set_on_default_test_referencing(
|
||||||
|
col_1 int, col_2 int, col_3 serial, col_4 int,
|
||||||
|
FOREIGN KEY(col_1, col_3)
|
||||||
|
REFERENCES set_on_default_test_referenced(col_1, col_3)
|
||||||
|
ON UPDATE SET DEFAULT
|
||||||
|
);
|
||||||
|
|
||||||
|
-- from distributed / reference to reference, fkey exists before calling the UDFs
|
||||||
|
SELECT create_distributed_table('set_on_default_test_referencing', 'col_1');
|
||||||
|
SELECT create_reference_table('set_on_default_test_referencing');
|
||||||
|
|
||||||
|
DROP TABLE set_on_default_test_referencing;
|
||||||
|
CREATE TABLE set_on_default_test_referencing(
|
||||||
|
col_1 serial, col_2 int, col_3 int, col_4 int
|
||||||
|
);
|
||||||
|
SELECT create_reference_table('set_on_default_test_referencing');
|
||||||
|
|
||||||
|
-- from reference to reference, fkey doesn't exist before calling the UDFs
|
||||||
|
ALTER TABLE set_on_default_test_referencing ADD CONSTRAINT fkey
|
||||||
|
FOREIGN KEY(col_1, col_3) REFERENCES set_on_default_test_referenced(col_1, col_3)
|
||||||
|
ON DELETE SET DEFAULT;
|
||||||
|
|
||||||
|
DROP TABLE set_on_default_test_referencing;
|
||||||
|
CREATE TABLE set_on_default_test_referencing(
|
||||||
|
col_1 int, col_2 serial, col_3 int, col_4 bigserial
|
||||||
|
);
|
||||||
|
SELECT create_reference_table('set_on_default_test_referencing');
|
||||||
|
|
||||||
|
-- ok since referencing columns are not based on sequences
|
||||||
|
ALTER TABLE set_on_default_test_referencing ADD CONSTRAINT fkey
|
||||||
|
FOREIGN KEY(col_1, col_3) REFERENCES set_on_default_test_referenced(col_1, col_3)
|
||||||
|
ON DELETE SET DEFAULT;
|
||||||
|
|
||||||
|
DROP TABLE set_on_default_test_referencing;
|
||||||
|
|
||||||
|
CREATE SEQUENCE test_sequence;
|
||||||
|
CREATE TABLE set_on_default_test_referencing(
|
||||||
|
col_1 int, col_2 int, col_3 int DEFAULT nextval('test_sequence'), col_4 int
|
||||||
|
);
|
||||||
|
SELECT create_distributed_table('set_on_default_test_referencing', 'col_1');
|
||||||
|
|
||||||
|
-- from distributed to reference, fkey doesn't exist before calling the UDFs
|
||||||
|
ALTER TABLE set_on_default_test_referencing ADD CONSTRAINT fkey
|
||||||
|
FOREIGN KEY(col_1, col_3) REFERENCES set_on_default_test_referenced(col_1, col_3)
|
||||||
|
ON DELETE SET DEFAULT ON UPDATE SET DEFAULT;
|
||||||
|
|
||||||
|
DROP TABLE set_on_default_test_referenced;
|
||||||
|
CREATE TABLE set_on_default_test_referenced(
|
||||||
|
col_1 int, col_2 int, col_3 int, col_4 int,
|
||||||
|
unique (col_1, col_3)
|
||||||
|
);
|
||||||
|
SELECT create_distributed_table('set_on_default_test_referenced', 'col_1');
|
||||||
|
|
||||||
|
DROP TABLE set_on_default_test_referencing;
|
||||||
|
CREATE TABLE set_on_default_test_referencing(
|
||||||
|
col_1 bigserial, col_2 int, col_3 int DEFAULT nextval('test_sequence'), col_4 int,
|
||||||
|
FOREIGN KEY(col_1, col_3)
|
||||||
|
REFERENCES set_on_default_test_referenced(col_1, col_3)
|
||||||
|
ON DELETE SET DEFAULT
|
||||||
|
);
|
||||||
|
|
||||||
|
-- from distributed to distributed, fkey exists before calling the UDFs
|
||||||
|
SELECT create_distributed_table('set_on_default_test_referencing', 'col_1');
|
||||||
|
|
||||||
|
DROP TABLE set_on_default_test_referencing;
|
||||||
|
CREATE TABLE set_on_default_test_referencing(
|
||||||
|
col_1 int DEFAULT nextval('test_sequence'), col_2 int, col_3 int, col_4 int
|
||||||
|
);
|
||||||
|
SELECT create_distributed_table('set_on_default_test_referencing', 'col_1');
|
||||||
|
|
||||||
|
-- from distributed to distributed, fkey doesn't exist before calling the UDFs
|
||||||
|
ALTER TABLE set_on_default_test_referencing ADD CONSTRAINT fkey
|
||||||
|
FOREIGN KEY(col_1, col_3) REFERENCES set_on_default_test_referenced(col_1, col_3)
|
||||||
|
ON DELETE SET DEFAULT;
|
||||||
|
|
||||||
-- we no longer need those tables
|
-- we no longer need those tables
|
||||||
DROP TABLE referenced_by_reference_table, references_to_reference_table, reference_table, reference_table_second, referenced_local_table, self_referencing_reference_table, dropfkeytest2;
|
DROP TABLE referenced_by_reference_table, references_to_reference_table, reference_table, reference_table_second, referenced_local_table, self_referencing_reference_table, dropfkeytest2,
|
||||||
|
set_on_default_test_referenced, set_on_default_test_referencing;
|
||||||
|
|
|
@ -581,6 +581,56 @@ CLUSTER sale_repl_factor_1 USING sale_repl_factor_1_pk;
|
||||||
-- verify that we can still cluster the partition tables now since replication factor is 1
|
-- verify that we can still cluster the partition tables now since replication factor is 1
|
||||||
CLUSTER sale_newyork_repl_factor_1 USING sale_newyork_repl_factor_1_pkey;
|
CLUSTER sale_newyork_repl_factor_1 USING sale_newyork_repl_factor_1_pkey;
|
||||||
|
|
||||||
|
CREATE TABLE set_on_default_test_referenced(
|
||||||
|
col_1 int, col_2 int, col_3 int, col_4 int,
|
||||||
|
unique (col_1, col_3)
|
||||||
|
);
|
||||||
|
SELECT create_reference_table('set_on_default_test_referenced');
|
||||||
|
|
||||||
|
CREATE TABLE set_on_default_test_referencing(
|
||||||
|
col_1 int, col_2 int, col_3 serial, col_4 int,
|
||||||
|
FOREIGN KEY(col_1, col_3)
|
||||||
|
REFERENCES set_on_default_test_referenced(col_1, col_3)
|
||||||
|
ON DELETE SET DEFAULT (col_1)
|
||||||
|
ON UPDATE SET DEFAULT
|
||||||
|
);
|
||||||
|
|
||||||
|
-- should error since col_3 defaults to a sequence
|
||||||
|
SELECT create_reference_table('set_on_default_test_referencing');
|
||||||
|
|
||||||
|
DROP TABLE set_on_default_test_referencing;
|
||||||
|
CREATE TABLE set_on_default_test_referencing(
|
||||||
|
col_1 int, col_2 int, col_3 serial, col_4 int,
|
||||||
|
FOREIGN KEY(col_1, col_3)
|
||||||
|
REFERENCES set_on_default_test_referenced(col_1, col_3)
|
||||||
|
ON DELETE SET DEFAULT (col_1)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- should not error since this doesn't set any sequence based columns to default
|
||||||
|
SELECT create_reference_table('set_on_default_test_referencing');
|
||||||
|
|
||||||
|
INSERT INTO set_on_default_test_referenced (col_1, col_3) VALUES (1, 1);
|
||||||
|
INSERT INTO set_on_default_test_referencing (col_1, col_3) VALUES (1, 1);
|
||||||
|
DELETE FROM set_on_default_test_referenced;
|
||||||
|
|
||||||
|
SELECT * FROM set_on_default_test_referencing ORDER BY 1,2;
|
||||||
|
|
||||||
|
DROP TABLE set_on_default_test_referencing;
|
||||||
|
|
||||||
|
SET client_min_messages to ERROR;
|
||||||
|
SELECT 1 FROM citus_add_node('localhost', :master_port, groupId => 0);
|
||||||
|
RESET client_min_messages;
|
||||||
|
|
||||||
|
-- should error since col_3 defaults to a sequence
|
||||||
|
CREATE TABLE set_on_default_test_referencing(
|
||||||
|
col_1 int, col_2 int, col_3 serial, col_4 int,
|
||||||
|
FOREIGN KEY(col_1, col_3)
|
||||||
|
REFERENCES set_on_default_test_referenced(col_1, col_3)
|
||||||
|
ON DELETE SET DEFAULT (col_3)
|
||||||
|
);
|
||||||
|
|
||||||
|
SELECT 1 FROM citus_remove_node('localhost', :master_port);
|
||||||
|
|
||||||
-- Clean up
|
-- Clean up
|
||||||
RESET citus.shard_replication_factor;
|
RESET citus.shard_replication_factor;
|
||||||
\set VERBOSITY terse
|
\set VERBOSITY terse
|
||||||
|
|
|
@ -159,5 +159,44 @@ BEGIN;
|
||||||
CREATE TABLE referencing_table(id int, ref_id int, FOREIGN KEY(ref_id) REFERENCES referenced_table(id) ON DELETE SET DEFAULT);
|
CREATE TABLE referencing_table(id int, ref_id int, FOREIGN KEY(ref_id) REFERENCES referenced_table(id) ON DELETE SET DEFAULT);
|
||||||
ROLLBACK;
|
ROLLBACK;
|
||||||
|
|
||||||
|
CREATE TABLE set_on_default_test_referenced(
|
||||||
|
col_1 int, col_2 int, col_3 int, col_4 int,
|
||||||
|
unique (col_1, col_3)
|
||||||
|
);
|
||||||
|
SELECT create_reference_table('set_on_default_test_referenced');
|
||||||
|
|
||||||
|
-- from citus local to reference - 1
|
||||||
|
CREATE TABLE set_on_default_test_referencing(
|
||||||
|
col_1 int, col_2 int, col_3 serial, col_4 int,
|
||||||
|
FOREIGN KEY(col_1, col_3)
|
||||||
|
REFERENCES set_on_default_test_referenced(col_1, col_3)
|
||||||
|
ON UPDATE SET DEFAULT
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE set_on_default_test_referencing(
|
||||||
|
col_1 serial, col_2 int, col_3 int, col_4 int
|
||||||
|
);
|
||||||
|
|
||||||
|
-- from citus local to reference - 2
|
||||||
|
ALTER TABLE set_on_default_test_referencing ADD CONSTRAINT fkey
|
||||||
|
FOREIGN KEY(col_1, col_3) REFERENCES set_on_default_test_referenced(col_1, col_3)
|
||||||
|
ON DELETE SET DEFAULT;
|
||||||
|
|
||||||
|
DROP TABLE set_on_default_test_referencing, set_on_default_test_referenced;
|
||||||
|
|
||||||
|
CREATE TABLE set_on_default_test_referenced(
|
||||||
|
col_1 int, col_2 int, col_3 int, col_4 int,
|
||||||
|
unique (col_1, col_3)
|
||||||
|
);
|
||||||
|
SELECT citus_add_local_table_to_metadata('set_on_default_test_referenced');
|
||||||
|
|
||||||
|
-- from citus local to citus local
|
||||||
|
CREATE TABLE set_on_default_test_referencing(
|
||||||
|
col_1 int, col_2 int, col_3 serial, col_4 int,
|
||||||
|
FOREIGN KEY(col_1, col_3)
|
||||||
|
REFERENCES set_on_default_test_referenced(col_1, col_3)
|
||||||
|
ON DELETE SET DEFAULT
|
||||||
|
);
|
||||||
|
|
||||||
-- cleanup at exit
|
-- cleanup at exit
|
||||||
DROP SCHEMA ref_citus_local_fkeys CASCADE;
|
DROP SCHEMA ref_citus_local_fkeys CASCADE;
|
||||||
|
|
Loading…
Reference in New Issue