1-- 2-- Test domains. 3-- 4-- Test Comment / Drop 5create domain domaindroptest int4; 6comment on domain domaindroptest is 'About to drop this..'; 7create domain dependenttypetest domaindroptest; 8-- fail because of dependent type 9drop domain domaindroptest; 10ERROR: cannot drop type domaindroptest because other objects depend on it 11DETAIL: type dependenttypetest depends on type domaindroptest 12HINT: Use DROP ... CASCADE to drop the dependent objects too. 13drop domain domaindroptest cascade; 14NOTICE: drop cascades to type dependenttypetest 15-- this should fail because already gone 16drop domain domaindroptest cascade; 17ERROR: type "domaindroptest" does not exist 18-- Test domain input. 19-- Note: the point of checking both INSERT and COPY FROM is that INSERT 20-- exercises CoerceToDomain while COPY exercises domain_in. 21create domain domainvarchar varchar(5); 22create domain domainnumeric numeric(8,2); 23create domain domainint4 int4; 24create domain domaintext text; 25-- Test explicit coercions --- these should succeed (and truncate) 26SELECT cast('123456' as domainvarchar); 27 domainvarchar 28--------------- 29 12345 30(1 row) 31 32SELECT cast('12345' as domainvarchar); 33 domainvarchar 34--------------- 35 12345 36(1 row) 37 38-- Test tables using domains 39create table basictest 40 ( testint4 domainint4 41 , testtext domaintext 42 , testvarchar domainvarchar 43 , testnumeric domainnumeric 44 ); 45INSERT INTO basictest values ('88', 'haha', 'short', '123.12'); -- Good 46INSERT INTO basictest values ('88', 'haha', 'short text', '123.12'); -- Bad varchar 47ERROR: value too long for type character varying(5) 48INSERT INTO basictest values ('88', 'haha', 'short', '123.1212'); -- Truncate numeric 49-- Test copy 50COPY basictest (testvarchar) FROM stdin; -- fail 51ERROR: value too long for type character varying(5) 52CONTEXT: COPY basictest, line 1, column testvarchar: "notsoshorttext" 53COPY basictest (testvarchar) FROM stdin; 54select * from basictest; 55 testint4 | testtext | testvarchar | testnumeric 56----------+----------+-------------+------------- 57 88 | haha | short | 123.12 58 88 | haha | short | 123.12 59 | | short | 60(3 rows) 61 62-- check that domains inherit operations from base types 63select testtext || testvarchar as concat, testnumeric + 42 as sum 64from basictest; 65 concat | sum 66-----------+-------- 67 hahashort | 165.12 68 hahashort | 165.12 69 | 70(3 rows) 71 72-- check that union/case/coalesce type resolution handles domains properly 73select coalesce(4::domainint4, 7) is of (int4) as t; 74 t 75--- 76 t 77(1 row) 78 79select coalesce(4::domainint4, 7) is of (domainint4) as f; 80 f 81--- 82 f 83(1 row) 84 85select coalesce(4::domainint4, 7::domainint4) is of (domainint4) as t; 86 t 87--- 88 t 89(1 row) 90 91drop table basictest; 92drop domain domainvarchar restrict; 93drop domain domainnumeric restrict; 94drop domain domainint4 restrict; 95drop domain domaintext; 96-- Test domains over array types 97create domain domainint4arr int4[1]; 98create domain domainchar4arr varchar(4)[2][3]; 99create table domarrtest 100 ( testint4arr domainint4arr 101 , testchar4arr domainchar4arr 102 ); 103INSERT INTO domarrtest values ('{2,2}', '{{"a","b"},{"c","d"}}'); 104INSERT INTO domarrtest values ('{{2,2},{2,2}}', '{{"a","b"}}'); 105INSERT INTO domarrtest values ('{2,2}', '{{"a","b"},{"c","d"},{"e","f"}}'); 106INSERT INTO domarrtest values ('{2,2}', '{{"a"},{"c"}}'); 107INSERT INTO domarrtest values (NULL, '{{"a","b","c"},{"d","e","f"}}'); 108INSERT INTO domarrtest values (NULL, '{{"toolong","b","c"},{"d","e","f"}}'); 109ERROR: value too long for type character varying(4) 110INSERT INTO domarrtest (testint4arr[1], testint4arr[3]) values (11,22); 111select * from domarrtest; 112 testint4arr | testchar4arr 113---------------+--------------------- 114 {2,2} | {{a,b},{c,d}} 115 {{2,2},{2,2}} | {{a,b}} 116 {2,2} | {{a,b},{c,d},{e,f}} 117 {2,2} | {{a},{c}} 118 | {{a,b,c},{d,e,f}} 119 {11,NULL,22} | 120(6 rows) 121 122select testint4arr[1], testchar4arr[2:2] from domarrtest; 123 testint4arr | testchar4arr 124-------------+-------------- 125 2 | {{c,d}} 126 | {} 127 2 | {{c,d}} 128 2 | {{c}} 129 | {{d,e,f}} 130 11 | 131(6 rows) 132 133select array_dims(testint4arr), array_dims(testchar4arr) from domarrtest; 134 array_dims | array_dims 135------------+------------ 136 [1:2] | [1:2][1:2] 137 [1:2][1:2] | [1:1][1:2] 138 [1:2] | [1:3][1:2] 139 [1:2] | [1:2][1:1] 140 | [1:2][1:3] 141 [1:3] | 142(6 rows) 143 144COPY domarrtest FROM stdin; 145COPY domarrtest FROM stdin; -- fail 146ERROR: value too long for type character varying(4) 147CONTEXT: COPY domarrtest, line 1, column testchar4arr: "{qwerty,w,e}" 148select * from domarrtest; 149 testint4arr | testchar4arr 150---------------+--------------------- 151 {2,2} | {{a,b},{c,d}} 152 {{2,2},{2,2}} | {{a,b}} 153 {2,2} | {{a,b},{c,d},{e,f}} 154 {2,2} | {{a},{c}} 155 | {{a,b,c},{d,e,f}} 156 {11,NULL,22} | 157 {3,4} | {q,w,e} 158 | 159(8 rows) 160 161update domarrtest set 162 testint4arr[1] = testint4arr[1] + 1, 163 testint4arr[3] = testint4arr[3] - 1 164where testchar4arr is null; 165select * from domarrtest where testchar4arr is null; 166 testint4arr | testchar4arr 167------------------+-------------- 168 {12,NULL,21} | 169 {NULL,NULL,NULL} | 170(2 rows) 171 172drop table domarrtest; 173drop domain domainint4arr restrict; 174drop domain domainchar4arr restrict; 175create domain dia as int[]; 176select '{1,2,3}'::dia; 177 dia 178--------- 179 {1,2,3} 180(1 row) 181 182select array_dims('{1,2,3}'::dia); 183 array_dims 184------------ 185 [1:3] 186(1 row) 187 188select pg_typeof('{1,2,3}'::dia); 189 pg_typeof 190----------- 191 dia 192(1 row) 193 194select pg_typeof('{1,2,3}'::dia || 42); -- should be int[] not dia 195 pg_typeof 196----------- 197 integer[] 198(1 row) 199 200drop domain dia; 201-- Test domains over arrays of composite 202create type comptype as (r float8, i float8); 203create domain dcomptypea as comptype[]; 204create table dcomptable (d1 dcomptypea unique); 205insert into dcomptable values (array[row(1,2)]::dcomptypea); 206insert into dcomptable values (array[row(3,4), row(5,6)]::comptype[]); 207insert into dcomptable values (array[row(7,8)::comptype, row(9,10)::comptype]); 208insert into dcomptable values (array[row(1,2)]::dcomptypea); -- fail on uniqueness 209ERROR: duplicate key value violates unique constraint "dcomptable_d1_key" 210DETAIL: Key (d1)=({"(1,2)"}) already exists. 211insert into dcomptable (d1[1]) values(row(9,10)); 212insert into dcomptable (d1[1].r) values(11); 213select * from dcomptable; 214 d1 215-------------------- 216 {"(1,2)"} 217 {"(3,4)","(5,6)"} 218 {"(7,8)","(9,10)"} 219 {"(9,10)"} 220 {"(11,)"} 221(5 rows) 222 223select d1[2], d1[1].r, d1[1].i from dcomptable; 224 d1 | r | i 225--------+----+---- 226 | 1 | 2 227 (5,6) | 3 | 4 228 (9,10) | 7 | 8 229 | 9 | 10 230 | 11 | 231(5 rows) 232 233update dcomptable set d1[2] = row(d1[2].i, d1[2].r); 234select * from dcomptable; 235 d1 236-------------------- 237 {"(1,2)","(,)"} 238 {"(3,4)","(6,5)"} 239 {"(7,8)","(10,9)"} 240 {"(9,10)","(,)"} 241 {"(11,)","(,)"} 242(5 rows) 243 244update dcomptable set d1[1].r = d1[1].r + 1 where d1[1].i > 0; 245select * from dcomptable; 246 d1 247-------------------- 248 {"(11,)","(,)"} 249 {"(2,2)","(,)"} 250 {"(4,4)","(6,5)"} 251 {"(8,8)","(10,9)"} 252 {"(10,10)","(,)"} 253(5 rows) 254 255alter domain dcomptypea add constraint c1 check (value[1].r <= value[1].i); 256alter domain dcomptypea add constraint c2 check (value[1].r > value[1].i); -- fail 257ERROR: column "d1" of table "dcomptable" contains values that violate the new constraint 258select array[row(2,1)]::dcomptypea; -- fail 259ERROR: value for domain dcomptypea violates check constraint "c1" 260insert into dcomptable values (array[row(1,2)]::comptype[]); 261insert into dcomptable values (array[row(2,1)]::comptype[]); -- fail 262ERROR: value for domain dcomptypea violates check constraint "c1" 263insert into dcomptable (d1[1].r) values(99); 264insert into dcomptable (d1[1].r, d1[1].i) values(99, 100); 265insert into dcomptable (d1[1].r, d1[1].i) values(100, 99); -- fail 266ERROR: value for domain dcomptypea violates check constraint "c1" 267update dcomptable set d1[1].r = d1[1].r + 1 where d1[1].i > 0; -- fail 268ERROR: value for domain dcomptypea violates check constraint "c1" 269update dcomptable set d1[1].r = d1[1].r - 1, d1[1].i = d1[1].i + 1 270 where d1[1].i > 0; 271select * from dcomptable; 272 d1 273-------------------- 274 {"(11,)","(,)"} 275 {"(99,)"} 276 {"(1,3)","(,)"} 277 {"(3,5)","(6,5)"} 278 {"(7,9)","(10,9)"} 279 {"(9,11)","(,)"} 280 {"(0,3)"} 281 {"(98,101)"} 282(8 rows) 283 284explain (verbose, costs off) 285 update dcomptable set d1[1].r = d1[1].r - 1, d1[1].i = d1[1].i + 1 286 where d1[1].i > 0; 287 QUERY PLAN 288---------------------------------------------------------------------------------------------------------------- 289 Update on public.dcomptable 290 -> Seq Scan on public.dcomptable 291 Output: (d1[1].r := (d1[1].r - '1'::double precision))[1].i := (d1[1].i + '1'::double precision), ctid 292 Filter: (dcomptable.d1[1].i > '0'::double precision) 293(4 rows) 294 295create rule silly as on delete to dcomptable do instead 296 update dcomptable set d1[1].r = d1[1].r - 1, d1[1].i = d1[1].i + 1 297 where d1[1].i > 0; 298\d+ dcomptable 299 Table "public.dcomptable" 300 Column | Type | Collation | Nullable | Default | Storage | Stats target | Description 301--------+------------+-----------+----------+---------+----------+--------------+------------- 302 d1 | dcomptypea | | | | extended | | 303Indexes: 304 "dcomptable_d1_key" UNIQUE CONSTRAINT, btree (d1) 305Rules: 306 silly AS 307 ON DELETE TO dcomptable DO INSTEAD UPDATE dcomptable SET d1[1].r = dcomptable.d1[1].r - 1::double precision, d1[1].i = dcomptable.d1[1].i + 1::double precision 308 WHERE dcomptable.d1[1].i > 0::double precision 309 310drop table dcomptable; 311drop type comptype cascade; 312NOTICE: drop cascades to type dcomptypea 313-- Test not-null restrictions 314create domain dnotnull varchar(15) NOT NULL; 315create domain dnull varchar(15); 316create domain dcheck varchar(15) NOT NULL CHECK (VALUE = 'a' OR VALUE = 'c' OR VALUE = 'd'); 317create table nulltest 318 ( col1 dnotnull 319 , col2 dnotnull NULL -- NOT NULL in the domain cannot be overridden 320 , col3 dnull NOT NULL 321 , col4 dnull 322 , col5 dcheck CHECK (col5 IN ('c', 'd')) 323 ); 324INSERT INTO nulltest DEFAULT VALUES; 325ERROR: domain dnotnull does not allow null values 326INSERT INTO nulltest values ('a', 'b', 'c', 'd', 'c'); -- Good 327insert into nulltest values ('a', 'b', 'c', 'd', NULL); 328ERROR: domain dcheck does not allow null values 329insert into nulltest values ('a', 'b', 'c', 'd', 'a'); 330ERROR: new row for relation "nulltest" violates check constraint "nulltest_col5_check" 331DETAIL: Failing row contains (a, b, c, d, a). 332INSERT INTO nulltest values (NULL, 'b', 'c', 'd', 'd'); 333ERROR: domain dnotnull does not allow null values 334INSERT INTO nulltest values ('a', NULL, 'c', 'd', 'c'); 335ERROR: domain dnotnull does not allow null values 336INSERT INTO nulltest values ('a', 'b', NULL, 'd', 'c'); 337ERROR: null value in column "col3" violates not-null constraint 338DETAIL: Failing row contains (a, b, null, d, c). 339INSERT INTO nulltest values ('a', 'b', 'c', NULL, 'd'); -- Good 340-- Test copy 341COPY nulltest FROM stdin; --fail 342ERROR: null value in column "col3" violates not-null constraint 343DETAIL: Failing row contains (a, b, null, d, d). 344CONTEXT: COPY nulltest, line 1: "a b \N d d" 345COPY nulltest FROM stdin; --fail 346ERROR: domain dcheck does not allow null values 347CONTEXT: COPY nulltest, line 1, column col5: null input 348-- Last row is bad 349COPY nulltest FROM stdin; 350ERROR: new row for relation "nulltest" violates check constraint "nulltest_col5_check" 351DETAIL: Failing row contains (a, b, c, null, a). 352CONTEXT: COPY nulltest, line 3: "a b c \N a" 353select * from nulltest; 354 col1 | col2 | col3 | col4 | col5 355------+------+------+------+------ 356 a | b | c | d | c 357 a | b | c | | d 358(2 rows) 359 360-- Test out coerced (casted) constraints 361SELECT cast('1' as dnotnull); 362 dnotnull 363---------- 364 1 365(1 row) 366 367SELECT cast(NULL as dnotnull); -- fail 368ERROR: domain dnotnull does not allow null values 369SELECT cast(cast(NULL as dnull) as dnotnull); -- fail 370ERROR: domain dnotnull does not allow null values 371SELECT cast(col4 as dnotnull) from nulltest; -- fail 372ERROR: domain dnotnull does not allow null values 373-- cleanup 374drop table nulltest; 375drop domain dnotnull restrict; 376drop domain dnull restrict; 377drop domain dcheck restrict; 378create domain ddef1 int4 DEFAULT 3; 379create domain ddef2 oid DEFAULT '12'; 380-- Type mixing, function returns int8 381create domain ddef3 text DEFAULT 5; 382create sequence ddef4_seq; 383create domain ddef4 int4 DEFAULT nextval('ddef4_seq'); 384create domain ddef5 numeric(8,2) NOT NULL DEFAULT '12.12'; 385create table defaulttest 386 ( col1 ddef1 387 , col2 ddef2 388 , col3 ddef3 389 , col4 ddef4 PRIMARY KEY 390 , col5 ddef1 NOT NULL DEFAULT NULL 391 , col6 ddef2 DEFAULT '88' 392 , col7 ddef4 DEFAULT 8000 393 , col8 ddef5 394 ); 395insert into defaulttest(col4) values(0); -- fails, col5 defaults to null 396ERROR: null value in column "col5" violates not-null constraint 397DETAIL: Failing row contains (3, 12, 5, 0, null, 88, 8000, 12.12). 398alter table defaulttest alter column col5 drop default; 399insert into defaulttest default values; -- succeeds, inserts domain default 400-- We used to treat SET DEFAULT NULL as equivalent to DROP DEFAULT; wrong 401alter table defaulttest alter column col5 set default null; 402insert into defaulttest(col4) values(0); -- fails 403ERROR: null value in column "col5" violates not-null constraint 404DETAIL: Failing row contains (3, 12, 5, 0, null, 88, 8000, 12.12). 405alter table defaulttest alter column col5 drop default; 406insert into defaulttest default values; 407insert into defaulttest default values; 408-- Test defaults with copy 409COPY defaulttest(col5) FROM stdin; 410select * from defaulttest; 411 col1 | col2 | col3 | col4 | col5 | col6 | col7 | col8 412------+------+------+------+------+------+------+------- 413 3 | 12 | 5 | 1 | 3 | 88 | 8000 | 12.12 414 3 | 12 | 5 | 2 | 3 | 88 | 8000 | 12.12 415 3 | 12 | 5 | 3 | 3 | 88 | 8000 | 12.12 416 3 | 12 | 5 | 4 | 42 | 88 | 8000 | 12.12 417(4 rows) 418 419drop table defaulttest cascade; 420-- Test ALTER DOMAIN .. NOT NULL 421create domain dnotnulltest integer; 422create table domnotnull 423( col1 dnotnulltest 424, col2 dnotnulltest 425); 426insert into domnotnull default values; 427alter domain dnotnulltest set not null; -- fails 428ERROR: column "col1" of table "domnotnull" contains null values 429update domnotnull set col1 = 5; 430alter domain dnotnulltest set not null; -- fails 431ERROR: column "col2" of table "domnotnull" contains null values 432update domnotnull set col2 = 6; 433alter domain dnotnulltest set not null; 434update domnotnull set col1 = null; -- fails 435ERROR: domain dnotnulltest does not allow null values 436alter domain dnotnulltest drop not null; 437update domnotnull set col1 = null; 438drop domain dnotnulltest cascade; 439NOTICE: drop cascades to 2 other objects 440DETAIL: drop cascades to table domnotnull column col1 441drop cascades to table domnotnull column col2 442-- Test ALTER DOMAIN .. DEFAULT .. 443create table domdeftest (col1 ddef1); 444insert into domdeftest default values; 445select * from domdeftest; 446 col1 447------ 448 3 449(1 row) 450 451alter domain ddef1 set default '42'; 452insert into domdeftest default values; 453select * from domdeftest; 454 col1 455------ 456 3 457 42 458(2 rows) 459 460alter domain ddef1 drop default; 461insert into domdeftest default values; 462select * from domdeftest; 463 col1 464------ 465 3 466 42 467 468(3 rows) 469 470drop table domdeftest; 471-- Test ALTER DOMAIN .. CONSTRAINT .. 472create domain con as integer; 473create table domcontest (col1 con); 474insert into domcontest values (1); 475insert into domcontest values (2); 476alter domain con add constraint t check (VALUE < 1); -- fails 477ERROR: column "col1" of table "domcontest" contains values that violate the new constraint 478alter domain con add constraint t check (VALUE < 34); 479alter domain con add check (VALUE > 0); 480insert into domcontest values (-5); -- fails 481ERROR: value for domain con violates check constraint "con_check" 482insert into domcontest values (42); -- fails 483ERROR: value for domain con violates check constraint "t" 484insert into domcontest values (5); 485alter domain con drop constraint t; 486insert into domcontest values (-5); --fails 487ERROR: value for domain con violates check constraint "con_check" 488insert into domcontest values (42); 489alter domain con drop constraint nonexistent; 490ERROR: constraint "nonexistent" of domain "con" does not exist 491alter domain con drop constraint if exists nonexistent; 492NOTICE: constraint "nonexistent" of domain "con" does not exist, skipping 493-- Test ALTER DOMAIN .. CONSTRAINT .. NOT VALID 494create domain things AS INT; 495CREATE TABLE thethings (stuff things); 496INSERT INTO thethings (stuff) VALUES (55); 497ALTER DOMAIN things ADD CONSTRAINT meow CHECK (VALUE < 11); 498ERROR: column "stuff" of table "thethings" contains values that violate the new constraint 499ALTER DOMAIN things ADD CONSTRAINT meow CHECK (VALUE < 11) NOT VALID; 500ALTER DOMAIN things VALIDATE CONSTRAINT meow; 501ERROR: column "stuff" of table "thethings" contains values that violate the new constraint 502UPDATE thethings SET stuff = 10; 503ALTER DOMAIN things VALIDATE CONSTRAINT meow; 504-- Confirm ALTER DOMAIN with RULES. 505create table domtab (col1 integer); 506create domain dom as integer; 507create view domview as select cast(col1 as dom) from domtab; 508insert into domtab (col1) values (null); 509insert into domtab (col1) values (5); 510select * from domview; 511 col1 512------ 513 514 5 515(2 rows) 516 517alter domain dom set not null; 518select * from domview; -- fail 519ERROR: domain dom does not allow null values 520alter domain dom drop not null; 521select * from domview; 522 col1 523------ 524 525 5 526(2 rows) 527 528alter domain dom add constraint domchkgt6 check(value > 6); 529select * from domview; --fail 530ERROR: value for domain dom violates check constraint "domchkgt6" 531alter domain dom drop constraint domchkgt6 restrict; 532select * from domview; 533 col1 534------ 535 536 5 537(2 rows) 538 539-- cleanup 540drop domain ddef1 restrict; 541drop domain ddef2 restrict; 542drop domain ddef3 restrict; 543drop domain ddef4 restrict; 544drop domain ddef5 restrict; 545drop sequence ddef4_seq; 546-- Test domains over domains 547create domain vchar4 varchar(4); 548create domain dinter vchar4 check (substring(VALUE, 1, 1) = 'x'); 549create domain dtop dinter check (substring(VALUE, 2, 1) = '1'); 550select 'x123'::dtop; 551 dtop 552------ 553 x123 554(1 row) 555 556select 'x1234'::dtop; -- explicit coercion should truncate 557 dtop 558------ 559 x123 560(1 row) 561 562select 'y1234'::dtop; -- fail 563ERROR: value for domain dtop violates check constraint "dinter_check" 564select 'y123'::dtop; -- fail 565ERROR: value for domain dtop violates check constraint "dinter_check" 566select 'yz23'::dtop; -- fail 567ERROR: value for domain dtop violates check constraint "dinter_check" 568select 'xz23'::dtop; -- fail 569ERROR: value for domain dtop violates check constraint "dtop_check" 570create temp table dtest(f1 dtop); 571insert into dtest values('x123'); 572insert into dtest values('x1234'); -- fail, implicit coercion 573ERROR: value too long for type character varying(4) 574insert into dtest values('y1234'); -- fail, implicit coercion 575ERROR: value too long for type character varying(4) 576insert into dtest values('y123'); -- fail 577ERROR: value for domain dtop violates check constraint "dinter_check" 578insert into dtest values('yz23'); -- fail 579ERROR: value for domain dtop violates check constraint "dinter_check" 580insert into dtest values('xz23'); -- fail 581ERROR: value for domain dtop violates check constraint "dtop_check" 582drop table dtest; 583drop domain vchar4 cascade; 584NOTICE: drop cascades to 2 other objects 585DETAIL: drop cascades to type dinter 586drop cascades to type dtop 587-- Make sure that constraints of newly-added domain columns are 588-- enforced correctly, even if there's no default value for the new 589-- column. Per bug #1433 590create domain str_domain as text not null; 591create table domain_test (a int, b int); 592insert into domain_test values (1, 2); 593insert into domain_test values (1, 2); 594-- should fail 595alter table domain_test add column c str_domain; 596ERROR: domain str_domain does not allow null values 597create domain str_domain2 as text check (value <> 'foo') default 'foo'; 598-- should fail 599alter table domain_test add column d str_domain2; 600ERROR: value for domain str_domain2 violates check constraint "str_domain2_check" 601-- Check that domain constraints on prepared statement parameters of 602-- unknown type are enforced correctly. 603create domain pos_int as int4 check (value > 0) not null; 604prepare s1 as select $1::pos_int = 10 as "is_ten"; 605execute s1(10); 606 is_ten 607-------- 608 t 609(1 row) 610 611execute s1(0); -- should fail 612ERROR: value for domain pos_int violates check constraint "pos_int_check" 613execute s1(NULL); -- should fail 614ERROR: domain pos_int does not allow null values 615-- Check that domain constraints on plpgsql function parameters, results, 616-- and local variables are enforced correctly. 617create function doubledecrement(p1 pos_int) returns pos_int as $$ 618declare v pos_int; 619begin 620 return p1; 621end$$ language plpgsql; 622select doubledecrement(3); -- fail because of implicit null assignment 623ERROR: domain pos_int does not allow null values 624CONTEXT: PL/pgSQL function doubledecrement(pos_int) line 3 during statement block local variable initialization 625create or replace function doubledecrement(p1 pos_int) returns pos_int as $$ 626declare v pos_int := 0; 627begin 628 return p1; 629end$$ language plpgsql; 630select doubledecrement(3); -- fail at initialization assignment 631ERROR: value for domain pos_int violates check constraint "pos_int_check" 632CONTEXT: PL/pgSQL function doubledecrement(pos_int) line 3 during statement block local variable initialization 633create or replace function doubledecrement(p1 pos_int) returns pos_int as $$ 634declare v pos_int := 1; 635begin 636 v := p1 - 1; 637 return v - 1; 638end$$ language plpgsql; 639select doubledecrement(null); -- fail before call 640ERROR: domain pos_int does not allow null values 641select doubledecrement(0); -- fail before call 642ERROR: value for domain pos_int violates check constraint "pos_int_check" 643select doubledecrement(1); -- fail at assignment to v 644ERROR: value for domain pos_int violates check constraint "pos_int_check" 645CONTEXT: PL/pgSQL function doubledecrement(pos_int) line 4 at assignment 646select doubledecrement(2); -- fail at return 647ERROR: value for domain pos_int violates check constraint "pos_int_check" 648CONTEXT: PL/pgSQL function doubledecrement(pos_int) while casting return value to function's return type 649select doubledecrement(3); -- good 650 doubledecrement 651----------------- 652 1 653(1 row) 654 655-- Check that ALTER DOMAIN tests columns of derived types 656create domain posint as int4; 657-- Currently, this doesn't work for composite types, but verify it complains 658create type ddtest1 as (f1 posint); 659create table ddtest2(f1 ddtest1); 660insert into ddtest2 values(row(-1)); 661alter domain posint add constraint c1 check(value >= 0); 662ERROR: cannot alter type "posint" because column "ddtest2.f1" uses it 663drop table ddtest2; 664-- Likewise for domains within arrays of composite 665create table ddtest2(f1 ddtest1[]); 666insert into ddtest2 values('{(-1)}'); 667alter domain posint add constraint c1 check(value >= 0); 668ERROR: cannot alter type "posint" because column "ddtest2.f1" uses it 669drop table ddtest2; 670-- Likewise for domains within domains over array of composite 671create domain ddtest1d as ddtest1[]; 672create table ddtest2(f1 ddtest1d); 673insert into ddtest2 values('{(-1)}'); 674alter domain posint add constraint c1 check(value >= 0); 675ERROR: cannot alter type "posint" because column "ddtest2.f1" uses it 676drop table ddtest2; 677drop domain ddtest1d; 678-- Doesn't work for ranges, either 679create type rposint as range (subtype = posint); 680create table ddtest2(f1 rposint); 681insert into ddtest2 values('(-1,3]'); 682alter domain posint add constraint c1 check(value >= 0); 683ERROR: cannot alter type "posint" because column "ddtest2.f1" uses it 684drop table ddtest2; 685drop type rposint; 686alter domain posint add constraint c1 check(value >= 0); 687create domain posint2 as posint check (value % 2 = 0); 688create table ddtest2(f1 posint2); 689insert into ddtest2 values(11); -- fail 690ERROR: value for domain posint2 violates check constraint "posint2_check" 691insert into ddtest2 values(-2); -- fail 692ERROR: value for domain posint2 violates check constraint "c1" 693insert into ddtest2 values(2); 694alter domain posint add constraint c2 check(value >= 10); -- fail 695ERROR: column "f1" of table "ddtest2" contains values that violate the new constraint 696alter domain posint add constraint c2 check(value > 0); -- OK 697drop table ddtest2; 698drop type ddtest1; 699drop domain posint cascade; 700NOTICE: drop cascades to type posint2 701-- 702-- Check enforcement of domain-related typmod in plpgsql (bug #5717) 703-- 704create or replace function array_elem_check(numeric) returns numeric as $$ 705declare 706 x numeric(4,2)[1]; 707begin 708 x[1] := $1; 709 return x[1]; 710end$$ language plpgsql; 711select array_elem_check(121.00); 712ERROR: numeric field overflow 713DETAIL: A field with precision 4, scale 2 must round to an absolute value less than 10^2. 714CONTEXT: PL/pgSQL function array_elem_check(numeric) line 5 at assignment 715select array_elem_check(1.23456); 716 array_elem_check 717------------------ 718 1.23 719(1 row) 720 721create domain mynums as numeric(4,2)[1]; 722create or replace function array_elem_check(numeric) returns numeric as $$ 723declare 724 x mynums; 725begin 726 x[1] := $1; 727 return x[1]; 728end$$ language plpgsql; 729select array_elem_check(121.00); 730ERROR: numeric field overflow 731DETAIL: A field with precision 4, scale 2 must round to an absolute value less than 10^2. 732CONTEXT: PL/pgSQL function array_elem_check(numeric) line 5 at assignment 733select array_elem_check(1.23456); 734 array_elem_check 735------------------ 736 1.23 737(1 row) 738 739create domain mynums2 as mynums; 740create or replace function array_elem_check(numeric) returns numeric as $$ 741declare 742 x mynums2; 743begin 744 x[1] := $1; 745 return x[1]; 746end$$ language plpgsql; 747select array_elem_check(121.00); 748ERROR: numeric field overflow 749DETAIL: A field with precision 4, scale 2 must round to an absolute value less than 10^2. 750CONTEXT: PL/pgSQL function array_elem_check(numeric) line 5 at assignment 751select array_elem_check(1.23456); 752 array_elem_check 753------------------ 754 1.23 755(1 row) 756 757drop function array_elem_check(numeric); 758-- 759-- Check enforcement of array-level domain constraints 760-- 761create domain orderedpair as int[2] check (value[1] < value[2]); 762select array[1,2]::orderedpair; 763 array 764------- 765 {1,2} 766(1 row) 767 768select array[2,1]::orderedpair; -- fail 769ERROR: value for domain orderedpair violates check constraint "orderedpair_check" 770create temp table op (f1 orderedpair); 771insert into op values (array[1,2]); 772insert into op values (array[2,1]); -- fail 773ERROR: value for domain orderedpair violates check constraint "orderedpair_check" 774update op set f1[2] = 3; 775update op set f1[2] = 0; -- fail 776ERROR: value for domain orderedpair violates check constraint "orderedpair_check" 777select * from op; 778 f1 779------- 780 {1,3} 781(1 row) 782 783create or replace function array_elem_check(int) returns int as $$ 784declare 785 x orderedpair := '{1,2}'; 786begin 787 x[2] := $1; 788 return x[2]; 789end$$ language plpgsql; 790select array_elem_check(3); 791 array_elem_check 792------------------ 793 3 794(1 row) 795 796select array_elem_check(-1); 797ERROR: value for domain orderedpair violates check constraint "orderedpair_check" 798CONTEXT: PL/pgSQL function array_elem_check(integer) line 5 at assignment 799drop function array_elem_check(int); 800-- 801-- Check enforcement of changing constraints in plpgsql 802-- 803create domain di as int; 804create function dom_check(int) returns di as $$ 805declare d di; 806begin 807 d := $1; 808 return d; 809end 810$$ language plpgsql immutable; 811select dom_check(0); 812 dom_check 813----------- 814 0 815(1 row) 816 817alter domain di add constraint pos check (value > 0); 818select dom_check(0); -- fail 819ERROR: value for domain di violates check constraint "pos" 820CONTEXT: PL/pgSQL function dom_check(integer) line 4 at assignment 821alter domain di drop constraint pos; 822select dom_check(0); 823 dom_check 824----------- 825 0 826(1 row) 827 828drop function dom_check(int); 829drop domain di; 830-- 831-- Check use of a (non-inline-able) SQL function in a domain constraint; 832-- this has caused issues in the past 833-- 834create function sql_is_distinct_from(anyelement, anyelement) 835returns boolean language sql 836as 'select $1 is distinct from $2 limit 1'; 837create domain inotnull int 838 check (sql_is_distinct_from(value, null)); 839select 1::inotnull; 840 inotnull 841---------- 842 1 843(1 row) 844 845select null::inotnull; 846ERROR: value for domain inotnull violates check constraint "inotnull_check" 847create table dom_table (x inotnull); 848insert into dom_table values ('1'); 849insert into dom_table values (1); 850insert into dom_table values (null); 851ERROR: value for domain inotnull violates check constraint "inotnull_check" 852drop table dom_table; 853drop domain inotnull; 854drop function sql_is_distinct_from(anyelement, anyelement); 855-- 856-- Renaming 857-- 858create domain testdomain1 as int; 859alter domain testdomain1 rename to testdomain2; 860alter type testdomain2 rename to testdomain3; -- alter type also works 861drop domain testdomain3; 862-- 863-- Renaming domain constraints 864-- 865create domain testdomain1 as int constraint unsigned check (value > 0); 866alter domain testdomain1 rename constraint unsigned to unsigned_foo; 867alter domain testdomain1 drop constraint unsigned_foo; 868drop domain testdomain1; 869