]> granicus.if.org Git - postgresql/blob - src/test/regress/expected/rangefuncs.out
Teach the system how to use hashing for UNION. (INTERSECT/EXCEPT will follow,
[postgresql] / src / test / regress / expected / rangefuncs.out
1 SELECT name, setting FROM pg_settings WHERE name LIKE 'enable%';
2        name        | setting 
3 -------------------+---------
4  enable_bitmapscan | on
5  enable_hashagg    | on
6  enable_hashjoin   | on
7  enable_indexscan  | on
8  enable_mergejoin  | on
9  enable_nestloop   | on
10  enable_seqscan    | on
11  enable_sort       | on
12  enable_tidscan    | on
13 (9 rows)
14
15 CREATE TABLE foo2(fooid int, f2 int);
16 INSERT INTO foo2 VALUES(1, 11);
17 INSERT INTO foo2 VALUES(2, 22);
18 INSERT INTO foo2 VALUES(1, 111);
19 CREATE FUNCTION foot(int) returns setof foo2 as 'SELECT * FROM foo2 WHERE fooid = $1;' LANGUAGE SQL;
20 -- supposed to fail with ERROR
21 select * from foo2, foot(foo2.fooid) z where foo2.f2 = z.f2;
22 ERROR:  function expression in FROM cannot refer to other relations of same query level
23 -- function in subselect
24 select * from foo2 where f2 in (select f2 from foot(foo2.fooid) z where z.fooid = foo2.fooid) ORDER BY 1,2;
25  fooid | f2  
26 -------+-----
27      1 |  11
28      1 | 111
29      2 |  22
30 (3 rows)
31
32 -- function in subselect
33 select * from foo2 where f2 in (select f2 from foot(1) z where z.fooid = foo2.fooid) ORDER BY 1,2;
34  fooid | f2  
35 -------+-----
36      1 |  11
37      1 | 111
38 (2 rows)
39
40 -- function in subselect
41 select * from foo2 where f2 in (select f2 from foot(foo2.fooid) z where z.fooid = 1) ORDER BY 1,2;
42  fooid | f2  
43 -------+-----
44      1 |  11
45      1 | 111
46 (2 rows)
47
48 -- nested functions
49 select foot.fooid, foot.f2 from foot(sin(pi()/2)::int) ORDER BY 1,2;
50  fooid | f2  
51 -------+-----
52      1 |  11
53      1 | 111
54 (2 rows)
55
56 CREATE TABLE foo (fooid int, foosubid int, fooname text, primary key(fooid,foosubid));
57 NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "foo_pkey" for table "foo"
58 INSERT INTO foo VALUES(1,1,'Joe');
59 INSERT INTO foo VALUES(1,2,'Ed');
60 INSERT INTO foo VALUES(2,1,'Mary');
61 -- sql, proretset = f, prorettype = b
62 CREATE FUNCTION getfoo(int) RETURNS int AS 'SELECT $1;' LANGUAGE SQL;
63 SELECT * FROM getfoo(1) AS t1;
64  t1 
65 ----
66   1
67 (1 row)
68
69 CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1);
70 SELECT * FROM vw_getfoo;
71  getfoo 
72 --------
73       1
74 (1 row)
75
76 -- sql, proretset = t, prorettype = b
77 DROP VIEW vw_getfoo;
78 DROP FUNCTION getfoo(int);
79 CREATE FUNCTION getfoo(int) RETURNS setof int AS 'SELECT fooid FROM foo WHERE fooid = $1;' LANGUAGE SQL;
80 SELECT * FROM getfoo(1) AS t1;
81  t1 
82 ----
83   1
84   1
85 (2 rows)
86
87 CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1);
88 SELECT * FROM vw_getfoo;
89  getfoo 
90 --------
91       1
92       1
93 (2 rows)
94
95 -- sql, proretset = t, prorettype = b
96 DROP VIEW vw_getfoo;
97 DROP FUNCTION getfoo(int);
98 CREATE FUNCTION getfoo(int) RETURNS setof text AS 'SELECT fooname FROM foo WHERE fooid = $1;' LANGUAGE SQL;
99 SELECT * FROM getfoo(1) AS t1;
100  t1  
101 -----
102  Joe
103  Ed
104 (2 rows)
105
106 CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1);
107 SELECT * FROM vw_getfoo;
108  getfoo 
109 --------
110  Joe
111  Ed
112 (2 rows)
113
114 -- sql, proretset = f, prorettype = c
115 DROP VIEW vw_getfoo;
116 DROP FUNCTION getfoo(int);
117 CREATE FUNCTION getfoo(int) RETURNS foo AS 'SELECT * FROM foo WHERE fooid = $1;' LANGUAGE SQL;
118 SELECT * FROM getfoo(1) AS t1;
119  fooid | foosubid | fooname 
120 -------+----------+---------
121      1 |        1 | Joe
122 (1 row)
123
124 CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1);
125 SELECT * FROM vw_getfoo;
126  fooid | foosubid | fooname 
127 -------+----------+---------
128      1 |        1 | Joe
129 (1 row)
130
131 -- sql, proretset = t, prorettype = c
132 DROP VIEW vw_getfoo;
133 DROP FUNCTION getfoo(int);
134 CREATE FUNCTION getfoo(int) RETURNS setof foo AS 'SELECT * FROM foo WHERE fooid = $1;' LANGUAGE SQL;
135 SELECT * FROM getfoo(1) AS t1;
136  fooid | foosubid | fooname 
137 -------+----------+---------
138      1 |        1 | Joe
139      1 |        2 | Ed
140 (2 rows)
141
142 CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1);
143 SELECT * FROM vw_getfoo;
144  fooid | foosubid | fooname 
145 -------+----------+---------
146      1 |        1 | Joe
147      1 |        2 | Ed
148 (2 rows)
149
150 -- sql, proretset = f, prorettype = record
151 DROP VIEW vw_getfoo;
152 DROP FUNCTION getfoo(int);
153 CREATE FUNCTION getfoo(int) RETURNS RECORD AS 'SELECT * FROM foo WHERE fooid = $1;' LANGUAGE SQL;
154 SELECT * FROM getfoo(1) AS t1(fooid int, foosubid int, fooname text);
155  fooid | foosubid | fooname 
156 -------+----------+---------
157      1 |        1 | Joe
158 (1 row)
159
160 CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1) AS 
161 (fooid int, foosubid int, fooname text);
162 SELECT * FROM vw_getfoo;
163  fooid | foosubid | fooname 
164 -------+----------+---------
165      1 |        1 | Joe
166 (1 row)
167
168 -- sql, proretset = t, prorettype = record
169 DROP VIEW vw_getfoo;
170 DROP FUNCTION getfoo(int);
171 CREATE FUNCTION getfoo(int) RETURNS setof record AS 'SELECT * FROM foo WHERE fooid = $1;' LANGUAGE SQL;
172 SELECT * FROM getfoo(1) AS t1(fooid int, foosubid int, fooname text);
173  fooid | foosubid | fooname 
174 -------+----------+---------
175      1 |        1 | Joe
176      1 |        2 | Ed
177 (2 rows)
178
179 CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1) AS
180 (fooid int, foosubid int, fooname text);
181 SELECT * FROM vw_getfoo;
182  fooid | foosubid | fooname 
183 -------+----------+---------
184      1 |        1 | Joe
185      1 |        2 | Ed
186 (2 rows)
187
188 -- plpgsql, proretset = f, prorettype = b
189 DROP VIEW vw_getfoo;
190 DROP FUNCTION getfoo(int);
191 CREATE FUNCTION getfoo(int) RETURNS int AS 'DECLARE fooint int; BEGIN SELECT fooid into fooint FROM foo WHERE fooid = $1; RETURN fooint; END;' LANGUAGE plpgsql;
192 SELECT * FROM getfoo(1) AS t1;
193  t1 
194 ----
195   1
196 (1 row)
197
198 CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1);
199 SELECT * FROM vw_getfoo;
200  getfoo 
201 --------
202       1
203 (1 row)
204
205 -- plpgsql, proretset = f, prorettype = c
206 DROP VIEW vw_getfoo;
207 DROP FUNCTION getfoo(int);
208 CREATE FUNCTION getfoo(int) RETURNS foo AS 'DECLARE footup foo%ROWTYPE; BEGIN SELECT * into footup FROM foo WHERE fooid = $1; RETURN footup; END;' LANGUAGE plpgsql;
209 SELECT * FROM getfoo(1) AS t1;
210  fooid | foosubid | fooname 
211 -------+----------+---------
212      1 |        1 | Joe
213 (1 row)
214
215 CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1);
216 SELECT * FROM vw_getfoo;
217  fooid | foosubid | fooname 
218 -------+----------+---------
219      1 |        1 | Joe
220 (1 row)
221
222 DROP VIEW vw_getfoo;
223 DROP FUNCTION getfoo(int);
224 DROP FUNCTION foot(int);
225 DROP TABLE foo2;
226 DROP TABLE foo;
227 -- Rescan tests --
228 CREATE TABLE foorescan (fooid int, foosubid int, fooname text, primary key(fooid,foosubid));
229 NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "foorescan_pkey" for table "foorescan"
230 INSERT INTO foorescan values(5000,1,'abc.5000.1');
231 INSERT INTO foorescan values(5001,1,'abc.5001.1');
232 INSERT INTO foorescan values(5002,1,'abc.5002.1');
233 INSERT INTO foorescan values(5003,1,'abc.5003.1');
234 INSERT INTO foorescan values(5004,1,'abc.5004.1');
235 INSERT INTO foorescan values(5005,1,'abc.5005.1');
236 INSERT INTO foorescan values(5006,1,'abc.5006.1');
237 INSERT INTO foorescan values(5007,1,'abc.5007.1');
238 INSERT INTO foorescan values(5008,1,'abc.5008.1');
239 INSERT INTO foorescan values(5009,1,'abc.5009.1');
240 INSERT INTO foorescan values(5000,2,'abc.5000.2');
241 INSERT INTO foorescan values(5001,2,'abc.5001.2');
242 INSERT INTO foorescan values(5002,2,'abc.5002.2');
243 INSERT INTO foorescan values(5003,2,'abc.5003.2');
244 INSERT INTO foorescan values(5004,2,'abc.5004.2');
245 INSERT INTO foorescan values(5005,2,'abc.5005.2');
246 INSERT INTO foorescan values(5006,2,'abc.5006.2');
247 INSERT INTO foorescan values(5007,2,'abc.5007.2');
248 INSERT INTO foorescan values(5008,2,'abc.5008.2');
249 INSERT INTO foorescan values(5009,2,'abc.5009.2');
250 INSERT INTO foorescan values(5000,3,'abc.5000.3');
251 INSERT INTO foorescan values(5001,3,'abc.5001.3');
252 INSERT INTO foorescan values(5002,3,'abc.5002.3');
253 INSERT INTO foorescan values(5003,3,'abc.5003.3');
254 INSERT INTO foorescan values(5004,3,'abc.5004.3');
255 INSERT INTO foorescan values(5005,3,'abc.5005.3');
256 INSERT INTO foorescan values(5006,3,'abc.5006.3');
257 INSERT INTO foorescan values(5007,3,'abc.5007.3');
258 INSERT INTO foorescan values(5008,3,'abc.5008.3');
259 INSERT INTO foorescan values(5009,3,'abc.5009.3');
260 INSERT INTO foorescan values(5000,4,'abc.5000.4');
261 INSERT INTO foorescan values(5001,4,'abc.5001.4');
262 INSERT INTO foorescan values(5002,4,'abc.5002.4');
263 INSERT INTO foorescan values(5003,4,'abc.5003.4');
264 INSERT INTO foorescan values(5004,4,'abc.5004.4');
265 INSERT INTO foorescan values(5005,4,'abc.5005.4');
266 INSERT INTO foorescan values(5006,4,'abc.5006.4');
267 INSERT INTO foorescan values(5007,4,'abc.5007.4');
268 INSERT INTO foorescan values(5008,4,'abc.5008.4');
269 INSERT INTO foorescan values(5009,4,'abc.5009.4');
270 INSERT INTO foorescan values(5000,5,'abc.5000.5');
271 INSERT INTO foorescan values(5001,5,'abc.5001.5');
272 INSERT INTO foorescan values(5002,5,'abc.5002.5');
273 INSERT INTO foorescan values(5003,5,'abc.5003.5');
274 INSERT INTO foorescan values(5004,5,'abc.5004.5');
275 INSERT INTO foorescan values(5005,5,'abc.5005.5');
276 INSERT INTO foorescan values(5006,5,'abc.5006.5');
277 INSERT INTO foorescan values(5007,5,'abc.5007.5');
278 INSERT INTO foorescan values(5008,5,'abc.5008.5');
279 INSERT INTO foorescan values(5009,5,'abc.5009.5');
280 CREATE FUNCTION foorescan(int,int) RETURNS setof foorescan AS 'SELECT * FROM foorescan WHERE fooid >= $1 and fooid < $2 ;' LANGUAGE SQL;
281 --invokes ExecFunctionReScan
282 SELECT * FROM foorescan f WHERE f.fooid IN (SELECT fooid FROM foorescan(5002,5004)) ORDER BY 1,2;
283  fooid | foosubid |  fooname   
284 -------+----------+------------
285   5002 |        1 | abc.5002.1
286   5002 |        2 | abc.5002.2
287   5002 |        3 | abc.5002.3
288   5002 |        4 | abc.5002.4
289   5002 |        5 | abc.5002.5
290   5003 |        1 | abc.5003.1
291   5003 |        2 | abc.5003.2
292   5003 |        3 | abc.5003.3
293   5003 |        4 | abc.5003.4
294   5003 |        5 | abc.5003.5
295 (10 rows)
296
297 CREATE VIEW vw_foorescan AS SELECT * FROM foorescan(5002,5004);
298 --invokes ExecFunctionReScan
299 SELECT * FROM foorescan f WHERE f.fooid IN (SELECT fooid FROM vw_foorescan) ORDER BY 1,2;
300  fooid | foosubid |  fooname   
301 -------+----------+------------
302   5002 |        1 | abc.5002.1
303   5002 |        2 | abc.5002.2
304   5002 |        3 | abc.5002.3
305   5002 |        4 | abc.5002.4
306   5002 |        5 | abc.5002.5
307   5003 |        1 | abc.5003.1
308   5003 |        2 | abc.5003.2
309   5003 |        3 | abc.5003.3
310   5003 |        4 | abc.5003.4
311   5003 |        5 | abc.5003.5
312 (10 rows)
313
314 CREATE TABLE barrescan (fooid int primary key);
315 NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "barrescan_pkey" for table "barrescan"
316 INSERT INTO barrescan values(5003);
317 INSERT INTO barrescan values(5004);
318 INSERT INTO barrescan values(5005);
319 INSERT INTO barrescan values(5006);
320 INSERT INTO barrescan values(5007);
321 INSERT INTO barrescan values(5008);
322 CREATE FUNCTION foorescan(int) RETURNS setof foorescan AS 'SELECT * FROM foorescan WHERE fooid = $1;' LANGUAGE SQL;
323 --invokes ExecFunctionReScan with chgParam != NULL
324 SELECT f.* FROM barrescan b, foorescan f WHERE f.fooid = b.fooid AND b.fooid IN (SELECT fooid FROM foorescan(b.fooid)) ORDER BY 1,2;
325  fooid | foosubid |  fooname   
326 -------+----------+------------
327   5003 |        1 | abc.5003.1
328   5003 |        2 | abc.5003.2
329   5003 |        3 | abc.5003.3
330   5003 |        4 | abc.5003.4
331   5003 |        5 | abc.5003.5
332   5004 |        1 | abc.5004.1
333   5004 |        2 | abc.5004.2
334   5004 |        3 | abc.5004.3
335   5004 |        4 | abc.5004.4
336   5004 |        5 | abc.5004.5
337   5005 |        1 | abc.5005.1
338   5005 |        2 | abc.5005.2
339   5005 |        3 | abc.5005.3
340   5005 |        4 | abc.5005.4
341   5005 |        5 | abc.5005.5
342   5006 |        1 | abc.5006.1
343   5006 |        2 | abc.5006.2
344   5006 |        3 | abc.5006.3
345   5006 |        4 | abc.5006.4
346   5006 |        5 | abc.5006.5
347   5007 |        1 | abc.5007.1
348   5007 |        2 | abc.5007.2
349   5007 |        3 | abc.5007.3
350   5007 |        4 | abc.5007.4
351   5007 |        5 | abc.5007.5
352   5008 |        1 | abc.5008.1
353   5008 |        2 | abc.5008.2
354   5008 |        3 | abc.5008.3
355   5008 |        4 | abc.5008.4
356   5008 |        5 | abc.5008.5
357 (30 rows)
358
359 SELECT b.fooid, max(f.foosubid) FROM barrescan b, foorescan f WHERE f.fooid = b.fooid AND b.fooid IN (SELECT fooid FROM foorescan(b.fooid)) GROUP BY b.fooid ORDER BY 1,2;
360  fooid | max 
361 -------+-----
362   5003 |   5
363   5004 |   5
364   5005 |   5
365   5006 |   5
366   5007 |   5
367   5008 |   5
368 (6 rows)
369
370 CREATE VIEW fooview1 AS SELECT f.* FROM barrescan b, foorescan f WHERE f.fooid = b.fooid AND b.fooid IN (SELECT fooid FROM foorescan(b.fooid)) ORDER BY 1,2;
371 SELECT * FROM fooview1 AS fv WHERE fv.fooid = 5004;
372  fooid | foosubid |  fooname   
373 -------+----------+------------
374   5004 |        1 | abc.5004.1
375   5004 |        2 | abc.5004.2
376   5004 |        3 | abc.5004.3
377   5004 |        4 | abc.5004.4
378   5004 |        5 | abc.5004.5
379 (5 rows)
380
381 CREATE VIEW fooview2 AS SELECT b.fooid, max(f.foosubid) AS maxsubid FROM barrescan b, foorescan f WHERE f.fooid = b.fooid AND b.fooid IN (SELECT fooid FROM foorescan(b.fooid)) GROUP BY b.fooid ORDER BY 1,2;
382 SELECT * FROM fooview2 AS fv WHERE fv.maxsubid = 5;
383  fooid | maxsubid 
384 -------+----------
385   5003 |        5
386   5004 |        5
387   5005 |        5
388   5006 |        5
389   5007 |        5
390   5008 |        5
391 (6 rows)
392
393 DROP VIEW vw_foorescan;
394 DROP VIEW fooview1;
395 DROP VIEW fooview2;
396 DROP FUNCTION foorescan(int,int);
397 DROP FUNCTION foorescan(int);
398 DROP TABLE foorescan;
399 DROP TABLE barrescan;
400 --
401 -- Test cases involving OUT parameters
402 --
403 CREATE FUNCTION foo(in f1 int, out f2 int)
404 AS 'select $1+1' LANGUAGE sql;
405 SELECT foo(42);
406  foo 
407 -----
408   43
409 (1 row)
410
411 SELECT * FROM foo(42);
412  f2 
413 ----
414  43
415 (1 row)
416
417 SELECT * FROM foo(42) AS p(x);
418  x  
419 ----
420  43
421 (1 row)
422
423 -- explicit spec of return type is OK
424 CREATE OR REPLACE FUNCTION foo(in f1 int, out f2 int) RETURNS int
425 AS 'select $1+1' LANGUAGE sql;
426 -- error, wrong result type
427 CREATE OR REPLACE FUNCTION foo(in f1 int, out f2 int) RETURNS float
428 AS 'select $1+1' LANGUAGE sql;
429 ERROR:  function result type must be integer because of OUT parameters
430 -- with multiple OUT params you must get a RECORD result
431 CREATE OR REPLACE FUNCTION foo(in f1 int, out f2 int, out f3 text) RETURNS int
432 AS 'select $1+1' LANGUAGE sql;
433 ERROR:  function result type must be record because of OUT parameters
434 CREATE OR REPLACE FUNCTION foo(in f1 int, out f2 int, out f3 text)
435 RETURNS record
436 AS 'select $1+1' LANGUAGE sql;
437 ERROR:  cannot change return type of existing function
438 HINT:  Use DROP FUNCTION first.
439 CREATE OR REPLACE FUNCTION foor(in f1 int, out f2 int, out text)
440 AS $$select $1-1, $1::text || 'z'$$ LANGUAGE sql;
441 SELECT f1, foor(f1) FROM int4_tbl;
442      f1      |            foor            
443 -------------+----------------------------
444            0 | (-1,0z)
445       123456 | (123455,123456z)
446      -123456 | (-123457,-123456z)
447   2147483647 | (2147483646,2147483647z)
448  -2147483647 | (-2147483648,-2147483647z)
449 (5 rows)
450
451 SELECT * FROM foor(42);
452  f2 | column2 
453 ----+---------
454  41 | 42z
455 (1 row)
456
457 SELECT * FROM foor(42) AS p(a,b);
458  a  |  b  
459 ----+-----
460  41 | 42z
461 (1 row)
462
463 CREATE OR REPLACE FUNCTION foob(in f1 int, inout f2 int, out text)
464 AS $$select $2-1, $1::text || 'z'$$ LANGUAGE sql;
465 SELECT f1, foob(f1, f1/2) FROM int4_tbl;
466      f1      |            foob            
467 -------------+----------------------------
468            0 | (-1,0z)
469       123456 | (61727,123456z)
470      -123456 | (-61729,-123456z)
471   2147483647 | (1073741822,2147483647z)
472  -2147483647 | (-1073741824,-2147483647z)
473 (5 rows)
474
475 SELECT * FROM foob(42, 99);
476  f2 | column2 
477 ----+---------
478  98 | 42z
479 (1 row)
480
481 SELECT * FROM foob(42, 99) AS p(a,b);
482  a  |  b  
483 ----+-----
484  98 | 42z
485 (1 row)
486
487 -- Can reference function with or without OUT params for DROP, etc
488 DROP FUNCTION foo(int);
489 DROP FUNCTION foor(in f2 int, out f1 int, out text);
490 DROP FUNCTION foob(in f1 int, inout f2 int);
491 --
492 -- For my next trick, polymorphic OUT parameters
493 --
494 CREATE FUNCTION dup (f1 anyelement, f2 out anyelement, f3 out anyarray)
495 AS 'select $1, array[$1,$1]' LANGUAGE sql;
496 SELECT dup(22);
497       dup       
498 ----------------
499  (22,"{22,22}")
500 (1 row)
501
502 SELECT dup('xyz');      -- fails
503 ERROR:  could not determine polymorphic type because input has type "unknown"
504 SELECT dup('xyz'::text);
505         dup        
506 -------------------
507  (xyz,"{xyz,xyz}")
508 (1 row)
509
510 SELECT * FROM dup('xyz'::text);
511  f2  |    f3     
512 -----+-----------
513  xyz | {xyz,xyz}
514 (1 row)
515
516 -- equivalent specification
517 CREATE OR REPLACE FUNCTION dup (inout f2 anyelement, out f3 anyarray)
518 AS 'select $1, array[$1,$1]' LANGUAGE sql;
519 SELECT dup(22);
520       dup       
521 ----------------
522  (22,"{22,22}")
523 (1 row)
524
525 DROP FUNCTION dup(anyelement);
526 -- fails, no way to deduce outputs
527 CREATE FUNCTION bad (f1 int, out f2 anyelement, out f3 anyarray)
528 AS 'select $1, array[$1,$1]' LANGUAGE sql;
529 ERROR:  cannot determine result data type
530 DETAIL:  A function returning a polymorphic type must have at least one polymorphic argument.
531 --
532 -- table functions
533 --
534 CREATE OR REPLACE FUNCTION foo()
535 RETURNS TABLE(a int)
536 AS $$ SELECT a FROM generate_series(1,5) a(a) $$ LANGUAGE sql;
537 SELECT * FROM foo();
538  a 
539 ---
540  1
541  2
542  3
543  4
544  5
545 (5 rows)
546
547 DROP FUNCTION foo();
548 CREATE OR REPLACE FUNCTION foo(int)
549 RETURNS TABLE(a int, b int)
550 AS $$ SELECT a, b
551          FROM generate_series(1,$1) a(a),
552               generate_series(1,$1) b(b) $$ LANGUAGE sql;
553 SELECT * FROM foo(3);
554  a | b 
555 ---+---
556  1 | 1
557  1 | 2
558  1 | 3
559  2 | 1
560  2 | 2
561  2 | 3
562  3 | 1
563  3 | 2
564  3 | 3
565 (9 rows)
566
567 DROP FUNCTION foo(int);