1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-03 09:13:20 +03:00

Add support for NOT ENFORCED in CHECK constraints

This adds support for the NOT ENFORCED/ENFORCED flag for constraints,
with support for check constraints.

The plan is to eventually support this for foreign key constraints,
where it is typically more useful.

Note that CHECK constraints do not currently support ALTER operations,
so changing the enforceability of an existing constraint isn't
possible without dropping and recreating it.  This could be added
later.

Author: Amul Sul <amul.sul@enterprisedb.com>
Reviewed-by: Peter Eisentraut <peter@eisentraut.org>
Reviewed-by: jian he <jian.universality@gmail.com>
Tested-by: Triveni N <triveni.n@enterprisedb.com>
Discussion: https://www.postgresql.org/message-id/flat/CAAJ_b962c5AcYW9KUt_R_ER5qs3fUGbe4az-SP-vuwPS-w-AGA@mail.gmail.com
This commit is contained in:
Peter Eisentraut
2025-01-11 10:45:17 +01:00
parent 72ceb21b02
commit ca87c415e2
37 changed files with 599 additions and 70 deletions

View File

@@ -387,10 +387,12 @@ ALTER TABLE attmp3 validate constraint attmpconstr;
-- Try a non-verified CHECK constraint
ALTER TABLE attmp3 ADD CONSTRAINT b_greater_than_ten CHECK (b > 10); -- fail
ALTER TABLE attmp3 ADD CONSTRAINT b_greater_than_ten CHECK (b > 10) NOT VALID; -- succeeds
ALTER TABLE attmp3 ADD CONSTRAINT b_greater_than_ten_not_enforced CHECK (b > 10) NOT ENFORCED; -- succeeds
ALTER TABLE attmp3 VALIDATE CONSTRAINT b_greater_than_ten; -- fails
DELETE FROM attmp3 WHERE NOT b > 10;
ALTER TABLE attmp3 VALIDATE CONSTRAINT b_greater_than_ten; -- succeeds
ALTER TABLE attmp3 VALIDATE CONSTRAINT b_greater_than_ten; -- succeeds
ALTER TABLE attmp3 VALIDATE CONSTRAINT b_greater_than_ten_not_enforced; -- fail
-- Test inherited NOT VALID CHECK constraints
select * from attmp3;
@@ -1188,6 +1190,11 @@ alter table renameColumn add column w int;
-- this should fail
alter table only renameColumn add column x int;
-- this should work
alter table renameColumn add column x int check (x > 0) not enforced;
-- this should fail
alter table renameColumn add column y int check (x > 0) not enforced enforced;
-- Test corner cases in dropping of inherited columns

View File

@@ -67,6 +67,18 @@ INSERT INTO CHECK_TBL VALUES (1);
SELECT * FROM CHECK_TBL;
CREATE TABLE NE_CHECK_TBL (x int,
CONSTRAINT CHECK_CON CHECK (x > 3) NOT ENFORCED);
INSERT INTO NE_CHECK_TBL VALUES (5);
INSERT INTO NE_CHECK_TBL VALUES (4);
INSERT INTO NE_CHECK_TBL VALUES (3);
INSERT INTO NE_CHECK_TBL VALUES (2);
INSERT INTO NE_CHECK_TBL VALUES (6);
INSERT INTO NE_CHECK_TBL VALUES (1);
SELECT * FROM NE_CHECK_TBL;
CREATE SEQUENCE CHECK_SEQ;
CREATE TABLE CHECK2_TBL (x int, y text, z int,
@@ -92,7 +104,8 @@ CREATE TABLE INSERT_TBL (x INT DEFAULT nextval('insert_seq'),
y TEXT DEFAULT '-NULL-',
z INT DEFAULT -1 * currval('insert_seq'),
CONSTRAINT INSERT_TBL_CON CHECK (x >= 3 AND y <> 'check failed' AND x < 8),
CHECK (x + z = 0));
CHECK (x + z = 0) ENFORCED, /* no change it is a default */
CONSTRAINT NE_INSERT_TBL_CON CHECK (x + z = 1) NOT ENFORCED);
INSERT INTO INSERT_TBL(x,z) VALUES (2, -2);
@@ -518,6 +531,13 @@ COMMIT;
SELECT * FROM unique_tbl;
-- enforcibility cannot be specified or set for unique constrain
CREATE TABLE UNIQUE_EN_TBL(i int UNIQUE ENFORCED);
CREATE TABLE UNIQUE_NOTEN_TBL(i int UNIQUE NOT ENFORCED);
-- XXX: error message is misleading here
ALTER TABLE unique_tbl ALTER CONSTRAINT unique_tbl_i_key ENFORCED;
ALTER TABLE unique_tbl ALTER CONSTRAINT unique_tbl_i_key NOT ENFORCED;
DROP TABLE unique_tbl;
--

View File

@@ -128,7 +128,8 @@ CREATE TABLE inhz (x text REFERENCES inhz, LIKE inhx INCLUDING INDEXES);
DROP TABLE inhz;
-- including storage and comments
CREATE TABLE ctlt1 (a text CHECK (length(a) > 2) PRIMARY KEY, b text);
CREATE TABLE ctlt1 (a text CHECK (length(a) > 2) ENFORCED PRIMARY KEY,
b text CHECK (length(b) > 100) NOT ENFORCED);
CREATE INDEX ctlt1_b_key ON ctlt1 (b);
CREATE INDEX ctlt1_fnidx ON ctlt1 ((a || b));
CREATE STATISTICS ctlt1_a_b_stat ON a,b FROM ctlt1;

View File

@@ -880,6 +880,16 @@ select pg_basetype(1); -- expect NULL not error
drop domain mytext cascade;
--
-- Explicit enforceability specification not allowed
---
CREATE DOMAIN constraint_enforced_dom AS int CONSTRAINT the_constraint CHECK (value > 0) ENFORCED;
CREATE DOMAIN constraint_not_enforced_dom AS int CONSTRAINT the_constraint CHECK (value > 0) NOT ENFORCED;
CREATE DOMAIN constraint_enforced_dom AS int;
-- XXX misleading error messages
ALTER DOMAIN constraint_enforced_dom ADD CONSTRAINT the_constraint CHECK (value > 0) ENFORCED;
ALTER DOMAIN constraint_enforced_dom ADD CONSTRAINT the_constraint CHECK (value > 0) NOT ENFORCED;
DROP DOMAIN constraint_enforced_dom;
--
-- Information schema

View File

@@ -468,12 +468,57 @@ alter table p1_c1 add constraint inh_check_constraint1 check (f1 > 0);
alter table p1_c1 add constraint inh_check_constraint2 check (f1 < 10);
alter table p1 add constraint inh_check_constraint2 check (f1 < 10);
select conrelid::regclass::text as relname, conname, conislocal, coninhcount
alter table p1 add constraint inh_check_constraint3 check (f1 > 0) not enforced;
alter table p1_c1 add constraint inh_check_constraint3 check (f1 > 0) not enforced;
alter table p1_c1 add constraint inh_check_constraint4 check (f1 < 10) not enforced;
alter table p1 add constraint inh_check_constraint4 check (f1 < 10) not enforced;
-- allowed to merge enforced constraint with parent's not enforced constraint
alter table p1_c1 add constraint inh_check_constraint5 check (f1 < 10) enforced;
alter table p1 add constraint inh_check_constraint5 check (f1 < 10) not enforced;
alter table p1 add constraint inh_check_constraint6 check (f1 < 10) not enforced;
alter table p1_c1 add constraint inh_check_constraint6 check (f1 < 10) enforced;
create table p1_c2(f1 int constraint inh_check_constraint4 check (f1 < 10)) inherits(p1);
-- but reverse is not allowed
alter table p1_c1 add constraint inh_check_constraint7 check (f1 < 10) not enforced;
alter table p1 add constraint inh_check_constraint7 check (f1 < 10) enforced;
alter table p1 add constraint inh_check_constraint8 check (f1 < 10) enforced;
alter table p1_c1 add constraint inh_check_constraint8 check (f1 < 10) not enforced;
create table p1_fail(f1 int constraint inh_check_constraint2 check (f1 < 10) not enforced) inherits(p1);
-- constraints with different enforceability can be merged by marking them as ENFORCED
create table p1_c3() inherits(p1, p1_c1);
-- but not allowed if the child constraint is explicitly asked to be NOT ENFORCED
create table p1_fail(f1 int constraint inh_check_constraint6 check (f1 < 10) not enforced) inherits(p1, p1_c1);
select conrelid::regclass::text as relname, conname, conislocal, coninhcount, conenforced
from pg_constraint where conname like 'inh\_check\_constraint%'
order by 1, 2;
drop table p1 cascade;
--
-- Similarly, check the merging of existing constraints; a parent constraint
-- marked as NOT ENFORCED can merge with an ENFORCED child constraint, but the
-- reverse is not allowed.
--
create table p1(f1 int constraint p1_a_check check (f1 > 0) not enforced);
create table p1_c1(f1 int constraint p1_a_check check (f1 > 0) enforced);
alter table p1_c1 inherit p1;
drop table p1 cascade;
create table p1(f1 int constraint p1_a_check check (f1 > 0) enforced);
create table p1_c1(f1 int constraint p1_a_check check (f1 > 0) not enforced);
alter table p1_c1 inherit p1;
drop table p1, p1_c1;
--
-- Test DROP behavior of multiply-defined CHECK constraints
--