-- syntax errors -- test for extraneous comma CREATETABLE error_tbl (i intDEFAULT (100, )); -- this will fail because gram.y uses b_expr not a_expr for defaults, -- to avoid a shift/reduce conflict that arises from NOT NULL being -- part of the column definition syntax: CREATETABLE error_tbl (b1 bool DEFAULT1IN (1, 2)); -- this should work, however: CREATETABLE error_tbl (b1 bool DEFAULT (1IN (1, 2)));
CREATETABLE INSERT_TBL (x INTDEFAULT nextval('insert_seq'),
y TEXT DEFAULT'-NULL-',
z INTDEFAULT -1 * currval('insert_seq'), CONSTRAINT INSERT_TBL_CON CHECK (x >= 3AND y <> 'check failed'AND x < 8), CHECK (x + z = 0) ENFORCED, /* no change it is a default */ CONSTRAINT NE_INSERT_TBL_CON CHECK (x + z = 1) NOT ENFORCED);
-- According to SQL, it is OK to insert a record that gives rise to NULL -- constraint-condition results. Postgres used to reject this, but it -- was wrong: INSERTINTO INSERT_TBL VALUES (null, null, null);
SELECT * FROM INSERT_TBL;
-- -- Check constraints on system columns --
CREATETABLE SYS_COL_CHECK_TBL (city text, state text, is_capital bool,
altitude int, CHECK (NOT (is_capital AND tableoid::regclass::text = 'sys_col_check_tbl')));
SELECT *, tableoid::regclass::text FROM SYS_COL_CHECK_TBL;
DROPTABLE SYS_COL_CHECK_TBL;
-- -- Check constraints on system columns other then TableOid should return error -- CREATETABLE SYS_COL_CHECK_TBL (city text, state text, is_capital bool,
altitude int, CHECK (NOT (is_capital AND ctid::text = 'sys_col_check_tbl')));
-- -- Check inheritance of defaults and constraints --
-- -- Check NO INHERIT type of constraints and inheritance --
CREATETABLE ATACC1 (TEST INT CHECK (TEST > 0) NO INHERIT);
CREATETABLE ATACC2 (TEST2 INT) INHERITS (ATACC1); -- check constraint is not there on child INSERTINTO ATACC2 (TEST) VALUES (-3); -- check constraint is there on parent INSERTINTO ATACC1 (TEST) VALUES (-3); DROPTABLE ATACC1 CASCADE;
CREATETABLE ATACC1 (TEST INT, TEST2 INT CHECK (TEST > 0), CHECK (TEST2 > 10) NO INHERIT);
CREATETABLE ATACC2 () INHERITS (ATACC1); -- check constraint is there on child INSERTINTO ATACC2 (TEST) VALUES (-3); -- check constraint is there on parent INSERTINTO ATACC1 (TEST) VALUES (-3); -- check constraint is not there on child INSERTINTO ATACC2 (TEST2) VALUES (3); -- check constraint is there on parent INSERTINTO ATACC1 (TEST2) VALUES (3); DROPTABLE ATACC1 CASCADE;
INSERTINTO INSERT_TBL SELECT * FROM tmp WHERE yd = 'try again'; INSERTINTO INSERT_TBL(y,z) SELECT yd, -7FROM tmp WHERE yd = 'try again'; INSERTINTO INSERT_TBL(y,z) SELECT yd, -8FROM tmp WHERE yd = 'try again';
SELECT * FROM INSERT_TBL;
DROPTABLE tmp;
-- -- Check constraints on UPDATE --
UPDATE INSERT_TBL SET x = NULLWHERE x = 5; UPDATE INSERT_TBL SET x = 6WHERE x = 6; UPDATE INSERT_TBL SET x = -z, z = -x; UPDATE INSERT_TBL SET x = z, z = x;
SELECT * FROM INSERT_TBL;
-- DROP TABLE INSERT_TBL;
-- -- Check constraints on COPY FROM --
CREATETABLE COPY_TBL (x INT, y TEXT, z INT, CONSTRAINT COPY_CON CHECK (x > 3AND y <> 'check failed'AND x < 7 ));
\set filename :abs_srcdir '/data/constro.data'
COPY COPY_TBL FROM :'filename';
SELECT * FROM COPY_TBL;
\set filename :abs_srcdir '/data/constrf.data'
COPY COPY_TBL FROM :'filename';
SELECT * FROM COPY_TBL;
-- -- Primary keys --
CREATETABLE PRIMARY_TBL (i intPRIMARYKEY, t text);
INSERTINTO UNIQUE_TBL VALUES (5, 'five-upsert-insert') ON CONFLICT (i) DO UPDATESET t = 'five-upsert-update'; INSERTINTO UNIQUE_TBL VALUES (6, 'six-upsert-insert') ON CONFLICT (i) DO UPDATESET t = 'six-upsert-update'; -- should fail INSERTINTO UNIQUE_TBL VALUES (1, 'a'), (2, 'b'), (2, 'b') ON CONFLICT (i) DO UPDATESET t = 'fails';
SELECT * FROM UNIQUE_TBL;
DROPTABLE UNIQUE_TBL;
CREATETABLE UNIQUE_TBL (i intUNIQUE NULLS NOTDISTINCT, t text);
INSERTINTO unique_tbl VALUES (1, 'five'); INSERTINTO unique_tbl VALUES (5, 'one'); UPDATE unique_tbl SET i = 4WHERE i = 2; UPDATE unique_tbl SET i = 2WHERE i = 4AND t = 'four'; DELETEFROM unique_tbl WHERE i = 1AND t = 'one'; DELETEFROM unique_tbl WHERE i = 5AND t = 'five';
COMMIT;
SELECT * FROM unique_tbl;
-- should fail at commit-time
BEGIN; INSERTINTO unique_tbl VALUES (3, 'Three'); -- should succeed for now COMMIT; -- should fail
-- make constraint check immediate
BEGIN;
SET CONSTRAINTS ALL IMMEDIATE;
INSERTINTO unique_tbl VALUES (3, 'Three'); -- should fail
COMMIT;
-- forced check when SET CONSTRAINTS is called
BEGIN;
SET CONSTRAINTS ALL DEFERRED;
INSERTINTO unique_tbl VALUES (3, 'Three'); -- should succeed for now
SET CONSTRAINTS ALL IMMEDIATE; -- should fail
COMMIT;
-- test deferrable UNIQUE with a partitioned table CREATETABLE parted_uniq_tbl (i intUNIQUE DEFERRABLE) partition by range (i); CREATETABLE parted_uniq_tbl_1 PARTITION OF parted_uniq_tbl FORVALUESFROM (0) TO (10); CREATETABLE parted_uniq_tbl_2 PARTITION OF parted_uniq_tbl FORVALUESFROM (20) TO (30); SELECT conname, conrelid::regclass FROM pg_constraint WHERE conname LIKE'parted_uniq%'ORDERBY conname;
BEGIN; INSERTINTO parted_uniq_tbl VALUES (1);
SAVEPOINT f; INSERTINTO parted_uniq_tbl VALUES (1); -- unique violation
ROLLBACK TO f; SET CONSTRAINTS parted_uniq_tbl_i_key DEFERRED; INSERTINTO parted_uniq_tbl VALUES (1); -- OK now, fail at commit COMMIT; DROPTABLE parted_uniq_tbl;
-- test naming a constraint in a partition when a conflict exists CREATETABLE parted_fk_naming (
id bigintNOTNULLdefault1,
id_abc bigint, CONSTRAINT dummy_constr FOREIGNKEY (id_abc) REFERENCES parted_fk_naming (id), PRIMARYKEY (id)
)
PARTITION BY LIST (id); CREATETABLE parted_fk_naming_1 (
id bigintNOTNULLdefault1,
id_abc bigint, PRIMARYKEY (id), CONSTRAINT dummy_constr CHECK (true)
); ALTERTABLE parted_fk_naming ATTACH PARTITION parted_fk_naming_1 FORVALUESIN ('1'); SELECT conname FROM pg_constraint WHERE conrelid = 'parted_fk_naming_1'::regclass AND contype = 'f'; DROPTABLE parted_fk_naming;
-- -- Test various ways to create primary keys on partitions, linked to unique -- indexes (without constraints) on the partitioned table. Ideally these should -- fail, but we don't dare change released behavior, so instead cope with it at -- DETACH time. CREATE TEMP TABLE t (a integer, b integer) PARTITION BY HASH (a, b); CREATE TEMP TABLE tp (a integer, b integer, PRIMARYKEY (a, b), UNIQUE (b, a)); ALTERTABLE t ATTACH PARTITION tp FORVALUESWITH (MODULUS 1, REMAINDER 0); CREATEUNIQUEINDEX t_a_idx ON t (a, b); CREATEUNIQUEINDEX t_b_idx ON t (b, a); ALTERINDEX t_a_idx ATTACH PARTITION tp_pkey; ALTERINDEX t_b_idx ATTACH PARTITION tp_b_a_key; SELECT conname, conparentid, conislocal, coninhcount FROM pg_constraint WHERE conname IN ('tp_pkey', 'tp_b_a_key') ORDERBY conname DESC; ALTERTABLE t DETACH PARTITION tp; DROPTABLE t, tp;
CREATE TEMP TABLE t (a integer) PARTITION BY LIST (a); CREATE TEMP TABLE tp (a integerPRIMARYKEY); CREATEUNIQUEINDEX t_a_idx ON t (a); ALTERTABLE t ATTACH PARTITION tp FORVALUESIN (1); ALTERTABLE t DETACH PARTITION tp; DROPTABLE t, tp;
CREATE TEMP TABLE t (a integer) PARTITION BY LIST (a); CREATE TEMP TABLE tp (a integerPRIMARYKEY); CREATEUNIQUEINDEX t_a_idx ON ONLY t (a); ALTERTABLE t ATTACH PARTITION tp FORVALUESIN (1); ALTERTABLE t DETACH PARTITION tp; DROPTABLE t, tp;
CREATETABLE regress_constr_partitioned (a integer) PARTITION BY LIST (a); CREATETABLE regress_constr_partition1 PARTITION OF regress_constr_partitioned FORVALUESIN (1); ALTERTABLE regress_constr_partition1 ADDPRIMARYKEY (a); CREATEUNIQUEINDEXON regress_constr_partitioned (a);
BEGIN; ALTERTABLE regress_constr_partitioned DETACH PARTITION regress_constr_partition1;
ROLLBACK; -- Leave this one in funny state for pg_upgrade testing
-- test a HOT update that invalidates the conflicting tuple. -- the trigger should still fire and catch the violation
BEGIN;
INSERTINTO unique_tbl VALUES (3, 'Three'); -- should succeed for now UPDATE unique_tbl SET t = 'THREE'WHERE i = 3AND t = 'Three';
COMMIT; -- should fail
SELECT * FROM unique_tbl;
-- test a HOT update that modifies the newly inserted tuple, -- but should succeed because we then remove the other conflicting tuple.
BEGIN;
INSERTINTO unique_tbl VALUES(3, 'tree'); -- should succeed for now UPDATE unique_tbl SET t = 'threex'WHERE t = 'tree'; DELETEFROM unique_tbl WHERE t = 'three';
SELECT * FROM unique_tbl;
COMMIT;
SELECT * FROM unique_tbl;
-- enforceability cannot be specified or set for unique constraint CREATETABLE UNIQUE_EN_TBL(i intUNIQUE ENFORCED); CREATETABLE UNIQUE_NOTEN_TBL(i intUNIQUENOT ENFORCED); ALTERTABLE unique_tbl ALTERCONSTRAINT unique_tbl_i_key ENFORCED; ALTERTABLE unique_tbl ALTERCONSTRAINT unique_tbl_i_key NOT ENFORCED;
-- can't make an existing constraint NOT VALID ALTERTABLE unique_tbl ALTERCONSTRAINT unique_tbl_i_key NOT VALID;
DROPTABLE unique_tbl;
-- -- EXCLUDE constraints --
CREATETABLE circles (
c1 CIRCLE,
c2 TEXT,
EXCLUDE USING gist
(c1 WITH &&, (c2::circle) WITH &&) WHERE (circle_center(c1) <> '(0,0)')
);
-- these should succeed because they don't match the index predicate INSERTINTO circles VALUES('<(0,0), 5>', '<(0,0), 5>'); INSERTINTO circles VALUES('<(0,0), 5>', '<(0,0), 4>');
-- succeed INSERTINTO circles VALUES('<(10,10), 10>', '<(0,0), 5>'); -- fail, overlaps INSERTINTO circles VALUES('<(20,20), 10>', '<(0,0), 4>'); -- succeed, because violation is ignored INSERTINTO circles VALUES('<(20,20), 10>', '<(0,0), 4>') ON CONFLICT ONCONSTRAINT circles_c1_c2_excl DO NOTHING; -- fail, because DO UPDATE variant requires unique index INSERTINTO circles VALUES('<(20,20), 10>', '<(0,0), 4>') ON CONFLICT ONCONSTRAINT circles_c1_c2_excl DO UPDATESET c2 = EXCLUDED.c2; -- succeed because c1 doesn't overlap INSERTINTO circles VALUES('<(20,20), 1>', '<(0,0), 5>'); -- succeed because c2 doesn't overlap INSERTINTO circles VALUES('<(20,20), 10>', '<(10,10), 5>');
-- should fail on existing data without the WHERE clause ALTERTABLE circles ADD EXCLUDE USING gist
(c1 WITH &&, (c2::circle) WITH &&);
-- try reindexing an existing constraint
REINDEX INDEX circles_c1_c2_excl;
DROPTABLE circles;
-- Check deferred exclusion constraint
CREATETABLE deferred_excl (
f1 int,
f2 int, CONSTRAINT deferred_excl_con EXCLUDE (f1 WITH =) INITIALLY DEFERRED
);
INSERTINTO deferred_excl VALUES(1); INSERTINTO deferred_excl VALUES(2); INSERTINTO deferred_excl VALUES(1); -- fail INSERTINTO deferred_excl VALUES(1) ON CONFLICT ONCONSTRAINT deferred_excl_con DO NOTHING; -- fail
BEGIN; INSERTINTO deferred_excl VALUES(2); -- no fail here COMMIT; -- should fail here
BEGIN; INSERTINTO deferred_excl VALUES(3); INSERTINTO deferred_excl VALUES(3); -- no fail here COMMIT; -- should fail here
-- bug #13148: deferred constraint versus HOT update
BEGIN; INSERTINTO deferred_excl VALUES(2, 1); -- no fail here DELETEFROM deferred_excl WHERE f1 = 2AND f2 ISNULL; -- remove old row UPDATE deferred_excl SET f2 = 2WHERE f1 = 2; COMMIT; -- should not fail
-- This should fail, but worth testing because of HOT updates UPDATE deferred_excl SET f1 = 3;
ALTERTABLE deferred_excl ADD EXCLUDE (f1 WITH =);
DROPTABLE deferred_excl;
-- verify constraints created for NOT NULL clauses CREATETABLE notnull_tbl1 (a INTEGERNOTNULLNOTNULL);
\d+ notnull_tbl1 -- specifying an existing constraint is a no-op ALTERTABLE notnull_tbl1 ADDCONSTRAINT notnull_tbl1_a_not_null NOTNULL a; -- but using a different constraint name is not allowed ALTERTABLE notnull_tbl1 ADDCONSTRAINT nn NOTNULL a;
\d+ notnull_tbl1 -- duplicate name ALTERTABLE notnull_tbl1 ADDCOLUMN b INTCONSTRAINT notnull_tbl1_a_not_null NOTNULL; -- DROP NOT NULL gets rid of both the attnotnull flag and the constraint itself ALTERTABLE notnull_tbl1 ALTER a DROPNOTNULL;
\d+ notnull_tbl1 -- SET NOT NULL puts both back ALTERTABLE notnull_tbl1 ALTER a SETNOTNULL;
\d+ notnull_tbl1 -- Doing it twice doesn't create a redundant constraint ALTERTABLE notnull_tbl1 ALTER a SETNOTNULL; select conname, contype, conkey from pg_constraint where conrelid = 'notnull_tbl1'::regclass; -- Using the "table constraint" syntax also works ALTERTABLE notnull_tbl1 ALTER a DROPNOTNULL; ALTERTABLE notnull_tbl1 ADDCONSTRAINT foobar NOTNULL a;
\d+ notnull_tbl1 DROPTABLE notnull_tbl1;
-- Verify that constraint names and NO INHERIT are properly considered when -- multiple constraint are specified, either explicitly or via SERIAL/PK/etc, -- and that conflicting cases are rejected. Mind that table constraints -- handle this separately from column constraints. createtable notnull_tbl1 (a intprimarykeyconstraint foo notnull);
\d+ notnull_tbl1 createtable notnull_tbl2 (a serial, constraint foo notnull a);
\d+ notnull_tbl2 createtable notnull_tbl3 (constraint foo notnull a, a int generated bydefaultas identity);
\d+ notnull_tbl3 createtable notnull_tbl4 (a intnotnullconstraint foo notnull);
\d+ notnull_tbl4 createtable notnull_tbl5 (a intconstraint foo notnullconstraint foo notnull);
\d+ notnull_tbl5 createtable notnull_tbl6 (like notnull_tbl1, constraint foo notnull a);
\d+ notnull_tbl6 droptable notnull_tbl2, notnull_tbl3, notnull_tbl4, notnull_tbl5, notnull_tbl6;
-- error cases: createtable notnull_tbl_fail (a serial constraint foo notnullconstraint bar notnull); createtable notnull_tbl_fail (a serial constraint foo notnull no inherit constraint foo notnull); createtable notnull_tbl_fail (a intconstraint foo notnull, constraint foo notnull a no inherit); createtable notnull_tbl_fail (a serial constraint foo notnull, constraint bar notnull a); createtable notnull_tbl_fail (a serial, constraint foo notnull a, constraint bar notnull a); createtable notnull_tbl_fail (a serial, constraint foo notnull a no inherit); createtable notnull_tbl_fail (a serial notnull no inherit); createtable notnull_tbl_fail (like notnull_tbl1, constraint foo2 notnull a); createtable notnull_tbl_fail (a intprimarykeyconstraint foo notnull no inherit); createtable notnull_tbl_fail (a intnotnull no inherit primarykey); createtable notnull_tbl_fail (a intprimarykey, notnull a no inherit); createtable notnull_tbl_fail (a int, primarykey(a), notnull a no inherit); createtable notnull_tbl_fail (a int generated bydefaultas identity, constraint foo notnull a no inherit); createtable notnull_tbl_fail (a int generated bydefaultas identity notnull no inherit);
droptable notnull_tbl1;
-- NOT NULL NO INHERIT CREATETABLE ATACC1 (a int, NOTNULL a NO INHERIT); CREATETABLE ATACC2 () INHERITS (ATACC1);
\d+ ATACC2 DROPTABLE ATACC1, ATACC2; CREATETABLE ATACC1 (a int); ALTERTABLE ATACC1 ADDNOTNULL a NO INHERIT; CREATETABLE ATACC2 () INHERITS (ATACC1);
\d+ ATACC2 DROPTABLE ATACC1, ATACC2; CREATETABLE ATACC1 (a int); CREATETABLE ATACC2 () INHERITS (ATACC1); ALTERTABLE ATACC1 ADDNOTNULL a NO INHERIT;
\d+ ATACC2 CREATETABLE ATACC3 (PRIMARYKEY (a)) INHERITS (ATACC1);
\d+ ATACC3 DROPTABLE ATACC1, ATACC2, ATACC3;
-- NOT NULL NO INHERIT is not possible on partitioned tables CREATETABLE ATACC1 (a intNOTNULL NO INHERIT) PARTITION BY LIST (a); CREATETABLE ATACC1 (a int, NOTNULL a NO INHERIT) PARTITION BY LIST (a);
-- it's not possible to override a no-inherit constraint with an inheritable one CREATETABLE ATACC2 (a int, CONSTRAINT a_is_not_null NOTNULL a NO INHERIT); CREATETABLE ATACC1 (a int); CREATETABLE ATACC3 (a int) INHERITS (ATACC2); ALTERTABLE ATACC2 INHERIT ATACC1; -- can't override ALTERTABLE ATACC1 ADDCONSTRAINT ditto NOTNULL a; -- dropping the NO INHERIT constraint allows this to work ALTERTABLE ATACC2 DROPCONSTRAINT a_is_not_null; ALTERTABLE ATACC1 ADDCONSTRAINT ditto NOTNULL a;
\d+ ATACC3 DROPTABLE ATACC1, ATACC2, ATACC3;
-- Can't have two constraints with the same name CREATETABLE notnull_tbl2 (a INTEGERCONSTRAINT blah NOTNULL, b INTEGERCONSTRAINT blah NOTNULL);
-- can't drop not-null in primary key CREATETABLE notnull_tbl2 (a INTEGERPRIMARYKEY); ALTERTABLE notnull_tbl2 ALTER a DROPNOTNULL; DROPTABLE notnull_tbl2;
CREATETABLE notnull_tbl3 (a INTEGERNOTNULL, CHECK (a ISNOTNULL)); ALTERTABLE notnull_tbl3 ALTER A DROPNOTNULL; ALTERTABLE notnull_tbl3 ADD b int, ADDCONSTRAINT pk PRIMARYKEY (a, b);
\d notnull_tbl3 ALTERTABLE notnull_tbl3 DROPCONSTRAINT pk;
\d notnull_tbl3
-- Primary keys cause not-null constraints to be created. CREATETABLE cnn_pk (a int, b int); CREATETABLE cnn_pk_child () INHERITS (cnn_pk); ALTERTABLE cnn_pk ADDCONSTRAINT cnn_primarykey PRIMARYKEY (b);
\d+ cnn_pk* ALTERTABLE cnn_pk DROPCONSTRAINT cnn_primarykey;
\d+ cnn_pk* DROPTABLE cnn_pk, cnn_pk_child;
-- As above, but create the primary key ahead of time CREATETABLE cnn_pk (a int, b int, CONSTRAINT cnn_primarykey PRIMARYKEY (b)); CREATETABLE cnn_pk_child () INHERITS (cnn_pk);
\d+ cnn_pk* ALTERTABLE cnn_pk DROPCONSTRAINT cnn_primarykey;
\d+ cnn_pk* DROPTABLE cnn_pk, cnn_pk_child;
-- As above, but create the primary key using a UNIQUE index CREATETABLE cnn_pk (a int, b int); CREATEUNIQUEINDEX cnn_uq ON cnn_pk (b); CREATETABLE cnn_pk_child () INHERITS (cnn_pk); ALTERTABLE cnn_pk ADDCONSTRAINT cnn_primarykey PRIMARYKEYUSINGINDEX cnn_uq;
\d+ cnn_pk* DROPTABLE cnn_pk, cnn_pk_child;
-- Unique constraints don't give raise to not-null constraints, however. createtable cnn_uq (a int); altertable cnn_uq addunique (a);
\d+ cnn_uq droptable cnn_uq; createtable cnn_uq (a int); createuniqueindex cnn_uq_idx on cnn_uq (a); altertable cnn_uq adduniqueusingindex cnn_uq_idx;
\d+ cnn_uq
-- can't create a primary key on a noinherit not-null createtable cnn_pk (a intnotnull no inherit); altertable cnn_pk addprimarykey (a); droptable cnn_pk;
-- Ensure partitions are scanned for null values when adding a PK createtable cnn2_parted(a int) partition by list (a); createtable cnn_part1 partition of cnn2_parted forvaluesin (1, null); insertinto cnn_part1 values (null); altertable cnn2_parted addprimarykey (a); droptable cnn2_parted;
-- columns in regular and LIKE inheritance should be marked not-nullable -- for primary keys, even if those are deferred CREATETABLE notnull_tbl4 (a INTEGERPRIMARYKEY INITIALLY DEFERRED); CREATETABLE notnull_tbl4_lk (LIKE notnull_tbl4); CREATETABLE notnull_tbl4_lk2 (LIKE notnull_tbl4 INCLUDING INDEXES); CREATETABLE notnull_tbl4_lk3 (LIKE notnull_tbl4 INCLUDING INDEXES, NOTNULL a); ALTERTABLE notnull_tbl4_lk3 RENAMECONSTRAINT notnull_tbl4_a_not_null TO a_nn; CREATETABLE notnull_tbl4_cld () INHERITS (notnull_tbl4); CREATETABLE notnull_tbl4_cld2 (PRIMARYKEY (a) DEFERRABLE) INHERITS (notnull_tbl4); CREATETABLE notnull_tbl4_cld3 (PRIMARYKEY (a) DEFERRABLE, CONSTRAINT a_nn NOTNULL a) INHERITS (notnull_tbl4);
\d+ notnull_tbl4
\d+ notnull_tbl4_lk
\d+ notnull_tbl4_lk2
\d+ notnull_tbl4_lk3
\d+ notnull_tbl4_cld
\d+ notnull_tbl4_cld2
\d+ notnull_tbl4_cld3 -- leave these tables around for pg_upgrade testing
-- It's possible to remove a constraint from parents without affecting children CREATETABLE notnull_tbl5 (a intCONSTRAINT ann NOTNULL,
b intCONSTRAINT bnn NOTNULL); CREATETABLE notnull_tbl5_child () INHERITS (notnull_tbl5); ALTERTABLE ONLY notnull_tbl5 DROPCONSTRAINT ann; ALTERTABLE ONLY notnull_tbl5 ALTER b DROPNOTNULL;
\d+ notnull_tbl5_child CREATETABLE notnull_tbl6 (a intCONSTRAINT ann NOTNULL,
b intCONSTRAINT bnn NOTNULL, check (a > 0)) PARTITION BY LIST (a); CREATETABLE notnull_tbl6_1 PARTITION OF notnull_tbl6 FORVALUESIN (1); ALTERTABLE ONLY notnull_tbl6 DROPCONSTRAINT ann; ALTERTABLE ONLY notnull_tbl6 ALTER b DROPNOTNULL;
\d+ notnull_tbl6_1
-- NOT NULL NOT VALID
PREPARE get_nnconstraint_info(regclass[]) AS SELECT conrelid::regclass as tabname, conname, convalidated, conislocal, coninhcount FROM pg_constraint WHERE conrelid = ANY($1) ORDERBY conrelid::regclass::text COLLATE"C", conname;
CREATETABLE notnull_tbl1 (a int, b int); INSERTINTO notnull_tbl1 VALUES (NULL, 1), (300, 3); ALTERTABLE notnull_tbl1 ADDCONSTRAINT nn NOTNULL a; -- error ALTERTABLE notnull_tbl1 ADDCONSTRAINT nn NOTNULL a NOT VALID; -- ok -- even an invalid not-null forbids new nulls INSERTINTO notnull_tbl1 VALUES (NULL, 4);
\d+ notnull_tbl1
-- If we have an invalid constraint, we can't have another ALTERTABLE notnull_tbl1 ADDCONSTRAINT nn1 NOTNULL a NOT VALID NO INHERIT; ALTERTABLE notnull_tbl1 ADDCONSTRAINT nn NOTNULL a;
-- cannot add primary key on a column with an invalid not-null ALTERTABLE notnull_tbl1 ADDPRIMARYKEY (a);
-- cannot set column as generated-as-identity if it has an invalid not-null ALTERTABLE notnull_tbl1 ALTERCOLUMN a ADD GENERATED ALWAYS AS IDENTITY;
-- ALTER column SET NOT NULL validates an invalid constraint (but this fails -- because of rows with null values) ALTERTABLE notnull_tbl1 ALTER a SETNOTNULL;
\d+ notnull_tbl1
-- Creating a derived table using LIKE gets the constraint, but it's valid CREATETABLE notnull_tbl1_copy (LIKE notnull_tbl1);
EXECUTE get_nnconstraint_info('{notnull_tbl1_copy}');
-- An inheritance child table gets the constraint, but it's valid CREATETABLE notnull_tbl1_child (a int, b int) INHERITS (notnull_tbl1);
EXECUTE get_nnconstraint_info('{notnull_tbl1_child, notnull_tbl1}');
-- Also try inheritance added after table creation CREATETABLE notnull_tbl1_child2 (c int, b int, a int); ALTERTABLE notnull_tbl1_child2 INHERIT notnull_tbl1; -- nope ALTERTABLE notnull_tbl1_child2 ADDNOTNULL a NOT VALID; ALTERTABLE notnull_tbl1_child2 INHERIT notnull_tbl1;
EXECUTE get_nnconstraint_info('{notnull_tbl1_child2}');
-- VALIDATE CONSTRAINT scans the table ALTERTABLE notnull_tbl1 VALIDATE CONSTRAINT nn; -- error, nulls exist UPDATE notnull_tbl1 SET a = 100WHERE b = 1; ALTERTABLE notnull_tbl1 VALIDATE CONSTRAINT nn; -- now ok
EXECUTE get_nnconstraint_info('{notnull_tbl1}');
--- now we can add primary key ALTERTABLE notnull_tbl1 ADDPRIMARYKEY (a); DROPTABLE notnull_tbl1, notnull_tbl1_child, notnull_tbl1_child2;
-- dropping an invalid constraint is possible CREATETABLE notnull_tbl1 (a int, b int); ALTERTABLE notnull_tbl1 ADDNOTNULL a NOT VALID, ADDNOTNULL b NOT VALID; ALTERTABLE notnull_tbl1 ALTER a DROPNOTNULL; ALTERTABLE notnull_tbl1 DROPCONSTRAINT notnull_tbl1_b_not_null; DROPTABLE notnull_tbl1;
-- ALTER .. NO INHERIT works for invalid constraints CREATETABLE notnull_tbl1 (a int); CREATETABLE notnull_tbl1_chld () INHERITS (notnull_tbl1); ALTERTABLE notnull_tbl1 ADDCONSTRAINT nntbl1_a NOTNULL a NOT VALID; ALTERTABLE notnull_tbl1 ALTERCONSTRAINT nntbl1_a NO INHERIT;
-- DROP CONSTRAINT recurses correctly on invalid constraints ALTERTABLE notnull_tbl1 ALTERCONSTRAINT nntbl1_a INHERIT; ALTERTABLE notnull_tbl1 DROPCONSTRAINT nntbl1_a; DROPTABLE notnull_tbl1, notnull_tbl1_chld;
-- if a parent has a valid not null constraint then a child table cannot -- have an invalid one CREATETABLE notnull_tbl1 (a int); ALTERTABLE notnull_tbl1 ADDCONSTRAINT nn_parent NOTNULL a not valid; CREATETABLE notnull_chld0 (a int, CONSTRAINT nn_chld0 NOTNULL a); ALTERTABLE notnull_tbl1 INHERIT notnull_chld0; --error
ALTERTABLE notnull_chld0 DROPCONSTRAINT nn_chld0; ALTERTABLE notnull_chld0 ADDCONSTRAINT nn_chld0 NOTNULL a not valid; ALTERTABLE notnull_tbl1 INHERIT notnull_chld0; --now ok
-- parents and child not-null will all be validated. ALTERTABLE notnull_tbl1 VALIDATE CONSTRAINT nn_parent;
EXECUTE get_nnconstraint_info('{notnull_tbl1, notnull_chld0}'); DROPTABLE notnull_tbl1, notnull_chld0;
-- Test invalid not null on inheritance table. CREATETABLE notnull_inhparent (i int); CREATETABLE notnull_inhchild (i int) INHERITS (notnull_inhparent); CREATETABLE notnull_inhgrand () INHERITS (notnull_inhparent, notnull_inhchild); ALTERTABLE notnull_inhparent ADDCONSTRAINT nn NOTNULL i NOT VALID; ALTERTABLE notnull_inhchild ADDCONSTRAINT nn1 NOTNULL i; -- error
EXECUTE get_nnconstraint_info('{notnull_inhparent, notnull_inhchild, notnull_inhgrand}'); ALTERTABLE notnull_inhparent ALTER i SETNOTNULL; -- ok
EXECUTE get_nnconstraint_info('{notnull_inhparent, notnull_inhchild, notnull_inhgrand}'); DROPTABLE notnull_inhparent, notnull_inhchild, notnull_inhgrand;
-- Verify NOT NULL VALID/NOT VALID with partition table. DROPTABLE notnull_tbl1; CREATETABLE notnull_tbl1 (a int, b int) PARTITION BY LIST (a); ALTERTABLE notnull_tbl1 ADDCONSTRAINT notnull_con NOTNULL a NOT VALID; --ok CREATETABLE notnull_tbl1_1 PARTITION OF notnull_tbl1 FORVALUESIN (1,2); CREATETABLE notnull_tbl1_2(a int, CONSTRAINT nn2 NOTNULL a, b int); ALTERTABLE notnull_tbl1 ATTACH PARTITION notnull_tbl1_2 FORVALUESIN (3,4);
CREATETABLE notnull_tbl1_3(a int, b int); INSERTINTO notnull_tbl1_3 values(NULL,1); ALTERTABLE notnull_tbl1_3 addCONSTRAINT nn3 NOTNULL a NOT VALID; ALTERTABLE notnull_tbl1 ATTACH PARTITION notnull_tbl1_3 FORVALUESIN (NULL,5);
-- partitioned table have not-null, then the partitions can not be NOT NULL NOT VALID. CREATETABLE pp_nn (a int, b int, NOTNULL a) PARTITION BY LIST (a); CREATETABLE pp_nn_1(a int, b int); ALTERTABLE pp_nn_1 ADDCONSTRAINT nn1 NOTNULL a NOT VALID; ALTERTABLE pp_nn ATTACH PARTITION pp_nn_1 FORVALUESIN (NULL,5); --error ALTERTABLE pp_nn_1 VALIDATE CONSTRAINT nn1; ALTERTABLE pp_nn ATTACH PARTITION pp_nn_1 FORVALUESIN (NULL,5); --ok DROPTABLE pp_nn;
-- Try a partition with an invalid constraint and create a PK on the parent. CREATETABLE pp_nn (a int) PARTITION BY HASH (a); CREATETABLE pp_nn_1 PARTITION OF pp_nn FORVALUESWITH (MODULUS 2, REMAINDER 0); ALTERTABLE pp_nn_1 ADDCONSTRAINT nn NOTNULL a NOT VALID; ALTERTABLE ONLY pp_nn ADDPRIMARYKEY (a); DROPTABLE pp_nn;
-- same as above, but the constraint is NO INHERIT CREATETABLE pp_nn (a int) PARTITION BY HASH (a); CREATETABLE pp_nn_1 PARTITION OF pp_nn FORVALUESWITH (MODULUS 2, REMAINDER 0); ALTERTABLE pp_nn_1 ADDCONSTRAINT nn NOTNULL a NO INHERIT; ALTERTABLE ONLY pp_nn ADDPRIMARYKEY (a); DROPTABLE pp_nn;
-- Create table with NOT NULL INVALID constraint, for pg_upgrade. CREATETABLE notnull_tbl1_upg (a int, b int); INSERTINTO notnull_tbl1_upg VALUES (NULL, 1), (NULL, 2), (300, 3); ALTERTABLE notnull_tbl1_upg ADDCONSTRAINT nn NOTNULL a NOT VALID; -- Inherit test for pg_upgrade CREATETABLE notnull_parent_upg (a int); CREATETABLE notnull_child_upg () INHERITS (notnull_parent_upg); ALTERTABLE notnull_child_upg ADDCONSTRAINT nn NOTNULL a; ALTERTABLE notnull_parent_upg ADDCONSTRAINT nn NOTNULL a NOT VALID; SELECT conrelid::regclass, contype, convalidated, conislocal FROM pg_catalog.pg_constraint WHERE conrelid in ('notnull_parent_upg'::regclass, 'notnull_child_upg'::regclass) ORDERBY1;
-- Partition table test, for pg_upgrade CREATETABLE notnull_part1_upg (a int, b int) PARTITION BY LIST (a); ALTERTABLE notnull_part1_upg ADDCONSTRAINT notnull_con NOTNULL a NOT VALID; --ok CREATETABLE notnull_part1_1_upg PARTITION OF notnull_part1_upg FORVALUESIN (1,2); CREATETABLE notnull_part1_2_upg (a int, CONSTRAINT nn2 NOTNULL a, b int); ALTERTABLE notnull_part1_upg ATTACH PARTITION notnull_part1_2_upg FORVALUESIN (3,4); CREATETABLE notnull_part1_3_upg (a int, b int); INSERTINTO notnull_part1_3_upg values(NULL,1); ALTERTABLE notnull_part1_3_upg addCONSTRAINT nn3 NOTNULL a NOT VALID; ALTERTABLE notnull_part1_upg ATTACH PARTITION notnull_part1_3_upg FORVALUESIN (NULL,5);
EXECUTE get_nnconstraint_info('{notnull_part1_upg, notnull_part1_1_upg, notnull_part1_2_upg, notnull_part1_3_upg}');
-- Inheritance test tables for pg_upgrade createtable constr_parent (a int); createtable constr_child (a int) inherits (constr_parent); altertable constr_parent addnotnull a not valid; altertable constr_child validate constraint constr_parent_a_not_null;
EXECUTE get_nnconstraint_info('{constr_parent, constr_child}');
createtable constr_parent2 (a int); createtable constr_child2 () inherits (constr_parent2); altertable constr_parent2 addnotnull a not valid; altertable constr_child2 validate constraint constr_parent2_a_not_null;
EXECUTE get_nnconstraint_info('{constr_parent2, constr_child2}');
COMMENT ONCONSTRAINT constr_parent2_a_not_null ON constr_parent2 IS'this constraint is invalid';
COMMENT ONCONSTRAINT constr_parent2_a_not_null ON constr_child2 IS'this constraint is valid';
DEALLOCATE get_nnconstraint_info;
-- end NOT NULL NOT VALID
-- Comments -- Setup a low-level role to enforce non-superuser checks. CREATE ROLE regress_constraint_comments; SET SESSION AUTHORIZATION regress_constraint_comments;
CREATETABLE constraint_comments_tbl (a intCONSTRAINT the_constraint CHECK (a > 0)); CREATE DOMAIN constraint_comments_dom ASintCONSTRAINT the_constraint CHECK (value > 0);
COMMENT ONCONSTRAINT the_constraint ON constraint_comments_tbl IS'yes, the comment';
COMMENT ONCONSTRAINT the_constraint ON DOMAIN constraint_comments_dom IS'yes, another comment';
-- no such constraint
COMMENT ONCONSTRAINT no_constraint ON constraint_comments_tbl IS'yes, the comment';
COMMENT ONCONSTRAINT no_constraint ON DOMAIN constraint_comments_dom IS'yes, another comment';
-- no such table/domain
COMMENT ONCONSTRAINT the_constraint ON no_comments_tbl IS'bad comment';
COMMENT ONCONSTRAINT the_constraint ON DOMAIN no_comments_dom IS'another bad comment';
COMMENT ONCONSTRAINT the_constraint ON constraint_comments_tbl ISNULL;
COMMENT ONCONSTRAINT the_constraint ON DOMAIN constraint_comments_dom ISNULL;
-- unauthorized user
RESET SESSION AUTHORIZATION; CREATE ROLE regress_constraint_comments_noaccess; SET SESSION AUTHORIZATION regress_constraint_comments_noaccess;
COMMENT ONCONSTRAINT the_constraint ON constraint_comments_tbl IS'no, the comment';
COMMENT ONCONSTRAINT the_constraint ON DOMAIN constraint_comments_dom IS'no, another comment';
RESET SESSION AUTHORIZATION;
DROPTABLE constraint_comments_tbl; DROP DOMAIN constraint_comments_dom;
DROP ROLE regress_constraint_comments; DROP ROLE regress_constraint_comments_noaccess;
-- Leave some constraints for the pg_upgrade test to pick up CREATE DOMAIN constraint_comments_dom ASint;
ALTER DOMAIN constraint_comments_dom ADDCONSTRAINT inv_ck CHECK (value > 0) NOT VALID;
COMMENT ONCONSTRAINT inv_ck ON DOMAIN constraint_comments_dom IS'comment on invalid constraint';
-- Create a table that exercises pg_upgrade CREATETABLE regress_notnull1 (a integer); CREATETABLE regress_notnull2 () INHERITS (regress_notnull1); ALTERTABLE ONLY regress_notnull2 ALTERCOLUMN a SETNOTNULL;
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.5 Sekunden
(vorverarbeitet am 2026-08-08)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.