1-- suppress CONTEXT so that function OIDs aren't in output
2\set VERBOSITY terse
3
4-- Test composite-type arguments
5select tcl_composite_arg_ref1(row('tkey', 42, 'ref2'));
6select tcl_composite_arg_ref2(row('tkey', 42, 'ref2'));
7
8-- More tests for composite argument/result types
9
10create domain d_comp1 as T_comp1 check ((value).ref1 > 0);
11
12create function tcl_record_arg(record, fldname text) returns int as '
13    return $1($2)
14' language pltcl;
15
16select tcl_record_arg(row('tkey', 42, 'ref2')::T_comp1, 'ref1');
17select tcl_record_arg(row('tkey', 42, 'ref2')::d_comp1, 'ref1');
18select tcl_record_arg(row(2,4), 'f2');
19
20create function tcl_cdomain_arg(d_comp1) returns int as '
21    return $1(ref1)
22' language pltcl;
23
24select tcl_cdomain_arg(row('tkey', 42, 'ref2'));
25select tcl_cdomain_arg(row('tkey', 42, 'ref2')::T_comp1);
26select tcl_cdomain_arg(row('tkey', -1, 'ref2'));  -- fail
27
28-- Test argisnull primitive
29select tcl_argisnull('foo');
30select tcl_argisnull('');
31select tcl_argisnull(null);
32
33-- test some error cases
34create function tcl_error(out a int, out b int) as $$return {$$ language pltcl;
35select tcl_error();
36
37create function bad_record(out a text, out b text) as $$return [list a]$$ language pltcl;
38select bad_record();
39
40create function bad_field(out a text, out b text) as $$return [list a 1 b 2 cow 3]$$ language pltcl;
41select bad_field();
42
43-- test compound return
44select * from tcl_test_cube_squared(5);
45
46-- test SRF
47select * from tcl_test_squared_rows(0,5);
48
49select * from tcl_test_sequence(0,5) as a;
50
51select 1, tcl_test_sequence(0,5);
52
53create function non_srf() returns int as $$return_next 1$$ language pltcl;
54select non_srf();
55
56create function bad_record_srf(out a text, out b text) returns setof record as $$
57return_next [list a]
58$$ language pltcl;
59select bad_record_srf();
60
61create function bad_field_srf(out a text, out b text) returns setof record as $$
62return_next [list a 1 b 2 cow 3]
63$$ language pltcl;
64select bad_field_srf();
65
66-- test composite and domain-over-composite results
67create function tcl_composite_result(int) returns T_comp1 as $$
68return [list tkey tkey1 ref1 $1 ref2 ref22]
69$$ language pltcl;
70select tcl_composite_result(1001);
71select * from tcl_composite_result(1002);
72
73create function tcl_dcomposite_result(int) returns d_comp1 as $$
74return [list tkey tkey2 ref1 $1 ref2 ref42]
75$$ language pltcl;
76select tcl_dcomposite_result(1001);
77select * from tcl_dcomposite_result(1002);
78select * from tcl_dcomposite_result(-1);  -- fail
79
80create function tcl_record_result(int) returns record as $$
81return [list q1 sometext q2 $1 q3 moretext]
82$$ language pltcl;
83select tcl_record_result(42);  -- fail
84select * from tcl_record_result(42);  -- fail
85select * from tcl_record_result(42) as (q1 text, q2 int, q3 text);
86select * from tcl_record_result(42) as (q1 text, q2 int, q3 text, q4 int);
87select * from tcl_record_result(42) as (q1 text, q2 int, q4 int);  -- fail
88
89-- test quote
90select tcl_eval('quote foo bar');
91select tcl_eval('quote [format %c 39]');
92select tcl_eval('quote [format %c 92]');
93
94-- Test argisnull
95select tcl_eval('argisnull');
96select tcl_eval('argisnull 14');
97select tcl_eval('argisnull abc');
98
99-- Test return_null
100select tcl_eval('return_null 14');
101
102-- Test spi_exec
103select tcl_eval('spi_exec');
104select tcl_eval('spi_exec -count');
105select tcl_eval('spi_exec -array');
106select tcl_eval('spi_exec -count abc');
107select tcl_eval('spi_exec query loop body toomuch');
108select tcl_eval('spi_exec "begin; rollback;"');
109
110-- Test spi_execp
111select tcl_eval('spi_execp');
112select tcl_eval('spi_execp -count');
113select tcl_eval('spi_execp -array');
114select tcl_eval('spi_execp -count abc');
115select tcl_eval('spi_execp -nulls');
116select tcl_eval('spi_execp ""');
117
118-- test spi_prepare
119select tcl_eval('spi_prepare');
120select tcl_eval('spi_prepare a b');
121select tcl_eval('spi_prepare a "b {"');
122select tcl_error_handling_test($tcl$spi_prepare "select moo" []$tcl$);
123
124-- test full error text
125select tcl_error_handling_test($tcl$
126spi_exec "DO $$
127BEGIN
128RAISE 'my message'
129	USING HINT = 'my hint'
130	, DETAIL = 'my detail'
131	, SCHEMA = 'my schema'
132	, TABLE = 'my table'
133	, COLUMN = 'my column'
134	, CONSTRAINT = 'my constraint'
135	, DATATYPE = 'my datatype'
136;
137END$$;"
138$tcl$);
139
140-- verify tcl_error_handling_test() properly reports non-postgres errors
141select tcl_error_handling_test('moo');
142
143-- test elog
144select tcl_eval('elog');
145select tcl_eval('elog foo bar');
146
147-- test forced error
148select tcl_eval('error "forced error"');
149
150-- test loop control in spi_exec[p]
151select tcl_spi_exec(true, 'break');
152select tcl_spi_exec(true, 'continue');
153select tcl_spi_exec(true, 'error');
154select tcl_spi_exec(true, 'return');
155select tcl_spi_exec(false, 'break');
156select tcl_spi_exec(false, 'continue');
157select tcl_spi_exec(false, 'error');
158select tcl_spi_exec(false, 'return');
159
160-- forcibly run the Tcl event loop for awhile, to check that we have not
161-- messed things up too badly by disabling the Tcl notifier subsystem
162select tcl_eval($$
163  unset -nocomplain ::tcl_vwait
164  after 100 {set ::tcl_vwait 1}
165  vwait ::tcl_vwait
166  unset -nocomplain ::tcl_vwait$$);
167