summaryrefslogtreecommitdiffstats
path: root/src/test/regress/expected/domain.out
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/regress/expected/domain.out')
-rw-r--r--src/test/regress/expected/domain.out1159
1 files changed, 1159 insertions, 0 deletions
diff --git a/src/test/regress/expected/domain.out b/src/test/regress/expected/domain.out
new file mode 100644
index 0000000..46a2635
--- /dev/null
+++ b/src/test/regress/expected/domain.out
@@ -0,0 +1,1159 @@
+--
+-- Test domains.
+--
+-- Test Comment / Drop
+create domain domaindroptest int4;
+comment on domain domaindroptest is 'About to drop this..';
+create domain dependenttypetest domaindroptest;
+-- fail because of dependent type
+drop domain domaindroptest;
+ERROR: cannot drop type domaindroptest because other objects depend on it
+DETAIL: type dependenttypetest depends on type domaindroptest
+HINT: Use DROP ... CASCADE to drop the dependent objects too.
+drop domain domaindroptest cascade;
+NOTICE: drop cascades to type dependenttypetest
+-- this should fail because already gone
+drop domain domaindroptest cascade;
+ERROR: type "domaindroptest" does not exist
+-- Test domain input.
+-- Note: the point of checking both INSERT and COPY FROM is that INSERT
+-- exercises CoerceToDomain while COPY exercises domain_in.
+create domain domainvarchar varchar(5);
+create domain domainnumeric numeric(8,2);
+create domain domainint4 int4;
+create domain domaintext text;
+-- Test explicit coercions --- these should succeed (and truncate)
+SELECT cast('123456' as domainvarchar);
+ domainvarchar
+---------------
+ 12345
+(1 row)
+
+SELECT cast('12345' as domainvarchar);
+ domainvarchar
+---------------
+ 12345
+(1 row)
+
+-- Test tables using domains
+create table basictest
+ ( testint4 domainint4
+ , testtext domaintext
+ , testvarchar domainvarchar
+ , testnumeric domainnumeric
+ );
+INSERT INTO basictest values ('88', 'haha', 'short', '123.12'); -- Good
+INSERT INTO basictest values ('88', 'haha', 'short text', '123.12'); -- Bad varchar
+ERROR: value too long for type character varying(5)
+INSERT INTO basictest values ('88', 'haha', 'short', '123.1212'); -- Truncate numeric
+-- Test copy
+COPY basictest (testvarchar) FROM stdin; -- fail
+ERROR: value too long for type character varying(5)
+CONTEXT: COPY basictest, line 1, column testvarchar: "notsoshorttext"
+COPY basictest (testvarchar) FROM stdin;
+select * from basictest;
+ testint4 | testtext | testvarchar | testnumeric
+----------+----------+-------------+-------------
+ 88 | haha | short | 123.12
+ 88 | haha | short | 123.12
+ | | short |
+(3 rows)
+
+-- check that domains inherit operations from base types
+select testtext || testvarchar as concat, testnumeric + 42 as sum
+from basictest;
+ concat | sum
+-----------+--------
+ hahashort | 165.12
+ hahashort | 165.12
+ |
+(3 rows)
+
+-- check that union/case/coalesce type resolution handles domains properly
+select pg_typeof(coalesce(4::domainint4, 7));
+ pg_typeof
+-----------
+ integer
+(1 row)
+
+select pg_typeof(coalesce(4::domainint4, 7::domainint4));
+ pg_typeof
+------------
+ domainint4
+(1 row)
+
+drop table basictest;
+drop domain domainvarchar restrict;
+drop domain domainnumeric restrict;
+drop domain domainint4 restrict;
+drop domain domaintext;
+-- Test domains over array types
+create domain domainint4arr int4[1];
+create domain domainchar4arr varchar(4)[2][3];
+create table domarrtest
+ ( testint4arr domainint4arr
+ , testchar4arr domainchar4arr
+ );
+INSERT INTO domarrtest values ('{2,2}', '{{"a","b"},{"c","d"}}');
+INSERT INTO domarrtest values ('{{2,2},{2,2}}', '{{"a","b"}}');
+INSERT INTO domarrtest values ('{2,2}', '{{"a","b"},{"c","d"},{"e","f"}}');
+INSERT INTO domarrtest values ('{2,2}', '{{"a"},{"c"}}');
+INSERT INTO domarrtest values (NULL, '{{"a","b","c"},{"d","e","f"}}');
+INSERT INTO domarrtest values (NULL, '{{"toolong","b","c"},{"d","e","f"}}');
+ERROR: value too long for type character varying(4)
+INSERT INTO domarrtest (testint4arr[1], testint4arr[3]) values (11,22);
+select * from domarrtest;
+ testint4arr | testchar4arr
+---------------+---------------------
+ {2,2} | {{a,b},{c,d}}
+ {{2,2},{2,2}} | {{a,b}}
+ {2,2} | {{a,b},{c,d},{e,f}}
+ {2,2} | {{a},{c}}
+ | {{a,b,c},{d,e,f}}
+ {11,NULL,22} |
+(6 rows)
+
+select testint4arr[1], testchar4arr[2:2] from domarrtest;
+ testint4arr | testchar4arr
+-------------+--------------
+ 2 | {{c,d}}
+ | {}
+ 2 | {{c,d}}
+ 2 | {{c}}
+ | {{d,e,f}}
+ 11 |
+(6 rows)
+
+select array_dims(testint4arr), array_dims(testchar4arr) from domarrtest;
+ array_dims | array_dims
+------------+------------
+ [1:2] | [1:2][1:2]
+ [1:2][1:2] | [1:1][1:2]
+ [1:2] | [1:3][1:2]
+ [1:2] | [1:2][1:1]
+ | [1:2][1:3]
+ [1:3] |
+(6 rows)
+
+COPY domarrtest FROM stdin;
+COPY domarrtest FROM stdin; -- fail
+ERROR: value too long for type character varying(4)
+CONTEXT: COPY domarrtest, line 1, column testchar4arr: "{qwerty,w,e}"
+select * from domarrtest;
+ testint4arr | testchar4arr
+---------------+---------------------
+ {2,2} | {{a,b},{c,d}}
+ {{2,2},{2,2}} | {{a,b}}
+ {2,2} | {{a,b},{c,d},{e,f}}
+ {2,2} | {{a},{c}}
+ | {{a,b,c},{d,e,f}}
+ {11,NULL,22} |
+ {3,4} | {q,w,e}
+ |
+(8 rows)
+
+update domarrtest set
+ testint4arr[1] = testint4arr[1] + 1,
+ testint4arr[3] = testint4arr[3] - 1
+where testchar4arr is null;
+select * from domarrtest where testchar4arr is null;
+ testint4arr | testchar4arr
+------------------+--------------
+ {12,NULL,21} |
+ {NULL,NULL,NULL} |
+(2 rows)
+
+drop table domarrtest;
+drop domain domainint4arr restrict;
+drop domain domainchar4arr restrict;
+create domain dia as int[];
+select '{1,2,3}'::dia;
+ dia
+---------
+ {1,2,3}
+(1 row)
+
+select array_dims('{1,2,3}'::dia);
+ array_dims
+------------
+ [1:3]
+(1 row)
+
+select pg_typeof('{1,2,3}'::dia);
+ pg_typeof
+-----------
+ dia
+(1 row)
+
+select pg_typeof('{1,2,3}'::dia || 42); -- should be int[] not dia
+ pg_typeof
+-----------
+ integer[]
+(1 row)
+
+drop domain dia;
+-- Test domains over composites
+create type comptype as (r float8, i float8);
+create domain dcomptype as comptype;
+create table dcomptable (d1 dcomptype unique);
+insert into dcomptable values (row(1,2)::dcomptype);
+insert into dcomptable values (row(3,4)::comptype);
+insert into dcomptable values (row(1,2)::dcomptype); -- fail on uniqueness
+ERROR: duplicate key value violates unique constraint "dcomptable_d1_key"
+DETAIL: Key (d1)=((1,2)) already exists.
+insert into dcomptable (d1.r) values(11);
+select * from dcomptable;
+ d1
+-------
+ (1,2)
+ (3,4)
+ (11,)
+(3 rows)
+
+select (d1).r, (d1).i, (d1).* from dcomptable;
+ r | i | r | i
+----+---+----+---
+ 1 | 2 | 1 | 2
+ 3 | 4 | 3 | 4
+ 11 | | 11 |
+(3 rows)
+
+update dcomptable set d1.r = (d1).r + 1 where (d1).i > 0;
+select * from dcomptable;
+ d1
+-------
+ (11,)
+ (2,2)
+ (4,4)
+(3 rows)
+
+alter domain dcomptype add constraint c1 check ((value).r <= (value).i);
+alter domain dcomptype add constraint c2 check ((value).r > (value).i); -- fail
+ERROR: column "d1" of table "dcomptable" contains values that violate the new constraint
+select row(2,1)::dcomptype; -- fail
+ERROR: value for domain dcomptype violates check constraint "c1"
+insert into dcomptable values (row(1,2)::comptype);
+insert into dcomptable values (row(2,1)::comptype); -- fail
+ERROR: value for domain dcomptype violates check constraint "c1"
+insert into dcomptable (d1.r) values(99);
+insert into dcomptable (d1.r, d1.i) values(99, 100);
+insert into dcomptable (d1.r, d1.i) values(100, 99); -- fail
+ERROR: value for domain dcomptype violates check constraint "c1"
+update dcomptable set d1.r = (d1).r + 1 where (d1).i > 0; -- fail
+ERROR: value for domain dcomptype violates check constraint "c1"
+update dcomptable set d1.r = (d1).r - 1, d1.i = (d1).i + 1 where (d1).i > 0;
+select * from dcomptable;
+ d1
+----------
+ (11,)
+ (99,)
+ (1,3)
+ (3,5)
+ (0,3)
+ (98,101)
+(6 rows)
+
+explain (verbose, costs off)
+ update dcomptable set d1.r = (d1).r - 1, d1.i = (d1).i + 1 where (d1).i > 0;
+ QUERY PLAN
+-----------------------------------------------------------------------------------------------
+ Update on public.dcomptable
+ -> Seq Scan on public.dcomptable
+ Output: ROW(((d1).r - '1'::double precision), ((d1).i + '1'::double precision)), ctid
+ Filter: ((dcomptable.d1).i > '0'::double precision)
+(4 rows)
+
+create rule silly as on delete to dcomptable do instead
+ update dcomptable set d1.r = (d1).r - 1, d1.i = (d1).i + 1 where (d1).i > 0;
+\d+ dcomptable
+ Table "public.dcomptable"
+ Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
+--------+-----------+-----------+----------+---------+----------+--------------+-------------
+ d1 | dcomptype | | | | extended | |
+Indexes:
+ "dcomptable_d1_key" UNIQUE CONSTRAINT, btree (d1)
+Rules:
+ silly AS
+ 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
+ WHERE (dcomptable.d1).i > 0::double precision
+
+create function makedcomp(r float8, i float8) returns dcomptype
+as 'select row(r, i)' language sql;
+select makedcomp(1,2);
+ makedcomp
+-----------
+ (1,2)
+(1 row)
+
+select makedcomp(2,1); -- fail
+ERROR: value for domain dcomptype violates check constraint "c1"
+select * from makedcomp(1,2) m;
+ r | i
+---+---
+ 1 | 2
+(1 row)
+
+select m, m is not null from makedcomp(1,2) m;
+ m | ?column?
+-------+----------
+ (1,2) | t
+(1 row)
+
+drop function makedcomp(float8, float8);
+drop table dcomptable;
+drop type comptype cascade;
+NOTICE: drop cascades to type dcomptype
+-- check altering and dropping columns used by domain constraints
+create type comptype as (r float8, i float8);
+create domain dcomptype as comptype;
+alter domain dcomptype add constraint c1 check ((value).r > 0);
+comment on constraint c1 on domain dcomptype is 'random commentary';
+select row(0,1)::dcomptype; -- fail
+ERROR: value for domain dcomptype violates check constraint "c1"
+alter type comptype alter attribute r type varchar; -- fail
+ERROR: operator does not exist: character varying > double precision
+HINT: No operator matches the given name and argument types. You might need to add explicit type casts.
+alter type comptype alter attribute r type bigint;
+alter type comptype drop attribute r; -- fail
+ERROR: cannot drop column r of composite type comptype because other objects depend on it
+DETAIL: constraint c1 depends on column r of composite type comptype
+HINT: Use DROP ... CASCADE to drop the dependent objects too.
+alter type comptype drop attribute i;
+select conname, obj_description(oid, 'pg_constraint') from pg_constraint
+ where contypid = 'dcomptype'::regtype; -- check comment is still there
+ conname | obj_description
+---------+-------------------
+ c1 | random commentary
+(1 row)
+
+drop type comptype cascade;
+NOTICE: drop cascades to type dcomptype
+-- Test domains over arrays of composite
+create type comptype as (r float8, i float8);
+create domain dcomptypea as comptype[];
+create table dcomptable (d1 dcomptypea unique);
+insert into dcomptable values (array[row(1,2)]::dcomptypea);
+insert into dcomptable values (array[row(3,4), row(5,6)]::comptype[]);
+insert into dcomptable values (array[row(7,8)::comptype, row(9,10)::comptype]);
+insert into dcomptable values (array[row(1,2)]::dcomptypea); -- fail on uniqueness
+ERROR: duplicate key value violates unique constraint "dcomptable_d1_key"
+DETAIL: Key (d1)=({"(1,2)"}) already exists.
+insert into dcomptable (d1[1]) values(row(9,10));
+insert into dcomptable (d1[1].r) values(11);
+select * from dcomptable;
+ d1
+--------------------
+ {"(1,2)"}
+ {"(3,4)","(5,6)"}
+ {"(7,8)","(9,10)"}
+ {"(9,10)"}
+ {"(11,)"}
+(5 rows)
+
+select d1[2], d1[1].r, d1[1].i from dcomptable;
+ d1 | r | i
+--------+----+----
+ | 1 | 2
+ (5,6) | 3 | 4
+ (9,10) | 7 | 8
+ | 9 | 10
+ | 11 |
+(5 rows)
+
+update dcomptable set d1[2] = row(d1[2].i, d1[2].r);
+select * from dcomptable;
+ d1
+--------------------
+ {"(1,2)","(,)"}
+ {"(3,4)","(6,5)"}
+ {"(7,8)","(10,9)"}
+ {"(9,10)","(,)"}
+ {"(11,)","(,)"}
+(5 rows)
+
+update dcomptable set d1[1].r = d1[1].r + 1 where d1[1].i > 0;
+select * from dcomptable;
+ d1
+--------------------
+ {"(11,)","(,)"}
+ {"(2,2)","(,)"}
+ {"(4,4)","(6,5)"}
+ {"(8,8)","(10,9)"}
+ {"(10,10)","(,)"}
+(5 rows)
+
+alter domain dcomptypea add constraint c1 check (value[1].r <= value[1].i);
+alter domain dcomptypea add constraint c2 check (value[1].r > value[1].i); -- fail
+ERROR: column "d1" of table "dcomptable" contains values that violate the new constraint
+select array[row(2,1)]::dcomptypea; -- fail
+ERROR: value for domain dcomptypea violates check constraint "c1"
+insert into dcomptable values (array[row(1,2)]::comptype[]);
+insert into dcomptable values (array[row(2,1)]::comptype[]); -- fail
+ERROR: value for domain dcomptypea violates check constraint "c1"
+insert into dcomptable (d1[1].r) values(99);
+insert into dcomptable (d1[1].r, d1[1].i) values(99, 100);
+insert into dcomptable (d1[1].r, d1[1].i) values(100, 99); -- fail
+ERROR: value for domain dcomptypea violates check constraint "c1"
+update dcomptable set d1[1].r = d1[1].r + 1 where d1[1].i > 0; -- fail
+ERROR: value for domain dcomptypea violates check constraint "c1"
+update dcomptable set d1[1].r = d1[1].r - 1, d1[1].i = d1[1].i + 1
+ where d1[1].i > 0;
+select * from dcomptable;
+ d1
+--------------------
+ {"(11,)","(,)"}
+ {"(99,)"}
+ {"(1,3)","(,)"}
+ {"(3,5)","(6,5)"}
+ {"(7,9)","(10,9)"}
+ {"(9,11)","(,)"}
+ {"(0,3)"}
+ {"(98,101)"}
+(8 rows)
+
+explain (verbose, costs off)
+ update dcomptable set d1[1].r = d1[1].r - 1, d1[1].i = d1[1].i + 1
+ where d1[1].i > 0;
+ QUERY PLAN
+----------------------------------------------------------------------------------------------------------------
+ Update on public.dcomptable
+ -> Seq Scan on public.dcomptable
+ Output: (d1[1].r := (d1[1].r - '1'::double precision))[1].i := (d1[1].i + '1'::double precision), ctid
+ Filter: (dcomptable.d1[1].i > '0'::double precision)
+(4 rows)
+
+create rule silly as on delete to dcomptable do instead
+ update dcomptable set d1[1].r = d1[1].r - 1, d1[1].i = d1[1].i + 1
+ where d1[1].i > 0;
+\d+ dcomptable
+ Table "public.dcomptable"
+ Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
+--------+------------+-----------+----------+---------+----------+--------------+-------------
+ d1 | dcomptypea | | | | extended | |
+Indexes:
+ "dcomptable_d1_key" UNIQUE CONSTRAINT, btree (d1)
+Rules:
+ silly AS
+ 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
+ WHERE dcomptable.d1[1].i > 0::double precision
+
+drop table dcomptable;
+drop type comptype cascade;
+NOTICE: drop cascades to type dcomptypea
+-- Test arrays over domains
+create domain posint as int check (value > 0);
+create table pitable (f1 posint[]);
+insert into pitable values(array[42]);
+insert into pitable values(array[-1]); -- fail
+ERROR: value for domain posint violates check constraint "posint_check"
+insert into pitable values('{0}'); -- fail
+ERROR: value for domain posint violates check constraint "posint_check"
+LINE 1: insert into pitable values('{0}');
+ ^
+update pitable set f1[1] = f1[1] + 1;
+update pitable set f1[1] = 0; -- fail
+ERROR: value for domain posint violates check constraint "posint_check"
+select * from pitable;
+ f1
+------
+ {43}
+(1 row)
+
+drop table pitable;
+create domain vc4 as varchar(4);
+create table vc4table (f1 vc4[]);
+insert into vc4table values(array['too long']); -- fail
+ERROR: value too long for type character varying(4)
+insert into vc4table values(array['too long']::vc4[]); -- cast truncates
+select * from vc4table;
+ f1
+----------
+ {"too "}
+(1 row)
+
+drop table vc4table;
+drop type vc4;
+-- You can sort of fake arrays-of-arrays by putting a domain in between
+create domain dposinta as posint[];
+create table dposintatable (f1 dposinta[]);
+insert into dposintatable values(array[array[42]]); -- fail
+ERROR: column "f1" is of type dposinta[] but expression is of type integer[]
+LINE 1: insert into dposintatable values(array[array[42]]);
+ ^
+HINT: You will need to rewrite or cast the expression.
+insert into dposintatable values(array[array[42]::posint[]]); -- still fail
+ERROR: column "f1" is of type dposinta[] but expression is of type posint[]
+LINE 1: insert into dposintatable values(array[array[42]::posint[]])...
+ ^
+HINT: You will need to rewrite or cast the expression.
+insert into dposintatable values(array[array[42]::dposinta]); -- but this works
+select f1, f1[1], (f1[1])[1] from dposintatable;
+ f1 | f1 | f1
+----------+------+----
+ {"{42}"} | {42} | 42
+(1 row)
+
+select pg_typeof(f1) from dposintatable;
+ pg_typeof
+------------
+ dposinta[]
+(1 row)
+
+select pg_typeof(f1[1]) from dposintatable;
+ pg_typeof
+-----------
+ dposinta
+(1 row)
+
+select pg_typeof(f1[1][1]) from dposintatable;
+ pg_typeof
+-----------
+ dposinta
+(1 row)
+
+select pg_typeof((f1[1])[1]) from dposintatable;
+ pg_typeof
+-----------
+ posint
+(1 row)
+
+update dposintatable set f1[2] = array[99];
+select f1, f1[1], (f1[2])[1] from dposintatable;
+ f1 | f1 | f1
+-----------------+------+----
+ {"{42}","{99}"} | {42} | 99
+(1 row)
+
+-- it'd be nice if you could do something like this, but for now you can't:
+update dposintatable set f1[2][1] = array[97];
+ERROR: wrong number of array subscripts
+-- maybe someday we can make this syntax work:
+update dposintatable set (f1[2])[1] = array[98];
+ERROR: syntax error at or near "["
+LINE 1: update dposintatable set (f1[2])[1] = array[98];
+ ^
+drop table dposintatable;
+drop domain posint cascade;
+NOTICE: drop cascades to type dposinta
+-- Test arrays over domains of composite
+create type comptype as (cf1 int, cf2 int);
+create domain dcomptype as comptype check ((value).cf1 > 0);
+create table dcomptable (f1 dcomptype[]);
+insert into dcomptable values (null);
+update dcomptable set f1[1].cf2 = 5;
+table dcomptable;
+ f1
+----------
+ {"(,5)"}
+(1 row)
+
+update dcomptable set f1[1].cf1 = -1; -- fail
+ERROR: value for domain dcomptype violates check constraint "dcomptype_check"
+update dcomptable set f1[1].cf1 = 1;
+table dcomptable;
+ f1
+-----------
+ {"(1,5)"}
+(1 row)
+
+-- if there's no constraints, a different code path is taken:
+alter domain dcomptype drop constraint dcomptype_check;
+update dcomptable set f1[1].cf1 = -1; -- now ok
+table dcomptable;
+ f1
+------------
+ {"(-1,5)"}
+(1 row)
+
+drop table dcomptable;
+drop type comptype cascade;
+NOTICE: drop cascades to type dcomptype
+-- Test not-null restrictions
+create domain dnotnull varchar(15) NOT NULL;
+create domain dnull varchar(15);
+create domain dcheck varchar(15) NOT NULL CHECK (VALUE = 'a' OR VALUE = 'c' OR VALUE = 'd');
+create table nulltest
+ ( col1 dnotnull
+ , col2 dnotnull NULL -- NOT NULL in the domain cannot be overridden
+ , col3 dnull NOT NULL
+ , col4 dnull
+ , col5 dcheck CHECK (col5 IN ('c', 'd'))
+ );
+INSERT INTO nulltest DEFAULT VALUES;
+ERROR: domain dnotnull does not allow null values
+INSERT INTO nulltest values ('a', 'b', 'c', 'd', 'c'); -- Good
+insert into nulltest values ('a', 'b', 'c', 'd', NULL);
+ERROR: domain dcheck does not allow null values
+insert into nulltest values ('a', 'b', 'c', 'd', 'a');
+ERROR: new row for relation "nulltest" violates check constraint "nulltest_col5_check"
+DETAIL: Failing row contains (a, b, c, d, a).
+INSERT INTO nulltest values (NULL, 'b', 'c', 'd', 'd');
+ERROR: domain dnotnull does not allow null values
+INSERT INTO nulltest values ('a', NULL, 'c', 'd', 'c');
+ERROR: domain dnotnull does not allow null values
+INSERT INTO nulltest values ('a', 'b', NULL, 'd', 'c');
+ERROR: null value in column "col3" of relation "nulltest" violates not-null constraint
+DETAIL: Failing row contains (a, b, null, d, c).
+INSERT INTO nulltest values ('a', 'b', 'c', NULL, 'd'); -- Good
+-- Test copy
+COPY nulltest FROM stdin; --fail
+ERROR: null value in column "col3" of relation "nulltest" violates not-null constraint
+DETAIL: Failing row contains (a, b, null, d, d).
+CONTEXT: COPY nulltest, line 1: "a b \N d d"
+COPY nulltest FROM stdin; --fail
+ERROR: domain dcheck does not allow null values
+CONTEXT: COPY nulltest, line 1, column col5: null input
+-- Last row is bad
+COPY nulltest FROM stdin;
+ERROR: new row for relation "nulltest" violates check constraint "nulltest_col5_check"
+DETAIL: Failing row contains (a, b, c, null, a).
+CONTEXT: COPY nulltest, line 3: "a b c \N a"
+select * from nulltest;
+ col1 | col2 | col3 | col4 | col5
+------+------+------+------+------
+ a | b | c | d | c
+ a | b | c | | d
+(2 rows)
+
+-- Test out coerced (casted) constraints
+SELECT cast('1' as dnotnull);
+ dnotnull
+----------
+ 1
+(1 row)
+
+SELECT cast(NULL as dnotnull); -- fail
+ERROR: domain dnotnull does not allow null values
+SELECT cast(cast(NULL as dnull) as dnotnull); -- fail
+ERROR: domain dnotnull does not allow null values
+SELECT cast(col4 as dnotnull) from nulltest; -- fail
+ERROR: domain dnotnull does not allow null values
+-- cleanup
+drop table nulltest;
+drop domain dnotnull restrict;
+drop domain dnull restrict;
+drop domain dcheck restrict;
+create domain ddef1 int4 DEFAULT 3;
+create domain ddef2 oid DEFAULT '12';
+-- Type mixing, function returns int8
+create domain ddef3 text DEFAULT 5;
+create sequence ddef4_seq;
+create domain ddef4 int4 DEFAULT nextval('ddef4_seq');
+create domain ddef5 numeric(8,2) NOT NULL DEFAULT '12.12';
+create table defaulttest
+ ( col1 ddef1
+ , col2 ddef2
+ , col3 ddef3
+ , col4 ddef4 PRIMARY KEY
+ , col5 ddef1 NOT NULL DEFAULT NULL
+ , col6 ddef2 DEFAULT '88'
+ , col7 ddef4 DEFAULT 8000
+ , col8 ddef5
+ );
+insert into defaulttest(col4) values(0); -- fails, col5 defaults to null
+ERROR: null value in column "col5" of relation "defaulttest" violates not-null constraint
+DETAIL: Failing row contains (3, 12, 5, 0, null, 88, 8000, 12.12).
+alter table defaulttest alter column col5 drop default;
+insert into defaulttest default values; -- succeeds, inserts domain default
+-- We used to treat SET DEFAULT NULL as equivalent to DROP DEFAULT; wrong
+alter table defaulttest alter column col5 set default null;
+insert into defaulttest(col4) values(0); -- fails
+ERROR: null value in column "col5" of relation "defaulttest" violates not-null constraint
+DETAIL: Failing row contains (3, 12, 5, 0, null, 88, 8000, 12.12).
+alter table defaulttest alter column col5 drop default;
+insert into defaulttest default values;
+insert into defaulttest default values;
+-- Test defaults with copy
+COPY defaulttest(col5) FROM stdin;
+select * from defaulttest;
+ col1 | col2 | col3 | col4 | col5 | col6 | col7 | col8
+------+------+------+------+------+------+------+-------
+ 3 | 12 | 5 | 1 | 3 | 88 | 8000 | 12.12
+ 3 | 12 | 5 | 2 | 3 | 88 | 8000 | 12.12
+ 3 | 12 | 5 | 3 | 3 | 88 | 8000 | 12.12
+ 3 | 12 | 5 | 4 | 42 | 88 | 8000 | 12.12
+(4 rows)
+
+drop table defaulttest cascade;
+-- Test ALTER DOMAIN .. NOT NULL
+create domain dnotnulltest integer;
+create table domnotnull
+( col1 dnotnulltest
+, col2 dnotnulltest
+);
+insert into domnotnull default values;
+alter domain dnotnulltest set not null; -- fails
+ERROR: column "col1" of table "domnotnull" contains null values
+update domnotnull set col1 = 5;
+alter domain dnotnulltest set not null; -- fails
+ERROR: column "col2" of table "domnotnull" contains null values
+update domnotnull set col2 = 6;
+alter domain dnotnulltest set not null;
+update domnotnull set col1 = null; -- fails
+ERROR: domain dnotnulltest does not allow null values
+alter domain dnotnulltest drop not null;
+update domnotnull set col1 = null;
+drop domain dnotnulltest cascade;
+NOTICE: drop cascades to 2 other objects
+DETAIL: drop cascades to column col2 of table domnotnull
+drop cascades to column col1 of table domnotnull
+-- Test ALTER DOMAIN .. DEFAULT ..
+create table domdeftest (col1 ddef1);
+insert into domdeftest default values;
+select * from domdeftest;
+ col1
+------
+ 3
+(1 row)
+
+alter domain ddef1 set default '42';
+insert into domdeftest default values;
+select * from domdeftest;
+ col1
+------
+ 3
+ 42
+(2 rows)
+
+alter domain ddef1 drop default;
+insert into domdeftest default values;
+select * from domdeftest;
+ col1
+------
+ 3
+ 42
+
+(3 rows)
+
+drop table domdeftest;
+-- Test ALTER DOMAIN .. CONSTRAINT ..
+create domain con as integer;
+create table domcontest (col1 con);
+insert into domcontest values (1);
+insert into domcontest values (2);
+alter domain con add constraint t check (VALUE < 1); -- fails
+ERROR: column "col1" of table "domcontest" contains values that violate the new constraint
+alter domain con add constraint t check (VALUE < 34);
+alter domain con add check (VALUE > 0);
+insert into domcontest values (-5); -- fails
+ERROR: value for domain con violates check constraint "con_check"
+insert into domcontest values (42); -- fails
+ERROR: value for domain con violates check constraint "t"
+insert into domcontest values (5);
+alter domain con drop constraint t;
+insert into domcontest values (-5); --fails
+ERROR: value for domain con violates check constraint "con_check"
+insert into domcontest values (42);
+alter domain con drop constraint nonexistent;
+ERROR: constraint "nonexistent" of domain "con" does not exist
+alter domain con drop constraint if exists nonexistent;
+NOTICE: constraint "nonexistent" of domain "con" does not exist, skipping
+-- Test ALTER DOMAIN .. CONSTRAINT .. NOT VALID
+create domain things AS INT;
+CREATE TABLE thethings (stuff things);
+INSERT INTO thethings (stuff) VALUES (55);
+ALTER DOMAIN things ADD CONSTRAINT meow CHECK (VALUE < 11);
+ERROR: column "stuff" of table "thethings" contains values that violate the new constraint
+ALTER DOMAIN things ADD CONSTRAINT meow CHECK (VALUE < 11) NOT VALID;
+ALTER DOMAIN things VALIDATE CONSTRAINT meow;
+ERROR: column "stuff" of table "thethings" contains values that violate the new constraint
+UPDATE thethings SET stuff = 10;
+ALTER DOMAIN things VALIDATE CONSTRAINT meow;
+-- Confirm ALTER DOMAIN with RULES.
+create table domtab (col1 integer);
+create domain dom as integer;
+create view domview as select cast(col1 as dom) from domtab;
+insert into domtab (col1) values (null);
+insert into domtab (col1) values (5);
+select * from domview;
+ col1
+------
+
+ 5
+(2 rows)
+
+alter domain dom set not null;
+select * from domview; -- fail
+ERROR: domain dom does not allow null values
+alter domain dom drop not null;
+select * from domview;
+ col1
+------
+
+ 5
+(2 rows)
+
+alter domain dom add constraint domchkgt6 check(value > 6);
+select * from domview; --fail
+ERROR: value for domain dom violates check constraint "domchkgt6"
+alter domain dom drop constraint domchkgt6 restrict;
+select * from domview;
+ col1
+------
+
+ 5
+(2 rows)
+
+-- cleanup
+drop domain ddef1 restrict;
+drop domain ddef2 restrict;
+drop domain ddef3 restrict;
+drop domain ddef4 restrict;
+drop domain ddef5 restrict;
+drop sequence ddef4_seq;
+-- Test domains over domains
+create domain vchar4 varchar(4);
+create domain dinter vchar4 check (substring(VALUE, 1, 1) = 'x');
+create domain dtop dinter check (substring(VALUE, 2, 1) = '1');
+select 'x123'::dtop;
+ dtop
+------
+ x123
+(1 row)
+
+select 'x1234'::dtop; -- explicit coercion should truncate
+ dtop
+------
+ x123
+(1 row)
+
+select 'y1234'::dtop; -- fail
+ERROR: value for domain dtop violates check constraint "dinter_check"
+select 'y123'::dtop; -- fail
+ERROR: value for domain dtop violates check constraint "dinter_check"
+select 'yz23'::dtop; -- fail
+ERROR: value for domain dtop violates check constraint "dinter_check"
+select 'xz23'::dtop; -- fail
+ERROR: value for domain dtop violates check constraint "dtop_check"
+create temp table dtest(f1 dtop);
+insert into dtest values('x123');
+insert into dtest values('x1234'); -- fail, implicit coercion
+ERROR: value too long for type character varying(4)
+insert into dtest values('y1234'); -- fail, implicit coercion
+ERROR: value too long for type character varying(4)
+insert into dtest values('y123'); -- fail
+ERROR: value for domain dtop violates check constraint "dinter_check"
+insert into dtest values('yz23'); -- fail
+ERROR: value for domain dtop violates check constraint "dinter_check"
+insert into dtest values('xz23'); -- fail
+ERROR: value for domain dtop violates check constraint "dtop_check"
+drop table dtest;
+drop domain vchar4 cascade;
+NOTICE: drop cascades to 2 other objects
+DETAIL: drop cascades to type dinter
+drop cascades to type dtop
+-- Make sure that constraints of newly-added domain columns are
+-- enforced correctly, even if there's no default value for the new
+-- column. Per bug #1433
+create domain str_domain as text not null;
+create table domain_test (a int, b int);
+insert into domain_test values (1, 2);
+insert into domain_test values (1, 2);
+-- should fail
+alter table domain_test add column c str_domain;
+ERROR: domain str_domain does not allow null values
+create domain str_domain2 as text check (value <> 'foo') default 'foo';
+-- should fail
+alter table domain_test add column d str_domain2;
+ERROR: value for domain str_domain2 violates check constraint "str_domain2_check"
+-- Check that domain constraints on prepared statement parameters of
+-- unknown type are enforced correctly.
+create domain pos_int as int4 check (value > 0) not null;
+prepare s1 as select $1::pos_int = 10 as "is_ten";
+execute s1(10);
+ is_ten
+--------
+ t
+(1 row)
+
+execute s1(0); -- should fail
+ERROR: value for domain pos_int violates check constraint "pos_int_check"
+execute s1(NULL); -- should fail
+ERROR: domain pos_int does not allow null values
+-- Check that domain constraints on plpgsql function parameters, results,
+-- and local variables are enforced correctly.
+create function doubledecrement(p1 pos_int) returns pos_int as $$
+declare v pos_int;
+begin
+ return p1;
+end$$ language plpgsql;
+select doubledecrement(3); -- fail because of implicit null assignment
+ERROR: domain pos_int does not allow null values
+CONTEXT: PL/pgSQL function doubledecrement(pos_int) line 2 during statement block local variable initialization
+create or replace function doubledecrement(p1 pos_int) returns pos_int as $$
+declare v pos_int := 0;
+begin
+ return p1;
+end$$ language plpgsql;
+select doubledecrement(3); -- fail at initialization assignment
+ERROR: value for domain pos_int violates check constraint "pos_int_check"
+CONTEXT: PL/pgSQL function doubledecrement(pos_int) line 2 during statement block local variable initialization
+create or replace function doubledecrement(p1 pos_int) returns pos_int as $$
+declare v pos_int := 1;
+begin
+ v := p1 - 1;
+ return v - 1;
+end$$ language plpgsql;
+select doubledecrement(null); -- fail before call
+ERROR: domain pos_int does not allow null values
+select doubledecrement(0); -- fail before call
+ERROR: value for domain pos_int violates check constraint "pos_int_check"
+select doubledecrement(1); -- fail at assignment to v
+ERROR: value for domain pos_int violates check constraint "pos_int_check"
+CONTEXT: PL/pgSQL function doubledecrement(pos_int) line 4 at assignment
+select doubledecrement(2); -- fail at return
+ERROR: value for domain pos_int violates check constraint "pos_int_check"
+CONTEXT: PL/pgSQL function doubledecrement(pos_int) while casting return value to function's return type
+select doubledecrement(3); -- good
+ doubledecrement
+-----------------
+ 1
+(1 row)
+
+-- Check that ALTER DOMAIN tests columns of derived types
+create domain posint as int4;
+-- Currently, this doesn't work for composite types, but verify it complains
+create type ddtest1 as (f1 posint);
+create table ddtest2(f1 ddtest1);
+insert into ddtest2 values(row(-1));
+alter domain posint add constraint c1 check(value >= 0);
+ERROR: cannot alter type "posint" because column "ddtest2.f1" uses it
+drop table ddtest2;
+-- Likewise for domains within arrays of composite
+create table ddtest2(f1 ddtest1[]);
+insert into ddtest2 values('{(-1)}');
+alter domain posint add constraint c1 check(value >= 0);
+ERROR: cannot alter type "posint" because column "ddtest2.f1" uses it
+drop table ddtest2;
+-- Likewise for domains within domains over composite
+create domain ddtest1d as ddtest1;
+create table ddtest2(f1 ddtest1d);
+insert into ddtest2 values('(-1)');
+alter domain posint add constraint c1 check(value >= 0);
+ERROR: cannot alter type "posint" because column "ddtest2.f1" uses it
+drop table ddtest2;
+drop domain ddtest1d;
+-- Likewise for domains within domains over array of composite
+create domain ddtest1d as ddtest1[];
+create table ddtest2(f1 ddtest1d);
+insert into ddtest2 values('{(-1)}');
+alter domain posint add constraint c1 check(value >= 0);
+ERROR: cannot alter type "posint" because column "ddtest2.f1" uses it
+drop table ddtest2;
+drop domain ddtest1d;
+-- Doesn't work for ranges, either
+create type rposint as range (subtype = posint);
+create table ddtest2(f1 rposint);
+insert into ddtest2 values('(-1,3]');
+alter domain posint add constraint c1 check(value >= 0);
+ERROR: cannot alter type "posint" because column "ddtest2.f1" uses it
+drop table ddtest2;
+drop type rposint;
+alter domain posint add constraint c1 check(value >= 0);
+create domain posint2 as posint check (value % 2 = 0);
+create table ddtest2(f1 posint2);
+insert into ddtest2 values(11); -- fail
+ERROR: value for domain posint2 violates check constraint "posint2_check"
+insert into ddtest2 values(-2); -- fail
+ERROR: value for domain posint2 violates check constraint "c1"
+insert into ddtest2 values(2);
+alter domain posint add constraint c2 check(value >= 10); -- fail
+ERROR: column "f1" of table "ddtest2" contains values that violate the new constraint
+alter domain posint add constraint c2 check(value > 0); -- OK
+drop table ddtest2;
+drop type ddtest1;
+drop domain posint cascade;
+NOTICE: drop cascades to type posint2
+--
+-- Check enforcement of domain-related typmod in plpgsql (bug #5717)
+--
+create or replace function array_elem_check(numeric) returns numeric as $$
+declare
+ x numeric(4,2)[1];
+begin
+ x[1] := $1;
+ return x[1];
+end$$ language plpgsql;
+select array_elem_check(121.00);
+ERROR: numeric field overflow
+DETAIL: A field with precision 4, scale 2 must round to an absolute value less than 10^2.
+CONTEXT: PL/pgSQL function array_elem_check(numeric) line 5 at assignment
+select array_elem_check(1.23456);
+ array_elem_check
+------------------
+ 1.23
+(1 row)
+
+create domain mynums as numeric(4,2)[1];
+create or replace function array_elem_check(numeric) returns numeric as $$
+declare
+ x mynums;
+begin
+ x[1] := $1;
+ return x[1];
+end$$ language plpgsql;
+select array_elem_check(121.00);
+ERROR: numeric field overflow
+DETAIL: A field with precision 4, scale 2 must round to an absolute value less than 10^2.
+CONTEXT: PL/pgSQL function array_elem_check(numeric) line 5 at assignment
+select array_elem_check(1.23456);
+ array_elem_check
+------------------
+ 1.23
+(1 row)
+
+create domain mynums2 as mynums;
+create or replace function array_elem_check(numeric) returns numeric as $$
+declare
+ x mynums2;
+begin
+ x[1] := $1;
+ return x[1];
+end$$ language plpgsql;
+select array_elem_check(121.00);
+ERROR: numeric field overflow
+DETAIL: A field with precision 4, scale 2 must round to an absolute value less than 10^2.
+CONTEXT: PL/pgSQL function array_elem_check(numeric) line 5 at assignment
+select array_elem_check(1.23456);
+ array_elem_check
+------------------
+ 1.23
+(1 row)
+
+drop function array_elem_check(numeric);
+--
+-- Check enforcement of array-level domain constraints
+--
+create domain orderedpair as int[2] check (value[1] < value[2]);
+select array[1,2]::orderedpair;
+ array
+-------
+ {1,2}
+(1 row)
+
+select array[2,1]::orderedpair; -- fail
+ERROR: value for domain orderedpair violates check constraint "orderedpair_check"
+create temp table op (f1 orderedpair);
+insert into op values (array[1,2]);
+insert into op values (array[2,1]); -- fail
+ERROR: value for domain orderedpair violates check constraint "orderedpair_check"
+update op set f1[2] = 3;
+update op set f1[2] = 0; -- fail
+ERROR: value for domain orderedpair violates check constraint "orderedpair_check"
+select * from op;
+ f1
+-------
+ {1,3}
+(1 row)
+
+create or replace function array_elem_check(int) returns int as $$
+declare
+ x orderedpair := '{1,2}';
+begin
+ x[2] := $1;
+ return x[2];
+end$$ language plpgsql;
+select array_elem_check(3);
+ array_elem_check
+------------------
+ 3
+(1 row)
+
+select array_elem_check(-1);
+ERROR: value for domain orderedpair violates check constraint "orderedpair_check"
+CONTEXT: PL/pgSQL function array_elem_check(integer) line 5 at assignment
+drop function array_elem_check(int);
+--
+-- Check enforcement of changing constraints in plpgsql
+--
+create domain di as int;
+create function dom_check(int) returns di as $$
+declare d di;
+begin
+ d := $1::di;
+ return d;
+end
+$$ language plpgsql immutable;
+select dom_check(0);
+ dom_check
+-----------
+ 0
+(1 row)
+
+alter domain di add constraint pos check (value > 0);
+select dom_check(0); -- fail
+ERROR: value for domain di violates check constraint "pos"
+CONTEXT: PL/pgSQL function dom_check(integer) line 4 at assignment
+alter domain di drop constraint pos;
+select dom_check(0);
+ dom_check
+-----------
+ 0
+(1 row)
+
+-- implicit cast during assignment is a separate code path, test that too
+create or replace function dom_check(int) returns di as $$
+declare d di;
+begin
+ d := $1;
+ return d;
+end
+$$ language plpgsql immutable;
+select dom_check(0);
+ dom_check
+-----------
+ 0
+(1 row)
+
+alter domain di add constraint pos check (value > 0);
+select dom_check(0); -- fail
+ERROR: value for domain di violates check constraint "pos"
+CONTEXT: PL/pgSQL function dom_check(integer) line 4 at assignment
+alter domain di drop constraint pos;
+select dom_check(0);
+ dom_check
+-----------
+ 0
+(1 row)
+
+drop function dom_check(int);
+drop domain di;
+--
+-- Check use of a (non-inline-able) SQL function in a domain constraint;
+-- this has caused issues in the past
+--
+create function sql_is_distinct_from(anyelement, anyelement)
+returns boolean language sql
+as 'select $1 is distinct from $2 limit 1';
+create domain inotnull int
+ check (sql_is_distinct_from(value, null));
+select 1::inotnull;
+ inotnull
+----------
+ 1
+(1 row)
+
+select null::inotnull;
+ERROR: value for domain inotnull violates check constraint "inotnull_check"
+create table dom_table (x inotnull);
+insert into dom_table values ('1');
+insert into dom_table values (1);
+insert into dom_table values (null);
+ERROR: value for domain inotnull violates check constraint "inotnull_check"
+drop table dom_table;
+drop domain inotnull;
+drop function sql_is_distinct_from(anyelement, anyelement);
+--
+-- Renaming
+--
+create domain testdomain1 as int;
+alter domain testdomain1 rename to testdomain2;
+alter type testdomain2 rename to testdomain3; -- alter type also works
+drop domain testdomain3;
+--
+-- Renaming domain constraints
+--
+create domain testdomain1 as int constraint unsigned check (value > 0);
+alter domain testdomain1 rename constraint unsigned to unsigned_foo;
+alter domain testdomain1 drop constraint unsigned_foo;
+drop domain testdomain1;