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 composites 202create type comptype as (r float8, i float8); 203create domain dcomptype as comptype; 204create table dcomptable (d1 dcomptype unique); 205insert into dcomptable values (row(1,2)::dcomptype); 206insert into dcomptable values (row(3,4)::comptype); 207insert into dcomptable values (row(1,2)::dcomptype); -- fail on uniqueness 208ERROR: duplicate key value violates unique constraint "dcomptable_d1_key" 209DETAIL: Key (d1)=((1,2)) already exists. 210insert into dcomptable (d1.r) values(11); 211select * from dcomptable; 212 d1 213------- 214 (1,2) 215 (3,4) 216 (11,) 217(3 rows) 218 219select (d1).r, (d1).i, (d1).* from dcomptable; 220 r | i | r | i 221----+---+----+--- 222 1 | 2 | 1 | 2 223 3 | 4 | 3 | 4 224 11 | | 11 | 225(3 rows) 226 227update dcomptable set d1.r = (d1).r + 1 where (d1).i > 0; 228select * from dcomptable; 229 d1 230------- 231 (11,) 232 (2,2) 233 (4,4) 234(3 rows) 235 236alter domain dcomptype add constraint c1 check ((value).r <= (value).i); 237alter domain dcomptype add constraint c2 check ((value).r > (value).i); -- fail 238ERROR: column "d1" of table "dcomptable" contains values that violate the new constraint 239select row(2,1)::dcomptype; -- fail 240ERROR: value for domain dcomptype violates check constraint "c1" 241insert into dcomptable values (row(1,2)::comptype); 242insert into dcomptable values (row(2,1)::comptype); -- fail 243ERROR: value for domain dcomptype violates check constraint "c1" 244insert into dcomptable (d1.r) values(99); 245insert into dcomptable (d1.r, d1.i) values(99, 100); 246insert into dcomptable (d1.r, d1.i) values(100, 99); -- fail 247ERROR: value for domain dcomptype violates check constraint "c1" 248update dcomptable set d1.r = (d1).r + 1 where (d1).i > 0; -- fail 249ERROR: value for domain dcomptype violates check constraint "c1" 250update dcomptable set d1.r = (d1).r - 1, d1.i = (d1).i + 1 where (d1).i > 0; 251select * from dcomptable; 252 d1 253---------- 254 (11,) 255 (99,) 256 (1,3) 257 (3,5) 258 (0,3) 259 (98,101) 260(6 rows) 261 262explain (verbose, costs off) 263 update dcomptable set d1.r = (d1).r - 1, d1.i = (d1).i + 1 where (d1).i > 0; 264 QUERY PLAN 265----------------------------------------------------------------------------------------------- 266 Update on public.dcomptable 267 -> Seq Scan on public.dcomptable 268 Output: ROW(((d1).r - '1'::double precision), ((d1).i + '1'::double precision)), ctid 269 Filter: ((dcomptable.d1).i > '0'::double precision) 270(4 rows) 271 272create rule silly as on delete to dcomptable do instead 273 update dcomptable set d1.r = (d1).r - 1, d1.i = (d1).i + 1 where (d1).i > 0; 274\d+ dcomptable 275 Table "public.dcomptable" 276 Column | Type | Collation | Nullable | Default | Storage | Stats target | Description 277--------+-----------+-----------+----------+---------+----------+--------------+------------- 278 d1 | dcomptype | | | | extended | | 279Indexes: 280 "dcomptable_d1_key" UNIQUE CONSTRAINT, btree (d1) 281Rules: 282 silly AS 283 ON DELETE TO dcomptable DO INSTEAD UPDATE dcomptable SET d1.r = (dcomptable.d1).r - 1::double precision, d1.i = (dcomptable.d1).i + 1::double precision 284 WHERE (dcomptable.d1).i > 0::double precision 285 286drop table dcomptable; 287drop type comptype cascade; 288NOTICE: drop cascades to type dcomptype 289-- check altering and dropping columns used by domain constraints 290create type comptype as (r float8, i float8); 291create domain dcomptype as comptype; 292alter domain dcomptype add constraint c1 check ((value).r > 0); 293comment on constraint c1 on domain dcomptype is 'random commentary'; 294select row(0,1)::dcomptype; -- fail 295ERROR: value for domain dcomptype violates check constraint "c1" 296alter type comptype alter attribute r type varchar; -- fail 297ERROR: operator does not exist: character varying > double precision 298HINT: No operator matches the given name and argument types. You might need to add explicit type casts. 299alter type comptype alter attribute r type bigint; 300alter type comptype drop attribute r; -- fail 301ERROR: cannot drop column r of composite type comptype because other objects depend on it 302DETAIL: constraint c1 depends on column r of composite type comptype 303HINT: Use DROP ... CASCADE to drop the dependent objects too. 304alter type comptype drop attribute i; 305select conname, obj_description(oid, 'pg_constraint') from pg_constraint 306 where contypid = 'dcomptype'::regtype; -- check comment is still there 307 conname | obj_description 308---------+------------------- 309 c1 | random commentary 310(1 row) 311 312drop type comptype cascade; 313NOTICE: drop cascades to type dcomptype 314-- Test domains over arrays of composite 315create type comptype as (r float8, i float8); 316create domain dcomptypea as comptype[]; 317create table dcomptable (d1 dcomptypea unique); 318insert into dcomptable values (array[row(1,2)]::dcomptypea); 319insert into dcomptable values (array[row(3,4), row(5,6)]::comptype[]); 320insert into dcomptable values (array[row(7,8)::comptype, row(9,10)::comptype]); 321insert into dcomptable values (array[row(1,2)]::dcomptypea); -- fail on uniqueness 322ERROR: duplicate key value violates unique constraint "dcomptable_d1_key" 323DETAIL: Key (d1)=({"(1,2)"}) already exists. 324insert into dcomptable (d1[1]) values(row(9,10)); 325insert into dcomptable (d1[1].r) values(11); 326select * from dcomptable; 327 d1 328-------------------- 329 {"(1,2)"} 330 {"(3,4)","(5,6)"} 331 {"(7,8)","(9,10)"} 332 {"(9,10)"} 333 {"(11,)"} 334(5 rows) 335 336select d1[2], d1[1].r, d1[1].i from dcomptable; 337 d1 | r | i 338--------+----+---- 339 | 1 | 2 340 (5,6) | 3 | 4 341 (9,10) | 7 | 8 342 | 9 | 10 343 | 11 | 344(5 rows) 345 346update dcomptable set d1[2] = row(d1[2].i, d1[2].r); 347select * from dcomptable; 348 d1 349-------------------- 350 {"(1,2)","(,)"} 351 {"(3,4)","(6,5)"} 352 {"(7,8)","(10,9)"} 353 {"(9,10)","(,)"} 354 {"(11,)","(,)"} 355(5 rows) 356 357update dcomptable set d1[1].r = d1[1].r + 1 where d1[1].i > 0; 358select * from dcomptable; 359 d1 360-------------------- 361 {"(11,)","(,)"} 362 {"(2,2)","(,)"} 363 {"(4,4)","(6,5)"} 364 {"(8,8)","(10,9)"} 365 {"(10,10)","(,)"} 366(5 rows) 367 368alter domain dcomptypea add constraint c1 check (value[1].r <= value[1].i); 369alter domain dcomptypea add constraint c2 check (value[1].r > value[1].i); -- fail 370ERROR: column "d1" of table "dcomptable" contains values that violate the new constraint 371select array[row(2,1)]::dcomptypea; -- fail 372ERROR: value for domain dcomptypea violates check constraint "c1" 373insert into dcomptable values (array[row(1,2)]::comptype[]); 374insert into dcomptable values (array[row(2,1)]::comptype[]); -- fail 375ERROR: value for domain dcomptypea violates check constraint "c1" 376insert into dcomptable (d1[1].r) values(99); 377insert into dcomptable (d1[1].r, d1[1].i) values(99, 100); 378insert into dcomptable (d1[1].r, d1[1].i) values(100, 99); -- fail 379ERROR: value for domain dcomptypea violates check constraint "c1" 380update dcomptable set d1[1].r = d1[1].r + 1 where d1[1].i > 0; -- fail 381ERROR: value for domain dcomptypea violates check constraint "c1" 382update dcomptable set d1[1].r = d1[1].r - 1, d1[1].i = d1[1].i + 1 383 where d1[1].i > 0; 384select * from dcomptable; 385 d1 386-------------------- 387 {"(11,)","(,)"} 388 {"(99,)"} 389 {"(1,3)","(,)"} 390 {"(3,5)","(6,5)"} 391 {"(7,9)","(10,9)"} 392 {"(9,11)","(,)"} 393 {"(0,3)"} 394 {"(98,101)"} 395(8 rows) 396 397explain (verbose, costs off) 398 update dcomptable set d1[1].r = d1[1].r - 1, d1[1].i = d1[1].i + 1 399 where d1[1].i > 0; 400 QUERY PLAN 401---------------------------------------------------------------------------------------------------------------- 402 Update on public.dcomptable 403 -> Seq Scan on public.dcomptable 404 Output: (d1[1].r := (d1[1].r - '1'::double precision))[1].i := (d1[1].i + '1'::double precision), ctid 405 Filter: (dcomptable.d1[1].i > '0'::double precision) 406(4 rows) 407 408create rule silly as on delete to dcomptable do instead 409 update dcomptable set d1[1].r = d1[1].r - 1, d1[1].i = d1[1].i + 1 410 where d1[1].i > 0; 411\d+ dcomptable 412 Table "public.dcomptable" 413 Column | Type | Collation | Nullable | Default | Storage | Stats target | Description 414--------+------------+-----------+----------+---------+----------+--------------+------------- 415 d1 | dcomptypea | | | | extended | | 416Indexes: 417 "dcomptable_d1_key" UNIQUE CONSTRAINT, btree (d1) 418Rules: 419 silly AS 420 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 421 WHERE dcomptable.d1[1].i > 0::double precision 422 423drop table dcomptable; 424drop type comptype cascade; 425NOTICE: drop cascades to type dcomptypea 426-- Test arrays over domains 427create domain posint as int check (value > 0); 428create table pitable (f1 posint[]); 429insert into pitable values(array[42]); 430insert into pitable values(array[-1]); -- fail 431ERROR: value for domain posint violates check constraint "posint_check" 432insert into pitable values('{0}'); -- fail 433ERROR: value for domain posint violates check constraint "posint_check" 434LINE 1: insert into pitable values('{0}'); 435 ^ 436update pitable set f1[1] = f1[1] + 1; 437update pitable set f1[1] = 0; -- fail 438ERROR: value for domain posint violates check constraint "posint_check" 439select * from pitable; 440 f1 441------ 442 {43} 443(1 row) 444 445drop table pitable; 446create domain vc4 as varchar(4); 447create table vc4table (f1 vc4[]); 448insert into vc4table values(array['too long']); -- fail 449ERROR: value too long for type character varying(4) 450insert into vc4table values(array['too long']::vc4[]); -- cast truncates 451select * from vc4table; 452 f1 453---------- 454 {"too "} 455(1 row) 456 457drop table vc4table; 458drop type vc4; 459-- You can sort of fake arrays-of-arrays by putting a domain in between 460create domain dposinta as posint[]; 461create table dposintatable (f1 dposinta[]); 462insert into dposintatable values(array[array[42]]); -- fail 463ERROR: column "f1" is of type dposinta[] but expression is of type integer[] 464LINE 1: insert into dposintatable values(array[array[42]]); 465 ^ 466HINT: You will need to rewrite or cast the expression. 467insert into dposintatable values(array[array[42]::posint[]]); -- still fail 468ERROR: column "f1" is of type dposinta[] but expression is of type posint[] 469LINE 1: insert into dposintatable values(array[array[42]::posint[]])... 470 ^ 471HINT: You will need to rewrite or cast the expression. 472insert into dposintatable values(array[array[42]::dposinta]); -- but this works 473select f1, f1[1], (f1[1])[1] from dposintatable; 474 f1 | f1 | f1 475----------+------+---- 476 {"{42}"} | {42} | 42 477(1 row) 478 479select pg_typeof(f1) from dposintatable; 480 pg_typeof 481------------ 482 dposinta[] 483(1 row) 484 485select pg_typeof(f1[1]) from dposintatable; 486 pg_typeof 487----------- 488 dposinta 489(1 row) 490 491select pg_typeof(f1[1][1]) from dposintatable; 492 pg_typeof 493----------- 494 dposinta 495(1 row) 496 497select pg_typeof((f1[1])[1]) from dposintatable; 498 pg_typeof 499----------- 500 posint 501(1 row) 502 503update dposintatable set f1[2] = array[99]; 504select f1, f1[1], (f1[2])[1] from dposintatable; 505 f1 | f1 | f1 506-----------------+------+---- 507 {"{42}","{99}"} | {42} | 99 508(1 row) 509 510-- it'd be nice if you could do something like this, but for now you can't: 511update dposintatable set f1[2][1] = array[97]; 512ERROR: wrong number of array subscripts 513-- maybe someday we can make this syntax work: 514update dposintatable set (f1[2])[1] = array[98]; 515ERROR: syntax error at or near "[" 516LINE 1: update dposintatable set (f1[2])[1] = array[98]; 517 ^ 518drop table dposintatable; 519drop domain posint cascade; 520NOTICE: drop cascades to type dposinta 521-- Test arrays over domains of composite 522create type comptype as (cf1 int, cf2 int); 523create domain dcomptype as comptype check ((value).cf1 > 0); 524create table dcomptable (f1 dcomptype[]); 525insert into dcomptable values (null); 526update dcomptable set f1[1].cf2 = 5; 527table dcomptable; 528 f1 529---------- 530 {"(,5)"} 531(1 row) 532 533update dcomptable set f1[1].cf1 = -1; -- fail 534ERROR: value for domain dcomptype violates check constraint "dcomptype_check" 535update dcomptable set f1[1].cf1 = 1; 536table dcomptable; 537 f1 538----------- 539 {"(1,5)"} 540(1 row) 541 542drop table dcomptable; 543drop type comptype cascade; 544NOTICE: drop cascades to type dcomptype 545-- Test not-null restrictions 546create domain dnotnull varchar(15) NOT NULL; 547create domain dnull varchar(15); 548create domain dcheck varchar(15) NOT NULL CHECK (VALUE = 'a' OR VALUE = 'c' OR VALUE = 'd'); 549create table nulltest 550 ( col1 dnotnull 551 , col2 dnotnull NULL -- NOT NULL in the domain cannot be overridden 552 , col3 dnull NOT NULL 553 , col4 dnull 554 , col5 dcheck CHECK (col5 IN ('c', 'd')) 555 ); 556INSERT INTO nulltest DEFAULT VALUES; 557ERROR: domain dnotnull does not allow null values 558INSERT INTO nulltest values ('a', 'b', 'c', 'd', 'c'); -- Good 559insert into nulltest values ('a', 'b', 'c', 'd', NULL); 560ERROR: domain dcheck does not allow null values 561insert into nulltest values ('a', 'b', 'c', 'd', 'a'); 562ERROR: new row for relation "nulltest" violates check constraint "nulltest_col5_check" 563DETAIL: Failing row contains (a, b, c, d, a). 564INSERT INTO nulltest values (NULL, 'b', 'c', 'd', 'd'); 565ERROR: domain dnotnull does not allow null values 566INSERT INTO nulltest values ('a', NULL, 'c', 'd', 'c'); 567ERROR: domain dnotnull does not allow null values 568INSERT INTO nulltest values ('a', 'b', NULL, 'd', 'c'); 569ERROR: null value in column "col3" of relation "nulltest" violates not-null constraint 570DETAIL: Failing row contains (a, b, null, d, c). 571INSERT INTO nulltest values ('a', 'b', 'c', NULL, 'd'); -- Good 572-- Test copy 573COPY nulltest FROM stdin; --fail 574ERROR: null value in column "col3" of relation "nulltest" violates not-null constraint 575DETAIL: Failing row contains (a, b, null, d, d). 576CONTEXT: COPY nulltest, line 1: "a b \N d d" 577COPY nulltest FROM stdin; --fail 578ERROR: domain dcheck does not allow null values 579CONTEXT: COPY nulltest, line 1, column col5: null input 580-- Last row is bad 581COPY nulltest FROM stdin; 582ERROR: new row for relation "nulltest" violates check constraint "nulltest_col5_check" 583DETAIL: Failing row contains (a, b, c, null, a). 584CONTEXT: COPY nulltest, line 3: "a b c \N a" 585select * from nulltest; 586 col1 | col2 | col3 | col4 | col5 587------+------+------+------+------ 588 a | b | c | d | c 589 a | b | c | | d 590(2 rows) 591 592-- Test out coerced (casted) constraints 593SELECT cast('1' as dnotnull); 594 dnotnull 595---------- 596 1 597(1 row) 598 599SELECT cast(NULL as dnotnull); -- fail 600ERROR: domain dnotnull does not allow null values 601SELECT cast(cast(NULL as dnull) as dnotnull); -- fail 602ERROR: domain dnotnull does not allow null values 603SELECT cast(col4 as dnotnull) from nulltest; -- fail 604ERROR: domain dnotnull does not allow null values 605-- cleanup 606drop table nulltest; 607drop domain dnotnull restrict; 608drop domain dnull restrict; 609drop domain dcheck restrict; 610create domain ddef1 int4 DEFAULT 3; 611create domain ddef2 oid DEFAULT '12'; 612-- Type mixing, function returns int8 613create domain ddef3 text DEFAULT 5; 614create sequence ddef4_seq; 615create domain ddef4 int4 DEFAULT nextval('ddef4_seq'); 616create domain ddef5 numeric(8,2) NOT NULL DEFAULT '12.12'; 617create table defaulttest 618 ( col1 ddef1 619 , col2 ddef2 620 , col3 ddef3 621 , col4 ddef4 PRIMARY KEY 622 , col5 ddef1 NOT NULL DEFAULT NULL 623 , col6 ddef2 DEFAULT '88' 624 , col7 ddef4 DEFAULT 8000 625 , col8 ddef5 626 ); 627insert into defaulttest(col4) values(0); -- fails, col5 defaults to null 628ERROR: null value in column "col5" of relation "defaulttest" violates not-null constraint 629DETAIL: Failing row contains (3, 12, 5, 0, null, 88, 8000, 12.12). 630alter table defaulttest alter column col5 drop default; 631insert into defaulttest default values; -- succeeds, inserts domain default 632-- We used to treat SET DEFAULT NULL as equivalent to DROP DEFAULT; wrong 633alter table defaulttest alter column col5 set default null; 634insert into defaulttest(col4) values(0); -- fails 635ERROR: null value in column "col5" of relation "defaulttest" violates not-null constraint 636DETAIL: Failing row contains (3, 12, 5, 0, null, 88, 8000, 12.12). 637alter table defaulttest alter column col5 drop default; 638insert into defaulttest default values; 639insert into defaulttest default values; 640-- Test defaults with copy 641COPY defaulttest(col5) FROM stdin; 642select * from defaulttest; 643 col1 | col2 | col3 | col4 | col5 | col6 | col7 | col8 644------+------+------+------+------+------+------+------- 645 3 | 12 | 5 | 1 | 3 | 88 | 8000 | 12.12 646 3 | 12 | 5 | 2 | 3 | 88 | 8000 | 12.12 647 3 | 12 | 5 | 3 | 3 | 88 | 8000 | 12.12 648 3 | 12 | 5 | 4 | 42 | 88 | 8000 | 12.12 649(4 rows) 650 651drop table defaulttest cascade; 652-- Test ALTER DOMAIN .. NOT NULL 653create domain dnotnulltest integer; 654create table domnotnull 655( col1 dnotnulltest 656, col2 dnotnulltest 657); 658insert into domnotnull default values; 659alter domain dnotnulltest set not null; -- fails 660ERROR: column "col1" of table "domnotnull" contains null values 661update domnotnull set col1 = 5; 662alter domain dnotnulltest set not null; -- fails 663ERROR: column "col2" of table "domnotnull" contains null values 664update domnotnull set col2 = 6; 665alter domain dnotnulltest set not null; 666update domnotnull set col1 = null; -- fails 667ERROR: domain dnotnulltest does not allow null values 668alter domain dnotnulltest drop not null; 669update domnotnull set col1 = null; 670drop domain dnotnulltest cascade; 671NOTICE: drop cascades to 2 other objects 672DETAIL: drop cascades to column col2 of table domnotnull 673drop cascades to column col1 of table domnotnull 674-- Test ALTER DOMAIN .. DEFAULT .. 675create table domdeftest (col1 ddef1); 676insert into domdeftest default values; 677select * from domdeftest; 678 col1 679------ 680 3 681(1 row) 682 683alter domain ddef1 set default '42'; 684insert into domdeftest default values; 685select * from domdeftest; 686 col1 687------ 688 3 689 42 690(2 rows) 691 692alter domain ddef1 drop default; 693insert into domdeftest default values; 694select * from domdeftest; 695 col1 696------ 697 3 698 42 699 700(3 rows) 701 702drop table domdeftest; 703-- Test ALTER DOMAIN .. CONSTRAINT .. 704create domain con as integer; 705create table domcontest (col1 con); 706insert into domcontest values (1); 707insert into domcontest values (2); 708alter domain con add constraint t check (VALUE < 1); -- fails 709ERROR: column "col1" of table "domcontest" contains values that violate the new constraint 710alter domain con add constraint t check (VALUE < 34); 711alter domain con add check (VALUE > 0); 712insert into domcontest values (-5); -- fails 713ERROR: value for domain con violates check constraint "con_check" 714insert into domcontest values (42); -- fails 715ERROR: value for domain con violates check constraint "t" 716insert into domcontest values (5); 717alter domain con drop constraint t; 718insert into domcontest values (-5); --fails 719ERROR: value for domain con violates check constraint "con_check" 720insert into domcontest values (42); 721alter domain con drop constraint nonexistent; 722ERROR: constraint "nonexistent" of domain "con" does not exist 723alter domain con drop constraint if exists nonexistent; 724NOTICE: constraint "nonexistent" of domain "con" does not exist, skipping 725-- Test ALTER DOMAIN .. CONSTRAINT .. NOT VALID 726create domain things AS INT; 727CREATE TABLE thethings (stuff things); 728INSERT INTO thethings (stuff) VALUES (55); 729ALTER DOMAIN things ADD CONSTRAINT meow CHECK (VALUE < 11); 730ERROR: column "stuff" of table "thethings" contains values that violate the new constraint 731ALTER DOMAIN things ADD CONSTRAINT meow CHECK (VALUE < 11) NOT VALID; 732ALTER DOMAIN things VALIDATE CONSTRAINT meow; 733ERROR: column "stuff" of table "thethings" contains values that violate the new constraint 734UPDATE thethings SET stuff = 10; 735ALTER DOMAIN things VALIDATE CONSTRAINT meow; 736-- Confirm ALTER DOMAIN with RULES. 737create table domtab (col1 integer); 738create domain dom as integer; 739create view domview as select cast(col1 as dom) from domtab; 740insert into domtab (col1) values (null); 741insert into domtab (col1) values (5); 742select * from domview; 743 col1 744------ 745 746 5 747(2 rows) 748 749alter domain dom set not null; 750select * from domview; -- fail 751ERROR: domain dom does not allow null values 752alter domain dom drop not null; 753select * from domview; 754 col1 755------ 756 757 5 758(2 rows) 759 760alter domain dom add constraint domchkgt6 check(value > 6); 761select * from domview; --fail 762ERROR: value for domain dom violates check constraint "domchkgt6" 763alter domain dom drop constraint domchkgt6 restrict; 764select * from domview; 765 col1 766------ 767 768 5 769(2 rows) 770 771-- cleanup 772drop domain ddef1 restrict; 773drop domain ddef2 restrict; 774drop domain ddef3 restrict; 775drop domain ddef4 restrict; 776drop domain ddef5 restrict; 777drop sequence ddef4_seq; 778-- Test domains over domains 779create domain vchar4 varchar(4); 780create domain dinter vchar4 check (substring(VALUE, 1, 1) = 'x'); 781create domain dtop dinter check (substring(VALUE, 2, 1) = '1'); 782select 'x123'::dtop; 783 dtop 784------ 785 x123 786(1 row) 787 788select 'x1234'::dtop; -- explicit coercion should truncate 789 dtop 790------ 791 x123 792(1 row) 793 794select 'y1234'::dtop; -- fail 795ERROR: value for domain dtop violates check constraint "dinter_check" 796select 'y123'::dtop; -- fail 797ERROR: value for domain dtop violates check constraint "dinter_check" 798select 'yz23'::dtop; -- fail 799ERROR: value for domain dtop violates check constraint "dinter_check" 800select 'xz23'::dtop; -- fail 801ERROR: value for domain dtop violates check constraint "dtop_check" 802create temp table dtest(f1 dtop); 803insert into dtest values('x123'); 804insert into dtest values('x1234'); -- fail, implicit coercion 805ERROR: value too long for type character varying(4) 806insert into dtest values('y1234'); -- fail, implicit coercion 807ERROR: value too long for type character varying(4) 808insert into dtest values('y123'); -- fail 809ERROR: value for domain dtop violates check constraint "dinter_check" 810insert into dtest values('yz23'); -- fail 811ERROR: value for domain dtop violates check constraint "dinter_check" 812insert into dtest values('xz23'); -- fail 813ERROR: value for domain dtop violates check constraint "dtop_check" 814drop table dtest; 815drop domain vchar4 cascade; 816NOTICE: drop cascades to 2 other objects 817DETAIL: drop cascades to type dinter 818drop cascades to type dtop 819-- Make sure that constraints of newly-added domain columns are 820-- enforced correctly, even if there's no default value for the new 821-- column. Per bug #1433 822create domain str_domain as text not null; 823create table domain_test (a int, b int); 824insert into domain_test values (1, 2); 825insert into domain_test values (1, 2); 826-- should fail 827alter table domain_test add column c str_domain; 828ERROR: domain str_domain does not allow null values 829create domain str_domain2 as text check (value <> 'foo') default 'foo'; 830-- should fail 831alter table domain_test add column d str_domain2; 832ERROR: value for domain str_domain2 violates check constraint "str_domain2_check" 833-- Check that domain constraints on prepared statement parameters of 834-- unknown type are enforced correctly. 835create domain pos_int as int4 check (value > 0) not null; 836prepare s1 as select $1::pos_int = 10 as "is_ten"; 837execute s1(10); 838 is_ten 839-------- 840 t 841(1 row) 842 843execute s1(0); -- should fail 844ERROR: value for domain pos_int violates check constraint "pos_int_check" 845execute s1(NULL); -- should fail 846ERROR: domain pos_int does not allow null values 847-- Check that domain constraints on plpgsql function parameters, results, 848-- and local variables are enforced correctly. 849create function doubledecrement(p1 pos_int) returns pos_int as $$ 850declare v pos_int; 851begin 852 return p1; 853end$$ language plpgsql; 854select doubledecrement(3); -- fail because of implicit null assignment 855ERROR: domain pos_int does not allow null values 856CONTEXT: PL/pgSQL function doubledecrement(pos_int) line 3 during statement block local variable initialization 857create or replace function doubledecrement(p1 pos_int) returns pos_int as $$ 858declare v pos_int := 0; 859begin 860 return p1; 861end$$ language plpgsql; 862select doubledecrement(3); -- fail at initialization assignment 863ERROR: value for domain pos_int violates check constraint "pos_int_check" 864CONTEXT: PL/pgSQL function doubledecrement(pos_int) line 3 during statement block local variable initialization 865create or replace function doubledecrement(p1 pos_int) returns pos_int as $$ 866declare v pos_int := 1; 867begin 868 v := p1 - 1; 869 return v - 1; 870end$$ language plpgsql; 871select doubledecrement(null); -- fail before call 872ERROR: domain pos_int does not allow null values 873select doubledecrement(0); -- fail before call 874ERROR: value for domain pos_int violates check constraint "pos_int_check" 875select doubledecrement(1); -- fail at assignment to v 876ERROR: value for domain pos_int violates check constraint "pos_int_check" 877CONTEXT: PL/pgSQL function doubledecrement(pos_int) line 4 at assignment 878select doubledecrement(2); -- fail at return 879ERROR: value for domain pos_int violates check constraint "pos_int_check" 880CONTEXT: PL/pgSQL function doubledecrement(pos_int) while casting return value to function's return type 881select doubledecrement(3); -- good 882 doubledecrement 883----------------- 884 1 885(1 row) 886 887-- Check that ALTER DOMAIN tests columns of derived types 888create domain posint as int4; 889-- Currently, this doesn't work for composite types, but verify it complains 890create type ddtest1 as (f1 posint); 891create table ddtest2(f1 ddtest1); 892insert into ddtest2 values(row(-1)); 893alter domain posint add constraint c1 check(value >= 0); 894ERROR: cannot alter type "posint" because column "ddtest2.f1" uses it 895drop table ddtest2; 896-- Likewise for domains within arrays of composite 897create table ddtest2(f1 ddtest1[]); 898insert into ddtest2 values('{(-1)}'); 899alter domain posint add constraint c1 check(value >= 0); 900ERROR: cannot alter type "posint" because column "ddtest2.f1" uses it 901drop table ddtest2; 902-- Likewise for domains within domains over composite 903create domain ddtest1d as ddtest1; 904create table ddtest2(f1 ddtest1d); 905insert into ddtest2 values('(-1)'); 906alter domain posint add constraint c1 check(value >= 0); 907ERROR: cannot alter type "posint" because column "ddtest2.f1" uses it 908drop table ddtest2; 909drop domain ddtest1d; 910-- Likewise for domains within domains over array of composite 911create domain ddtest1d as ddtest1[]; 912create table ddtest2(f1 ddtest1d); 913insert into ddtest2 values('{(-1)}'); 914alter domain posint add constraint c1 check(value >= 0); 915ERROR: cannot alter type "posint" because column "ddtest2.f1" uses it 916drop table ddtest2; 917drop domain ddtest1d; 918-- Doesn't work for ranges, either 919create type rposint as range (subtype = posint); 920create table ddtest2(f1 rposint); 921insert into ddtest2 values('(-1,3]'); 922alter domain posint add constraint c1 check(value >= 0); 923ERROR: cannot alter type "posint" because column "ddtest2.f1" uses it 924drop table ddtest2; 925drop type rposint; 926alter domain posint add constraint c1 check(value >= 0); 927create domain posint2 as posint check (value % 2 = 0); 928create table ddtest2(f1 posint2); 929insert into ddtest2 values(11); -- fail 930ERROR: value for domain posint2 violates check constraint "posint2_check" 931insert into ddtest2 values(-2); -- fail 932ERROR: value for domain posint2 violates check constraint "c1" 933insert into ddtest2 values(2); 934alter domain posint add constraint c2 check(value >= 10); -- fail 935ERROR: column "f1" of table "ddtest2" contains values that violate the new constraint 936alter domain posint add constraint c2 check(value > 0); -- OK 937drop table ddtest2; 938drop type ddtest1; 939drop domain posint cascade; 940NOTICE: drop cascades to type posint2 941-- 942-- Check enforcement of domain-related typmod in plpgsql (bug #5717) 943-- 944create or replace function array_elem_check(numeric) returns numeric as $$ 945declare 946 x numeric(4,2)[1]; 947begin 948 x[1] := $1; 949 return x[1]; 950end$$ language plpgsql; 951select array_elem_check(121.00); 952ERROR: numeric field overflow 953DETAIL: A field with precision 4, scale 2 must round to an absolute value less than 10^2. 954CONTEXT: PL/pgSQL function array_elem_check(numeric) line 5 at assignment 955select array_elem_check(1.23456); 956 array_elem_check 957------------------ 958 1.23 959(1 row) 960 961create domain mynums as numeric(4,2)[1]; 962create or replace function array_elem_check(numeric) returns numeric as $$ 963declare 964 x mynums; 965begin 966 x[1] := $1; 967 return x[1]; 968end$$ language plpgsql; 969select array_elem_check(121.00); 970ERROR: numeric field overflow 971DETAIL: A field with precision 4, scale 2 must round to an absolute value less than 10^2. 972CONTEXT: PL/pgSQL function array_elem_check(numeric) line 5 at assignment 973select array_elem_check(1.23456); 974 array_elem_check 975------------------ 976 1.23 977(1 row) 978 979create domain mynums2 as mynums; 980create or replace function array_elem_check(numeric) returns numeric as $$ 981declare 982 x mynums2; 983begin 984 x[1] := $1; 985 return x[1]; 986end$$ language plpgsql; 987select array_elem_check(121.00); 988ERROR: numeric field overflow 989DETAIL: A field with precision 4, scale 2 must round to an absolute value less than 10^2. 990CONTEXT: PL/pgSQL function array_elem_check(numeric) line 5 at assignment 991select array_elem_check(1.23456); 992 array_elem_check 993------------------ 994 1.23 995(1 row) 996 997drop function array_elem_check(numeric); 998-- 999-- Check enforcement of array-level domain constraints 1000-- 1001create domain orderedpair as int[2] check (value[1] < value[2]); 1002select array[1,2]::orderedpair; 1003 array 1004------- 1005 {1,2} 1006(1 row) 1007 1008select array[2,1]::orderedpair; -- fail 1009ERROR: value for domain orderedpair violates check constraint "orderedpair_check" 1010create temp table op (f1 orderedpair); 1011insert into op values (array[1,2]); 1012insert into op values (array[2,1]); -- fail 1013ERROR: value for domain orderedpair violates check constraint "orderedpair_check" 1014update op set f1[2] = 3; 1015update op set f1[2] = 0; -- fail 1016ERROR: value for domain orderedpair violates check constraint "orderedpair_check" 1017select * from op; 1018 f1 1019------- 1020 {1,3} 1021(1 row) 1022 1023create or replace function array_elem_check(int) returns int as $$ 1024declare 1025 x orderedpair := '{1,2}'; 1026begin 1027 x[2] := $1; 1028 return x[2]; 1029end$$ language plpgsql; 1030select array_elem_check(3); 1031 array_elem_check 1032------------------ 1033 3 1034(1 row) 1035 1036select array_elem_check(-1); 1037ERROR: value for domain orderedpair violates check constraint "orderedpair_check" 1038CONTEXT: PL/pgSQL function array_elem_check(integer) line 5 at assignment 1039drop function array_elem_check(int); 1040-- 1041-- Check enforcement of changing constraints in plpgsql 1042-- 1043create domain di as int; 1044create function dom_check(int) returns di as $$ 1045declare d di; 1046begin 1047 d := $1::di; 1048 return d; 1049end 1050$$ language plpgsql immutable; 1051select dom_check(0); 1052 dom_check 1053----------- 1054 0 1055(1 row) 1056 1057alter domain di add constraint pos check (value > 0); 1058select dom_check(0); -- fail 1059ERROR: value for domain di violates check constraint "pos" 1060CONTEXT: PL/pgSQL function dom_check(integer) line 4 at assignment 1061alter domain di drop constraint pos; 1062select dom_check(0); 1063 dom_check 1064----------- 1065 0 1066(1 row) 1067 1068-- implicit cast during assignment is a separate code path, test that too 1069create or replace function dom_check(int) returns di as $$ 1070declare d di; 1071begin 1072 d := $1; 1073 return d; 1074end 1075$$ language plpgsql immutable; 1076select dom_check(0); 1077 dom_check 1078----------- 1079 0 1080(1 row) 1081 1082alter domain di add constraint pos check (value > 0); 1083select dom_check(0); -- fail 1084ERROR: value for domain di violates check constraint "pos" 1085CONTEXT: PL/pgSQL function dom_check(integer) line 4 at assignment 1086alter domain di drop constraint pos; 1087select dom_check(0); 1088 dom_check 1089----------- 1090 0 1091(1 row) 1092 1093drop function dom_check(int); 1094drop domain di; 1095-- 1096-- Check use of a (non-inline-able) SQL function in a domain constraint; 1097-- this has caused issues in the past 1098-- 1099create function sql_is_distinct_from(anyelement, anyelement) 1100returns boolean language sql 1101as 'select $1 is distinct from $2 limit 1'; 1102create domain inotnull int 1103 check (sql_is_distinct_from(value, null)); 1104select 1::inotnull; 1105 inotnull 1106---------- 1107 1 1108(1 row) 1109 1110select null::inotnull; 1111ERROR: value for domain inotnull violates check constraint "inotnull_check" 1112create table dom_table (x inotnull); 1113insert into dom_table values ('1'); 1114insert into dom_table values (1); 1115insert into dom_table values (null); 1116ERROR: value for domain inotnull violates check constraint "inotnull_check" 1117drop table dom_table; 1118drop domain inotnull; 1119drop function sql_is_distinct_from(anyelement, anyelement); 1120-- 1121-- Renaming 1122-- 1123create domain testdomain1 as int; 1124alter domain testdomain1 rename to testdomain2; 1125alter type testdomain2 rename to testdomain3; -- alter type also works 1126drop domain testdomain3; 1127-- 1128-- Renaming domain constraints 1129-- 1130create domain testdomain1 as int constraint unsigned check (value > 0); 1131alter domain testdomain1 rename constraint unsigned to unsigned_foo; 1132alter domain testdomain1 drop constraint unsigned_foo; 1133drop domain testdomain1; 1134