mirror of https://github.com/postgres/postgres
If a plpgsql function is declared to return a domain type, and the domain's constraints forbid a null value, it was nonetheless possible to return NULL, because we didn't bother to check the constraints for a null result. I'd noticed this while fooling with domains-over-composite, but had not gotten around to fixing it immediately. Add a regression test script exercising this and various other domain cases, largely borrowed from the plpython_types test. Although this is clearly a bug fix, I'm not sure whether anyone would thank us for changing the behavior in stable branches, so I'm inclined not to back-patch.pull/31/merge
parent
439c7bc1a0
commit
51db0d18fb
@ -0,0 +1,397 @@ |
||||
-- |
||||
-- Tests for PL/pgSQL's behavior with domain types |
||||
-- |
||||
CREATE DOMAIN booltrue AS bool CHECK (VALUE IS TRUE OR VALUE IS NULL); |
||||
CREATE FUNCTION test_argresult_booltrue(x booltrue, y bool) RETURNS booltrue AS $$ |
||||
begin |
||||
return y; |
||||
end |
||||
$$ LANGUAGE plpgsql; |
||||
SELECT * FROM test_argresult_booltrue(true, true); |
||||
test_argresult_booltrue |
||||
------------------------- |
||||
t |
||||
(1 row) |
||||
|
||||
SELECT * FROM test_argresult_booltrue(false, true); |
||||
ERROR: value for domain booltrue violates check constraint "booltrue_check" |
||||
SELECT * FROM test_argresult_booltrue(true, false); |
||||
ERROR: value for domain booltrue violates check constraint "booltrue_check" |
||||
CONTEXT: PL/pgSQL function test_argresult_booltrue(booltrue,boolean) while casting return value to function's return type |
||||
CREATE FUNCTION test_assign_booltrue(x bool, y bool) RETURNS booltrue AS $$ |
||||
declare v booltrue := x; |
||||
begin |
||||
v := y; |
||||
return v; |
||||
end |
||||
$$ LANGUAGE plpgsql; |
||||
SELECT * FROM test_assign_booltrue(true, true); |
||||
test_assign_booltrue |
||||
---------------------- |
||||
t |
||||
(1 row) |
||||
|
||||
SELECT * FROM test_assign_booltrue(false, true); |
||||
ERROR: value for domain booltrue violates check constraint "booltrue_check" |
||||
CONTEXT: PL/pgSQL function test_assign_booltrue(boolean,boolean) line 3 during statement block local variable initialization |
||||
SELECT * FROM test_assign_booltrue(true, false); |
||||
ERROR: value for domain booltrue violates check constraint "booltrue_check" |
||||
CONTEXT: PL/pgSQL function test_assign_booltrue(boolean,boolean) line 4 at assignment |
||||
CREATE DOMAIN uint2 AS int2 CHECK (VALUE >= 0); |
||||
CREATE FUNCTION test_argresult_uint2(x uint2, y int) RETURNS uint2 AS $$ |
||||
begin |
||||
return y; |
||||
end |
||||
$$ LANGUAGE plpgsql; |
||||
SELECT * FROM test_argresult_uint2(100::uint2, 50); |
||||
test_argresult_uint2 |
||||
---------------------- |
||||
50 |
||||
(1 row) |
||||
|
||||
SELECT * FROM test_argresult_uint2(100::uint2, -50); |
||||
ERROR: value for domain uint2 violates check constraint "uint2_check" |
||||
CONTEXT: PL/pgSQL function test_argresult_uint2(uint2,integer) while casting return value to function's return type |
||||
SELECT * FROM test_argresult_uint2(null, 1); |
||||
test_argresult_uint2 |
||||
---------------------- |
||||
1 |
||||
(1 row) |
||||
|
||||
CREATE FUNCTION test_assign_uint2(x int, y int) RETURNS uint2 AS $$ |
||||
declare v uint2 := x; |
||||
begin |
||||
v := y; |
||||
return v; |
||||
end |
||||
$$ LANGUAGE plpgsql; |
||||
SELECT * FROM test_assign_uint2(100, 50); |
||||
test_assign_uint2 |
||||
------------------- |
||||
50 |
||||
(1 row) |
||||
|
||||
SELECT * FROM test_assign_uint2(100, -50); |
||||
ERROR: value for domain uint2 violates check constraint "uint2_check" |
||||
CONTEXT: PL/pgSQL function test_assign_uint2(integer,integer) line 4 at assignment |
||||
SELECT * FROM test_assign_uint2(-100, 50); |
||||
ERROR: value for domain uint2 violates check constraint "uint2_check" |
||||
CONTEXT: PL/pgSQL function test_assign_uint2(integer,integer) line 3 during statement block local variable initialization |
||||
SELECT * FROM test_assign_uint2(null, 1); |
||||
test_assign_uint2 |
||||
------------------- |
||||
1 |
||||
(1 row) |
||||
|
||||
CREATE DOMAIN nnint AS int NOT NULL; |
||||
CREATE FUNCTION test_argresult_nnint(x nnint, y int) RETURNS nnint AS $$ |
||||
begin |
||||
return y; |
||||
end |
||||
$$ LANGUAGE plpgsql; |
||||
SELECT * FROM test_argresult_nnint(10, 20); |
||||
test_argresult_nnint |
||||
---------------------- |
||||
20 |
||||
(1 row) |
||||
|
||||
SELECT * FROM test_argresult_nnint(null, 20); |
||||
ERROR: domain nnint does not allow null values |
||||
SELECT * FROM test_argresult_nnint(10, null); |
||||
ERROR: domain nnint does not allow null values |
||||
CONTEXT: PL/pgSQL function test_argresult_nnint(nnint,integer) while casting return value to function's return type |
||||
CREATE FUNCTION test_assign_nnint(x int, y int) RETURNS nnint AS $$ |
||||
declare v nnint := x; |
||||
begin |
||||
v := y; |
||||
return v; |
||||
end |
||||
$$ LANGUAGE plpgsql; |
||||
SELECT * FROM test_assign_nnint(10, 20); |
||||
test_assign_nnint |
||||
------------------- |
||||
20 |
||||
(1 row) |
||||
|
||||
SELECT * FROM test_assign_nnint(null, 20); |
||||
ERROR: domain nnint does not allow null values |
||||
CONTEXT: PL/pgSQL function test_assign_nnint(integer,integer) line 3 during statement block local variable initialization |
||||
SELECT * FROM test_assign_nnint(10, null); |
||||
ERROR: domain nnint does not allow null values |
||||
CONTEXT: PL/pgSQL function test_assign_nnint(integer,integer) line 4 at assignment |
||||
-- |
||||
-- Domains over arrays |
||||
-- |
||||
CREATE DOMAIN ordered_pair_domain AS integer[] CHECK (array_length(VALUE,1)=2 AND VALUE[1] < VALUE[2]); |
||||
CREATE FUNCTION test_argresult_array_domain(x ordered_pair_domain) |
||||
RETURNS ordered_pair_domain AS $$ |
||||
begin |
||||
return x; |
||||
end |
||||
$$ LANGUAGE plpgsql; |
||||
SELECT * FROM test_argresult_array_domain(ARRAY[0, 100]::ordered_pair_domain); |
||||
test_argresult_array_domain |
||||
----------------------------- |
||||
{0,100} |
||||
(1 row) |
||||
|
||||
SELECT * FROM test_argresult_array_domain(NULL::ordered_pair_domain); |
||||
test_argresult_array_domain |
||||
----------------------------- |
||||
|
||||
(1 row) |
||||
|
||||
CREATE FUNCTION test_argresult_array_domain_check_violation() |
||||
RETURNS ordered_pair_domain AS $$ |
||||
begin |
||||
return array[2,1]; |
||||
end |
||||
$$ LANGUAGE plpgsql; |
||||
SELECT * FROM test_argresult_array_domain_check_violation(); |
||||
ERROR: value for domain ordered_pair_domain violates check constraint "ordered_pair_domain_check" |
||||
CONTEXT: PL/pgSQL function test_argresult_array_domain_check_violation() while casting return value to function's return type |
||||
CREATE FUNCTION test_assign_ordered_pair_domain(x int, y int, z int) RETURNS ordered_pair_domain AS $$ |
||||
declare v ordered_pair_domain := array[x, y]; |
||||
begin |
||||
v[2] := z; |
||||
return v; |
||||
end |
||||
$$ LANGUAGE plpgsql; |
||||
SELECT * FROM test_assign_ordered_pair_domain(1,2,3); |
||||
test_assign_ordered_pair_domain |
||||
--------------------------------- |
||||
{1,3} |
||||
(1 row) |
||||
|
||||
SELECT * FROM test_assign_ordered_pair_domain(1,2,0); |
||||
ERROR: value for domain ordered_pair_domain violates check constraint "ordered_pair_domain_check" |
||||
CONTEXT: PL/pgSQL function test_assign_ordered_pair_domain(integer,integer,integer) line 4 at assignment |
||||
SELECT * FROM test_assign_ordered_pair_domain(2,1,3); |
||||
ERROR: value for domain ordered_pair_domain violates check constraint "ordered_pair_domain_check" |
||||
CONTEXT: PL/pgSQL function test_assign_ordered_pair_domain(integer,integer,integer) line 3 during statement block local variable initialization |
||||
-- |
||||
-- Arrays of domains |
||||
-- |
||||
CREATE FUNCTION test_read_uint2_array(x uint2[]) RETURNS uint2 AS $$ |
||||
begin |
||||
return x[1]; |
||||
end |
||||
$$ LANGUAGE plpgsql; |
||||
select test_read_uint2_array(array[1::uint2]); |
||||
test_read_uint2_array |
||||
----------------------- |
||||
1 |
||||
(1 row) |
||||
|
||||
CREATE FUNCTION test_build_uint2_array(x int2) RETURNS uint2[] AS $$ |
||||
begin |
||||
return array[x, x]; |
||||
end |
||||
$$ LANGUAGE plpgsql; |
||||
select test_build_uint2_array(1::int2); |
||||
test_build_uint2_array |
||||
------------------------ |
||||
{1,1} |
||||
(1 row) |
||||
|
||||
select test_build_uint2_array(-1::int2); -- fail |
||||
ERROR: value for domain uint2 violates check constraint "uint2_check" |
||||
CONTEXT: PL/pgSQL function test_build_uint2_array(smallint) while casting return value to function's return type |
||||
CREATE FUNCTION test_argresult_domain_array(x integer[]) |
||||
RETURNS ordered_pair_domain[] AS $$ |
||||
begin |
||||
return array[x::ordered_pair_domain, x::ordered_pair_domain]; |
||||
end |
||||
$$ LANGUAGE plpgsql; |
||||
select test_argresult_domain_array(array[2,4]); |
||||
test_argresult_domain_array |
||||
----------------------------- |
||||
{"{2,4}","{2,4}"} |
||||
(1 row) |
||||
|
||||
select test_argresult_domain_array(array[4,2]); -- fail |
||||
ERROR: value for domain ordered_pair_domain violates check constraint "ordered_pair_domain_check" |
||||
CONTEXT: PL/pgSQL function test_argresult_domain_array(integer[]) line 3 at RETURN |
||||
CREATE FUNCTION test_argresult_domain_array2(x ordered_pair_domain) |
||||
RETURNS integer AS $$ |
||||
begin |
||||
return x[1]; |
||||
end |
||||
$$ LANGUAGE plpgsql; |
||||
select test_argresult_domain_array2(array[2,4]); |
||||
test_argresult_domain_array2 |
||||
------------------------------ |
||||
2 |
||||
(1 row) |
||||
|
||||
select test_argresult_domain_array2(array[4,2]); -- fail |
||||
ERROR: value for domain ordered_pair_domain violates check constraint "ordered_pair_domain_check" |
||||
CREATE FUNCTION test_argresult_array_domain_array(x ordered_pair_domain[]) |
||||
RETURNS ordered_pair_domain AS $$ |
||||
begin |
||||
return x[1]; |
||||
end |
||||
$$ LANGUAGE plpgsql; |
||||
select test_argresult_array_domain_array(array[array[2,4]::ordered_pair_domain]); |
||||
test_argresult_array_domain_array |
||||
----------------------------------- |
||||
{2,4} |
||||
(1 row) |
||||
|
||||
-- |
||||
-- Domains within composite |
||||
-- |
||||
CREATE TYPE nnint_container AS (f1 int, f2 nnint); |
||||
CREATE FUNCTION test_result_nnint_container(x int, y int) |
||||
RETURNS nnint_container AS $$ |
||||
begin |
||||
return row(x, y)::nnint_container; |
||||
end |
||||
$$ LANGUAGE plpgsql; |
||||
SELECT test_result_nnint_container(null, 3); |
||||
test_result_nnint_container |
||||
----------------------------- |
||||
(,3) |
||||
(1 row) |
||||
|
||||
SELECT test_result_nnint_container(3, null); -- fail |
||||
ERROR: domain nnint does not allow null values |
||||
CONTEXT: PL/pgSQL function test_result_nnint_container(integer,integer) line 3 at RETURN |
||||
CREATE FUNCTION test_assign_nnint_container(x int, y int, z int) |
||||
RETURNS nnint_container AS $$ |
||||
declare v nnint_container := row(x, y); |
||||
begin |
||||
v.f2 := z; |
||||
return v; |
||||
end |
||||
$$ LANGUAGE plpgsql; |
||||
SELECT * FROM test_assign_nnint_container(1,2,3); |
||||
f1 | f2 |
||||
----+---- |
||||
1 | 3 |
||||
(1 row) |
||||
|
||||
SELECT * FROM test_assign_nnint_container(1,2,null); |
||||
ERROR: domain nnint does not allow null values |
||||
CONTEXT: PL/pgSQL function test_assign_nnint_container(integer,integer,integer) line 4 at assignment |
||||
SELECT * FROM test_assign_nnint_container(1,null,3); |
||||
ERROR: domain nnint does not allow null values |
||||
CONTEXT: PL/pgSQL function test_assign_nnint_container(integer,integer,integer) line 3 during statement block local variable initialization |
||||
-- Since core system allows this: |
||||
SELECT null::nnint_container; |
||||
nnint_container |
||||
----------------- |
||||
|
||||
(1 row) |
||||
|
||||
-- so should PL/PgSQL |
||||
CREATE FUNCTION test_assign_nnint_container2(x int, y int, z int) |
||||
RETURNS nnint_container AS $$ |
||||
declare v nnint_container; |
||||
begin |
||||
v.f2 := z; |
||||
return v; |
||||
end |
||||
$$ LANGUAGE plpgsql; |
||||
SELECT * FROM test_assign_nnint_container2(1,2,3); |
||||
f1 | f2 |
||||
----+---- |
||||
| 3 |
||||
(1 row) |
||||
|
||||
SELECT * FROM test_assign_nnint_container2(1,2,null); |
||||
ERROR: domain nnint does not allow null values |
||||
CONTEXT: PL/pgSQL function test_assign_nnint_container2(integer,integer,integer) line 4 at assignment |
||||
-- |
||||
-- Domains of composite |
||||
-- |
||||
CREATE TYPE named_pair AS ( |
||||
i integer, |
||||
j integer |
||||
); |
||||
CREATE DOMAIN ordered_named_pair AS named_pair CHECK((VALUE).i <= (VALUE).j); |
||||
CREATE FUNCTION read_ordered_named_pair(p ordered_named_pair) RETURNS integer AS $$ |
||||
begin |
||||
return p.i + p.j; |
||||
end |
||||
$$ LANGUAGE plpgsql; |
||||
SELECT read_ordered_named_pair(row(1, 2)); |
||||
read_ordered_named_pair |
||||
------------------------- |
||||
3 |
||||
(1 row) |
||||
|
||||
SELECT read_ordered_named_pair(row(2, 1)); -- fail |
||||
ERROR: value for domain ordered_named_pair violates check constraint "ordered_named_pair_check" |
||||
CREATE FUNCTION build_ordered_named_pair(i int, j int) RETURNS ordered_named_pair AS $$ |
||||
begin |
||||
return row(i, j); |
||||
end |
||||
$$ LANGUAGE plpgsql; |
||||
SELECT build_ordered_named_pair(1,2); |
||||
build_ordered_named_pair |
||||
-------------------------- |
||||
(1,2) |
||||
(1 row) |
||||
|
||||
SELECT build_ordered_named_pair(2,1); -- fail |
||||
ERROR: value for domain ordered_named_pair violates check constraint "ordered_named_pair_check" |
||||
CONTEXT: PL/pgSQL function build_ordered_named_pair(integer,integer) while casting return value to function's return type |
||||
CREATE FUNCTION test_assign_ordered_named_pair(x int, y int, z int) |
||||
RETURNS ordered_named_pair AS $$ |
||||
declare v ordered_named_pair := row(x, y); |
||||
begin |
||||
v.j := z; |
||||
return v; |
||||
end |
||||
$$ LANGUAGE plpgsql; |
||||
SELECT * FROM test_assign_ordered_named_pair(1,2,3); |
||||
i | j |
||||
---+--- |
||||
1 | 3 |
||||
(1 row) |
||||
|
||||
SELECT * FROM test_assign_ordered_named_pair(1,2,0); |
||||
ERROR: value for domain ordered_named_pair violates check constraint "ordered_named_pair_check" |
||||
CONTEXT: PL/pgSQL function test_assign_ordered_named_pair(integer,integer,integer) line 4 at assignment |
||||
SELECT * FROM test_assign_ordered_named_pair(2,1,3); |
||||
ERROR: value for domain ordered_named_pair violates check constraint "ordered_named_pair_check" |
||||
CONTEXT: PL/pgSQL function test_assign_ordered_named_pair(integer,integer,integer) line 3 during statement block local variable initialization |
||||
CREATE FUNCTION build_ordered_named_pairs(i int, j int) RETURNS ordered_named_pair[] AS $$ |
||||
begin |
||||
return array[row(i, j), row(i, j+1)]; |
||||
end |
||||
$$ LANGUAGE plpgsql; |
||||
SELECT build_ordered_named_pairs(1,2); |
||||
build_ordered_named_pairs |
||||
--------------------------- |
||||
{"(1,2)","(1,3)"} |
||||
(1 row) |
||||
|
||||
SELECT build_ordered_named_pairs(2,1); -- fail |
||||
ERROR: value for domain ordered_named_pair violates check constraint "ordered_named_pair_check" |
||||
CONTEXT: PL/pgSQL function build_ordered_named_pairs(integer,integer) while casting return value to function's return type |
||||
CREATE FUNCTION test_assign_ordered_named_pairs(x int, y int, z int) |
||||
RETURNS ordered_named_pair[] AS $$ |
||||
declare v ordered_named_pair[] := array[row(x, y)]; |
||||
begin |
||||
-- ideally this would work, but it doesn't yet: |
||||
-- v[1].j := z; |
||||
return v; |
||||
end |
||||
$$ LANGUAGE plpgsql; |
||||
SELECT * FROM test_assign_ordered_named_pairs(1,2,3); |
||||
test_assign_ordered_named_pairs |
||||
--------------------------------- |
||||
{"(1,2)"} |
||||
(1 row) |
||||
|
||||
SELECT * FROM test_assign_ordered_named_pairs(2,1,3); |
||||
ERROR: value for domain ordered_named_pair violates check constraint "ordered_named_pair_check" |
||||
CONTEXT: PL/pgSQL function test_assign_ordered_named_pairs(integer,integer,integer) line 3 during statement block local variable initialization |
||||
SELECT * FROM test_assign_ordered_named_pairs(1,2,0); -- should fail someday |
||||
test_assign_ordered_named_pairs |
||||
--------------------------------- |
||||
{"(1,2)"} |
||||
(1 row) |
||||
|
||||
@ -0,0 +1,279 @@ |
||||
-- |
||||
-- Tests for PL/pgSQL's behavior with domain types |
||||
-- |
||||
|
||||
CREATE DOMAIN booltrue AS bool CHECK (VALUE IS TRUE OR VALUE IS NULL); |
||||
|
||||
CREATE FUNCTION test_argresult_booltrue(x booltrue, y bool) RETURNS booltrue AS $$ |
||||
begin |
||||
return y; |
||||
end |
||||
$$ LANGUAGE plpgsql; |
||||
|
||||
SELECT * FROM test_argresult_booltrue(true, true); |
||||
SELECT * FROM test_argresult_booltrue(false, true); |
||||
SELECT * FROM test_argresult_booltrue(true, false); |
||||
|
||||
CREATE FUNCTION test_assign_booltrue(x bool, y bool) RETURNS booltrue AS $$ |
||||
declare v booltrue := x; |
||||
begin |
||||
v := y; |
||||
return v; |
||||
end |
||||
$$ LANGUAGE plpgsql; |
||||
|
||||
SELECT * FROM test_assign_booltrue(true, true); |
||||
SELECT * FROM test_assign_booltrue(false, true); |
||||
SELECT * FROM test_assign_booltrue(true, false); |
||||
|
||||
|
||||
CREATE DOMAIN uint2 AS int2 CHECK (VALUE >= 0); |
||||
|
||||
CREATE FUNCTION test_argresult_uint2(x uint2, y int) RETURNS uint2 AS $$ |
||||
begin |
||||
return y; |
||||
end |
||||
$$ LANGUAGE plpgsql; |
||||
|
||||
SELECT * FROM test_argresult_uint2(100::uint2, 50); |
||||
SELECT * FROM test_argresult_uint2(100::uint2, -50); |
||||
SELECT * FROM test_argresult_uint2(null, 1); |
||||
|
||||
CREATE FUNCTION test_assign_uint2(x int, y int) RETURNS uint2 AS $$ |
||||
declare v uint2 := x; |
||||
begin |
||||
v := y; |
||||
return v; |
||||
end |
||||
$$ LANGUAGE plpgsql; |
||||
|
||||
SELECT * FROM test_assign_uint2(100, 50); |
||||
SELECT * FROM test_assign_uint2(100, -50); |
||||
SELECT * FROM test_assign_uint2(-100, 50); |
||||
SELECT * FROM test_assign_uint2(null, 1); |
||||
|
||||
|
||||
CREATE DOMAIN nnint AS int NOT NULL; |
||||
|
||||
CREATE FUNCTION test_argresult_nnint(x nnint, y int) RETURNS nnint AS $$ |
||||
begin |
||||
return y; |
||||
end |
||||
$$ LANGUAGE plpgsql; |
||||
|
||||
SELECT * FROM test_argresult_nnint(10, 20); |
||||
SELECT * FROM test_argresult_nnint(null, 20); |
||||
SELECT * FROM test_argresult_nnint(10, null); |
||||
|
||||
CREATE FUNCTION test_assign_nnint(x int, y int) RETURNS nnint AS $$ |
||||
declare v nnint := x; |
||||
begin |
||||
v := y; |
||||
return v; |
||||
end |
||||
$$ LANGUAGE plpgsql; |
||||
|
||||
SELECT * FROM test_assign_nnint(10, 20); |
||||
SELECT * FROM test_assign_nnint(null, 20); |
||||
SELECT * FROM test_assign_nnint(10, null); |
||||
|
||||
|
||||
-- |
||||
-- Domains over arrays |
||||
-- |
||||
|
||||
CREATE DOMAIN ordered_pair_domain AS integer[] CHECK (array_length(VALUE,1)=2 AND VALUE[1] < VALUE[2]); |
||||
|
||||
CREATE FUNCTION test_argresult_array_domain(x ordered_pair_domain) |
||||
RETURNS ordered_pair_domain AS $$ |
||||
begin |
||||
return x; |
||||
end |
||||
$$ LANGUAGE plpgsql; |
||||
|
||||
SELECT * FROM test_argresult_array_domain(ARRAY[0, 100]::ordered_pair_domain); |
||||
SELECT * FROM test_argresult_array_domain(NULL::ordered_pair_domain); |
||||
|
||||
CREATE FUNCTION test_argresult_array_domain_check_violation() |
||||
RETURNS ordered_pair_domain AS $$ |
||||
begin |
||||
return array[2,1]; |
||||
end |
||||
$$ LANGUAGE plpgsql; |
||||
|
||||
SELECT * FROM test_argresult_array_domain_check_violation(); |
||||
|
||||
CREATE FUNCTION test_assign_ordered_pair_domain(x int, y int, z int) RETURNS ordered_pair_domain AS $$ |
||||
declare v ordered_pair_domain := array[x, y]; |
||||
begin |
||||
v[2] := z; |
||||
return v; |
||||
end |
||||
$$ LANGUAGE plpgsql; |
||||
|
||||
SELECT * FROM test_assign_ordered_pair_domain(1,2,3); |
||||
SELECT * FROM test_assign_ordered_pair_domain(1,2,0); |
||||
SELECT * FROM test_assign_ordered_pair_domain(2,1,3); |
||||
|
||||
|
||||
-- |
||||
-- Arrays of domains |
||||
-- |
||||
|
||||
CREATE FUNCTION test_read_uint2_array(x uint2[]) RETURNS uint2 AS $$ |
||||
begin |
||||
return x[1]; |
||||
end |
||||
$$ LANGUAGE plpgsql; |
||||
|
||||
select test_read_uint2_array(array[1::uint2]); |
||||
|
||||
CREATE FUNCTION test_build_uint2_array(x int2) RETURNS uint2[] AS $$ |
||||
begin |
||||
return array[x, x]; |
||||
end |
||||
$$ LANGUAGE plpgsql; |
||||
|
||||
select test_build_uint2_array(1::int2); |
||||
select test_build_uint2_array(-1::int2); -- fail |
||||
|
||||
CREATE FUNCTION test_argresult_domain_array(x integer[]) |
||||
RETURNS ordered_pair_domain[] AS $$ |
||||
begin |
||||
return array[x::ordered_pair_domain, x::ordered_pair_domain]; |
||||
end |
||||
$$ LANGUAGE plpgsql; |
||||
|
||||
select test_argresult_domain_array(array[2,4]); |
||||
select test_argresult_domain_array(array[4,2]); -- fail |
||||
|
||||
CREATE FUNCTION test_argresult_domain_array2(x ordered_pair_domain) |
||||
RETURNS integer AS $$ |
||||
begin |
||||
return x[1]; |
||||
end |
||||
$$ LANGUAGE plpgsql; |
||||
|
||||
select test_argresult_domain_array2(array[2,4]); |
||||
select test_argresult_domain_array2(array[4,2]); -- fail |
||||
|
||||
CREATE FUNCTION test_argresult_array_domain_array(x ordered_pair_domain[]) |
||||
RETURNS ordered_pair_domain AS $$ |
||||
begin |
||||
return x[1]; |
||||
end |
||||
$$ LANGUAGE plpgsql; |
||||
|
||||
select test_argresult_array_domain_array(array[array[2,4]::ordered_pair_domain]); |
||||
|
||||
|
||||
-- |
||||
-- Domains within composite |
||||
-- |
||||
|
||||
CREATE TYPE nnint_container AS (f1 int, f2 nnint); |
||||
|
||||
CREATE FUNCTION test_result_nnint_container(x int, y int) |
||||
RETURNS nnint_container AS $$ |
||||
begin |
||||
return row(x, y)::nnint_container; |
||||
end |
||||
$$ LANGUAGE plpgsql; |
||||
|
||||
SELECT test_result_nnint_container(null, 3); |
||||
SELECT test_result_nnint_container(3, null); -- fail |
||||
|
||||
CREATE FUNCTION test_assign_nnint_container(x int, y int, z int) |
||||
RETURNS nnint_container AS $$ |
||||
declare v nnint_container := row(x, y); |
||||
begin |
||||
v.f2 := z; |
||||
return v; |
||||
end |
||||
$$ LANGUAGE plpgsql; |
||||
|
||||
SELECT * FROM test_assign_nnint_container(1,2,3); |
||||
SELECT * FROM test_assign_nnint_container(1,2,null); |
||||
SELECT * FROM test_assign_nnint_container(1,null,3); |
||||
|
||||
-- Since core system allows this: |
||||
SELECT null::nnint_container; |
||||
-- so should PL/PgSQL |
||||
|
||||
CREATE FUNCTION test_assign_nnint_container2(x int, y int, z int) |
||||
RETURNS nnint_container AS $$ |
||||
declare v nnint_container; |
||||
begin |
||||
v.f2 := z; |
||||
return v; |
||||
end |
||||
$$ LANGUAGE plpgsql; |
||||
|
||||
SELECT * FROM test_assign_nnint_container2(1,2,3); |
||||
SELECT * FROM test_assign_nnint_container2(1,2,null); |
||||
|
||||
|
||||
-- |
||||
-- Domains of composite |
||||
-- |
||||
|
||||
CREATE TYPE named_pair AS ( |
||||
i integer, |
||||
j integer |
||||
); |
||||
|
||||
CREATE DOMAIN ordered_named_pair AS named_pair CHECK((VALUE).i <= (VALUE).j); |
||||
|
||||
CREATE FUNCTION read_ordered_named_pair(p ordered_named_pair) RETURNS integer AS $$ |
||||
begin |
||||
return p.i + p.j; |
||||
end |
||||
$$ LANGUAGE plpgsql; |
||||
|
||||
SELECT read_ordered_named_pair(row(1, 2)); |
||||
SELECT read_ordered_named_pair(row(2, 1)); -- fail |
||||
|
||||
CREATE FUNCTION build_ordered_named_pair(i int, j int) RETURNS ordered_named_pair AS $$ |
||||
begin |
||||
return row(i, j); |
||||
end |
||||
$$ LANGUAGE plpgsql; |
||||
|
||||
SELECT build_ordered_named_pair(1,2); |
||||
SELECT build_ordered_named_pair(2,1); -- fail |
||||
|
||||
CREATE FUNCTION test_assign_ordered_named_pair(x int, y int, z int) |
||||
RETURNS ordered_named_pair AS $$ |
||||
declare v ordered_named_pair := row(x, y); |
||||
begin |
||||
v.j := z; |
||||
return v; |
||||
end |
||||
$$ LANGUAGE plpgsql; |
||||
|
||||
SELECT * FROM test_assign_ordered_named_pair(1,2,3); |
||||
SELECT * FROM test_assign_ordered_named_pair(1,2,0); |
||||
SELECT * FROM test_assign_ordered_named_pair(2,1,3); |
||||
|
||||
CREATE FUNCTION build_ordered_named_pairs(i int, j int) RETURNS ordered_named_pair[] AS $$ |
||||
begin |
||||
return array[row(i, j), row(i, j+1)]; |
||||
end |
||||
$$ LANGUAGE plpgsql; |
||||
|
||||
SELECT build_ordered_named_pairs(1,2); |
||||
SELECT build_ordered_named_pairs(2,1); -- fail |
||||
|
||||
CREATE FUNCTION test_assign_ordered_named_pairs(x int, y int, z int) |
||||
RETURNS ordered_named_pair[] AS $$ |
||||
declare v ordered_named_pair[] := array[row(x, y)]; |
||||
begin |
||||
-- ideally this would work, but it doesn't yet: |
||||
-- v[1].j := z; |
||||
return v; |
||||
end |
||||
$$ LANGUAGE plpgsql; |
||||
|
||||
SELECT * FROM test_assign_ordered_named_pairs(1,2,3); |
||||
SELECT * FROM test_assign_ordered_named_pairs(2,1,3); |
||||
SELECT * FROM test_assign_ordered_named_pairs(1,2,0); -- should fail someday |
||||
Loading…
Reference in new issue