1 SELECT name, setting FROM pg_settings WHERE name LIKE 'enable%';
3 -------------------+---------
16 CREATE TABLE foo2(fooid int, f2 int);
17 INSERT INTO foo2 VALUES(1, 11);
18 INSERT INTO foo2 VALUES(2, 22);
19 INSERT INTO foo2 VALUES(1, 111);
20 CREATE FUNCTION foot(int) returns setof foo2 as 'SELECT * FROM foo2 WHERE fooid = $1;' LANGUAGE SQL;
21 -- supposed to fail with ERROR
22 select * from foo2, foot(foo2.fooid) z where foo2.f2 = z.f2;
23 ERROR: function expression in FROM cannot refer to other relations of same query level
24 LINE 1: select * from foo2, foot(foo2.fooid) z where foo2.f2 = z.f2;
26 -- function in subselect
27 select * from foo2 where f2 in (select f2 from foot(foo2.fooid) z where z.fooid = foo2.fooid) ORDER BY 1,2;
35 -- function in subselect
36 select * from foo2 where f2 in (select f2 from foot(1) z where z.fooid = foo2.fooid) ORDER BY 1,2;
43 -- function in subselect
44 select * from foo2 where f2 in (select f2 from foot(foo2.fooid) z where z.fooid = 1) ORDER BY 1,2;
52 select foot.fooid, foot.f2 from foot(sin(pi()/2)::int) ORDER BY 1,2;
59 CREATE TABLE foo (fooid int, foosubid int, fooname text, primary key(fooid,foosubid));
60 NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "foo_pkey" for table "foo"
61 INSERT INTO foo VALUES(1,1,'Joe');
62 INSERT INTO foo VALUES(1,2,'Ed');
63 INSERT INTO foo VALUES(2,1,'Mary');
64 -- sql, proretset = f, prorettype = b
65 CREATE FUNCTION getfoo(int) RETURNS int AS 'SELECT $1;' LANGUAGE SQL;
66 SELECT * FROM getfoo(1) AS t1;
72 CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1);
73 SELECT * FROM vw_getfoo;
79 -- sql, proretset = t, prorettype = b
81 DROP FUNCTION getfoo(int);
82 CREATE FUNCTION getfoo(int) RETURNS setof int AS 'SELECT fooid FROM foo WHERE fooid = $1;' LANGUAGE SQL;
83 SELECT * FROM getfoo(1) AS t1;
90 CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1);
91 SELECT * FROM vw_getfoo;
98 -- sql, proretset = t, prorettype = b
100 DROP FUNCTION getfoo(int);
101 CREATE FUNCTION getfoo(int) RETURNS setof text AS 'SELECT fooname FROM foo WHERE fooid = $1;' LANGUAGE SQL;
102 SELECT * FROM getfoo(1) AS t1;
109 CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1);
110 SELECT * FROM vw_getfoo;
117 -- sql, proretset = f, prorettype = c
119 DROP FUNCTION getfoo(int);
120 CREATE FUNCTION getfoo(int) RETURNS foo AS 'SELECT * FROM foo WHERE fooid = $1;' LANGUAGE SQL;
121 SELECT * FROM getfoo(1) AS t1;
122 fooid | foosubid | fooname
123 -------+----------+---------
127 CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1);
128 SELECT * FROM vw_getfoo;
129 fooid | foosubid | fooname
130 -------+----------+---------
134 -- sql, proretset = t, prorettype = c
136 DROP FUNCTION getfoo(int);
137 CREATE FUNCTION getfoo(int) RETURNS setof foo AS 'SELECT * FROM foo WHERE fooid = $1;' LANGUAGE SQL;
138 SELECT * FROM getfoo(1) AS t1;
139 fooid | foosubid | fooname
140 -------+----------+---------
145 CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1);
146 SELECT * FROM vw_getfoo;
147 fooid | foosubid | fooname
148 -------+----------+---------
153 -- sql, proretset = f, prorettype = record
155 DROP FUNCTION getfoo(int);
156 CREATE FUNCTION getfoo(int) RETURNS RECORD AS 'SELECT * FROM foo WHERE fooid = $1;' LANGUAGE SQL;
157 SELECT * FROM getfoo(1) AS t1(fooid int, foosubid int, fooname text);
158 fooid | foosubid | fooname
159 -------+----------+---------
163 CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1) AS
164 (fooid int, foosubid int, fooname text);
165 SELECT * FROM vw_getfoo;
166 fooid | foosubid | fooname
167 -------+----------+---------
171 -- sql, proretset = t, prorettype = record
173 DROP FUNCTION getfoo(int);
174 CREATE FUNCTION getfoo(int) RETURNS setof record AS 'SELECT * FROM foo WHERE fooid = $1;' LANGUAGE SQL;
175 SELECT * FROM getfoo(1) AS t1(fooid int, foosubid int, fooname text);
176 fooid | foosubid | fooname
177 -------+----------+---------
182 CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1) AS
183 (fooid int, foosubid int, fooname text);
184 SELECT * FROM vw_getfoo;
185 fooid | foosubid | fooname
186 -------+----------+---------
191 -- plpgsql, proretset = f, prorettype = b
193 DROP FUNCTION getfoo(int);
194 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;
195 SELECT * FROM getfoo(1) AS t1;
201 CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1);
202 SELECT * FROM vw_getfoo;
208 -- plpgsql, proretset = f, prorettype = c
210 DROP FUNCTION getfoo(int);
211 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;
212 SELECT * FROM getfoo(1) AS t1;
213 fooid | foosubid | fooname
214 -------+----------+---------
218 CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1);
219 SELECT * FROM vw_getfoo;
220 fooid | foosubid | fooname
221 -------+----------+---------
226 DROP FUNCTION getfoo(int);
227 DROP FUNCTION foot(int);
231 CREATE TABLE foorescan (fooid int, foosubid int, fooname text, primary key(fooid,foosubid));
232 NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "foorescan_pkey" for table "foorescan"
233 INSERT INTO foorescan values(5000,1,'abc.5000.1');
234 INSERT INTO foorescan values(5001,1,'abc.5001.1');
235 INSERT INTO foorescan values(5002,1,'abc.5002.1');
236 INSERT INTO foorescan values(5003,1,'abc.5003.1');
237 INSERT INTO foorescan values(5004,1,'abc.5004.1');
238 INSERT INTO foorescan values(5005,1,'abc.5005.1');
239 INSERT INTO foorescan values(5006,1,'abc.5006.1');
240 INSERT INTO foorescan values(5007,1,'abc.5007.1');
241 INSERT INTO foorescan values(5008,1,'abc.5008.1');
242 INSERT INTO foorescan values(5009,1,'abc.5009.1');
243 INSERT INTO foorescan values(5000,2,'abc.5000.2');
244 INSERT INTO foorescan values(5001,2,'abc.5001.2');
245 INSERT INTO foorescan values(5002,2,'abc.5002.2');
246 INSERT INTO foorescan values(5003,2,'abc.5003.2');
247 INSERT INTO foorescan values(5004,2,'abc.5004.2');
248 INSERT INTO foorescan values(5005,2,'abc.5005.2');
249 INSERT INTO foorescan values(5006,2,'abc.5006.2');
250 INSERT INTO foorescan values(5007,2,'abc.5007.2');
251 INSERT INTO foorescan values(5008,2,'abc.5008.2');
252 INSERT INTO foorescan values(5009,2,'abc.5009.2');
253 INSERT INTO foorescan values(5000,3,'abc.5000.3');
254 INSERT INTO foorescan values(5001,3,'abc.5001.3');
255 INSERT INTO foorescan values(5002,3,'abc.5002.3');
256 INSERT INTO foorescan values(5003,3,'abc.5003.3');
257 INSERT INTO foorescan values(5004,3,'abc.5004.3');
258 INSERT INTO foorescan values(5005,3,'abc.5005.3');
259 INSERT INTO foorescan values(5006,3,'abc.5006.3');
260 INSERT INTO foorescan values(5007,3,'abc.5007.3');
261 INSERT INTO foorescan values(5008,3,'abc.5008.3');
262 INSERT INTO foorescan values(5009,3,'abc.5009.3');
263 INSERT INTO foorescan values(5000,4,'abc.5000.4');
264 INSERT INTO foorescan values(5001,4,'abc.5001.4');
265 INSERT INTO foorescan values(5002,4,'abc.5002.4');
266 INSERT INTO foorescan values(5003,4,'abc.5003.4');
267 INSERT INTO foorescan values(5004,4,'abc.5004.4');
268 INSERT INTO foorescan values(5005,4,'abc.5005.4');
269 INSERT INTO foorescan values(5006,4,'abc.5006.4');
270 INSERT INTO foorescan values(5007,4,'abc.5007.4');
271 INSERT INTO foorescan values(5008,4,'abc.5008.4');
272 INSERT INTO foorescan values(5009,4,'abc.5009.4');
273 INSERT INTO foorescan values(5000,5,'abc.5000.5');
274 INSERT INTO foorescan values(5001,5,'abc.5001.5');
275 INSERT INTO foorescan values(5002,5,'abc.5002.5');
276 INSERT INTO foorescan values(5003,5,'abc.5003.5');
277 INSERT INTO foorescan values(5004,5,'abc.5004.5');
278 INSERT INTO foorescan values(5005,5,'abc.5005.5');
279 INSERT INTO foorescan values(5006,5,'abc.5006.5');
280 INSERT INTO foorescan values(5007,5,'abc.5007.5');
281 INSERT INTO foorescan values(5008,5,'abc.5008.5');
282 INSERT INTO foorescan values(5009,5,'abc.5009.5');
283 CREATE FUNCTION foorescan(int,int) RETURNS setof foorescan AS 'SELECT * FROM foorescan WHERE fooid >= $1 and fooid < $2 ;' LANGUAGE SQL;
284 --invokes ExecReScanFunctionScan
285 SELECT * FROM foorescan f WHERE f.fooid IN (SELECT fooid FROM foorescan(5002,5004)) ORDER BY 1,2;
286 fooid | foosubid | fooname
287 -------+----------+------------
288 5002 | 1 | abc.5002.1
289 5002 | 2 | abc.5002.2
290 5002 | 3 | abc.5002.3
291 5002 | 4 | abc.5002.4
292 5002 | 5 | abc.5002.5
293 5003 | 1 | abc.5003.1
294 5003 | 2 | abc.5003.2
295 5003 | 3 | abc.5003.3
296 5003 | 4 | abc.5003.4
297 5003 | 5 | abc.5003.5
300 CREATE VIEW vw_foorescan AS SELECT * FROM foorescan(5002,5004);
301 --invokes ExecReScanFunctionScan
302 SELECT * FROM foorescan f WHERE f.fooid IN (SELECT fooid FROM vw_foorescan) ORDER BY 1,2;
303 fooid | foosubid | fooname
304 -------+----------+------------
305 5002 | 1 | abc.5002.1
306 5002 | 2 | abc.5002.2
307 5002 | 3 | abc.5002.3
308 5002 | 4 | abc.5002.4
309 5002 | 5 | abc.5002.5
310 5003 | 1 | abc.5003.1
311 5003 | 2 | abc.5003.2
312 5003 | 3 | abc.5003.3
313 5003 | 4 | abc.5003.4
314 5003 | 5 | abc.5003.5
317 CREATE TABLE barrescan (fooid int primary key);
318 NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "barrescan_pkey" for table "barrescan"
319 INSERT INTO barrescan values(5003);
320 INSERT INTO barrescan values(5004);
321 INSERT INTO barrescan values(5005);
322 INSERT INTO barrescan values(5006);
323 INSERT INTO barrescan values(5007);
324 INSERT INTO barrescan values(5008);
325 CREATE FUNCTION foorescan(int) RETURNS setof foorescan AS 'SELECT * FROM foorescan WHERE fooid = $1;' LANGUAGE SQL;
326 --invokes ExecReScanFunctionScan with chgParam != NULL
327 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;
328 fooid | foosubid | fooname
329 -------+----------+------------
330 5003 | 1 | abc.5003.1
331 5003 | 2 | abc.5003.2
332 5003 | 3 | abc.5003.3
333 5003 | 4 | abc.5003.4
334 5003 | 5 | abc.5003.5
335 5004 | 1 | abc.5004.1
336 5004 | 2 | abc.5004.2
337 5004 | 3 | abc.5004.3
338 5004 | 4 | abc.5004.4
339 5004 | 5 | abc.5004.5
340 5005 | 1 | abc.5005.1
341 5005 | 2 | abc.5005.2
342 5005 | 3 | abc.5005.3
343 5005 | 4 | abc.5005.4
344 5005 | 5 | abc.5005.5
345 5006 | 1 | abc.5006.1
346 5006 | 2 | abc.5006.2
347 5006 | 3 | abc.5006.3
348 5006 | 4 | abc.5006.4
349 5006 | 5 | abc.5006.5
350 5007 | 1 | abc.5007.1
351 5007 | 2 | abc.5007.2
352 5007 | 3 | abc.5007.3
353 5007 | 4 | abc.5007.4
354 5007 | 5 | abc.5007.5
355 5008 | 1 | abc.5008.1
356 5008 | 2 | abc.5008.2
357 5008 | 3 | abc.5008.3
358 5008 | 4 | abc.5008.4
359 5008 | 5 | abc.5008.5
362 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;
373 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;
374 SELECT * FROM fooview1 AS fv WHERE fv.fooid = 5004;
375 fooid | foosubid | fooname
376 -------+----------+------------
377 5004 | 1 | abc.5004.1
378 5004 | 2 | abc.5004.2
379 5004 | 3 | abc.5004.3
380 5004 | 4 | abc.5004.4
381 5004 | 5 | abc.5004.5
384 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;
385 SELECT * FROM fooview2 AS fv WHERE fv.maxsubid = 5;
396 DROP VIEW vw_foorescan;
399 DROP FUNCTION foorescan(int,int);
400 DROP FUNCTION foorescan(int);
401 DROP TABLE foorescan;
402 DROP TABLE barrescan;
404 -- Test cases involving OUT parameters
406 CREATE FUNCTION foo(in f1 int, out f2 int)
407 AS 'select $1+1' LANGUAGE sql;
414 SELECT * FROM foo(42);
420 SELECT * FROM foo(42) AS p(x);
426 -- explicit spec of return type is OK
427 CREATE OR REPLACE FUNCTION foo(in f1 int, out f2 int) RETURNS int
428 AS 'select $1+1' LANGUAGE sql;
429 -- error, wrong result type
430 CREATE OR REPLACE FUNCTION foo(in f1 int, out f2 int) RETURNS float
431 AS 'select $1+1' LANGUAGE sql;
432 ERROR: function result type must be integer because of OUT parameters
433 -- with multiple OUT params you must get a RECORD result
434 CREATE OR REPLACE FUNCTION foo(in f1 int, out f2 int, out f3 text) RETURNS int
435 AS 'select $1+1' LANGUAGE sql;
436 ERROR: function result type must be record because of OUT parameters
437 CREATE OR REPLACE FUNCTION foo(in f1 int, out f2 int, out f3 text)
439 AS 'select $1+1' LANGUAGE sql;
440 ERROR: cannot change return type of existing function
441 HINT: Use DROP FUNCTION first.
442 CREATE OR REPLACE FUNCTION foor(in f1 int, out f2 int, out text)
443 AS $$select $1-1, $1::text || 'z'$$ LANGUAGE sql;
444 SELECT f1, foor(f1) FROM int4_tbl;
446 -------------+----------------------------
448 123456 | (123455,123456z)
449 -123456 | (-123457,-123456z)
450 2147483647 | (2147483646,2147483647z)
451 -2147483647 | (-2147483648,-2147483647z)
454 SELECT * FROM foor(42);
460 SELECT * FROM foor(42) AS p(a,b);
466 CREATE OR REPLACE FUNCTION foob(in f1 int, inout f2 int, out text)
467 AS $$select $2-1, $1::text || 'z'$$ LANGUAGE sql;
468 SELECT f1, foob(f1, f1/2) FROM int4_tbl;
470 -------------+----------------------------
472 123456 | (61727,123456z)
473 -123456 | (-61729,-123456z)
474 2147483647 | (1073741822,2147483647z)
475 -2147483647 | (-1073741824,-2147483647z)
478 SELECT * FROM foob(42, 99);
484 SELECT * FROM foob(42, 99) AS p(a,b);
490 -- Can reference function with or without OUT params for DROP, etc
491 DROP FUNCTION foo(int);
492 DROP FUNCTION foor(in f2 int, out f1 int, out text);
493 DROP FUNCTION foob(in f1 int, inout f2 int);
495 -- For my next trick, polymorphic OUT parameters
497 CREATE FUNCTION dup (f1 anyelement, f2 out anyelement, f3 out anyarray)
498 AS 'select $1, array[$1,$1]' LANGUAGE sql;
505 SELECT dup('xyz'); -- fails
506 ERROR: could not determine polymorphic type because input has type "unknown"
507 SELECT dup('xyz'::text);
513 SELECT * FROM dup('xyz'::text);
519 -- fails, as we are attempting to rename first argument
520 CREATE OR REPLACE FUNCTION dup (inout f2 anyelement, out f3 anyarray)
521 AS 'select $1, array[$1,$1]' LANGUAGE sql;
522 ERROR: cannot change name of input parameter "f1"
523 HINT: Use DROP FUNCTION first.
524 DROP FUNCTION dup(anyelement);
525 -- equivalent behavior, though different name exposed for input arg
526 CREATE OR REPLACE FUNCTION dup (inout f2 anyelement, out f3 anyarray)
527 AS 'select $1, array[$1,$1]' LANGUAGE sql;
534 DROP FUNCTION dup(anyelement);
535 -- fails, no way to deduce outputs
536 CREATE FUNCTION bad (f1 int, out f2 anyelement, out f3 anyarray)
537 AS 'select $1, array[$1,$1]' LANGUAGE sql;
538 ERROR: cannot determine result data type
539 DETAIL: A function returning a polymorphic type must have at least one polymorphic argument.
543 CREATE OR REPLACE FUNCTION foo()
545 AS $$ SELECT a FROM generate_series(1,5) a(a) $$ LANGUAGE sql;
557 CREATE OR REPLACE FUNCTION foo(int)
558 RETURNS TABLE(a int, b int)
560 FROM generate_series(1,$1) a(a),
561 generate_series(1,$1) b(b) $$ LANGUAGE sql;
562 SELECT * FROM foo(3);
576 DROP FUNCTION foo(int);
578 -- some tests on SQL functions with RETURNING
580 create temp table tt(f1 serial, data text);
581 NOTICE: CREATE TABLE will create implicit sequence "tt_f1_seq" for serial column "tt.f1"
582 create function insert_tt(text) returns int as
583 $$ insert into tt(data) values($1) returning f1 $$
585 select insert_tt('foo');
591 select insert_tt('bar');
604 -- insert will execute to completion even if function needs just 1 row
605 create or replace function insert_tt(text) returns int as
606 $$ insert into tt(data) values($1),($1||$1) returning f1 $$
608 select insert_tt('fool');
623 -- setof does what's expected
624 create or replace function insert_tt2(text,text) returns setof int as
625 $$ insert into tt(data) values($1),($2) returning f1 $$
627 select insert_tt2('foolish','barrish');
634 select * from insert_tt2('baz','quux');
654 -- limit doesn't prevent execution to completion
655 select insert_tt2('foolish','barrish') limit 1;
676 -- triggers will fire, too
677 create function noticetrigger() returns trigger as $$
679 raise notice 'noticetrigger % %', new.f1, new.data;
681 end $$ language plpgsql;
682 create trigger tnoticetrigger after insert on tt for each row
683 execute procedure noticetrigger();
684 select insert_tt2('foolme','barme') limit 1;
685 NOTICE: noticetrigger 11 foolme
686 CONTEXT: SQL function "insert_tt2" statement 1
687 NOTICE: noticetrigger 12 barme
688 CONTEXT: SQL function "insert_tt2" statement 1
712 create temp table tt_log(f1 int, data text);
713 create rule insert_tt_rule as on insert to tt do also
714 insert into tt_log values(new.*);
715 select insert_tt2('foollog','barlog') limit 1;
716 NOTICE: noticetrigger 13 foollog
717 CONTEXT: SQL function "insert_tt2" statement 1
718 NOTICE: noticetrigger 14 barlog
719 CONTEXT: SQL function "insert_tt2" statement 1
744 -- note that nextval() gets executed a second time in the rule expansion,
745 -- which is expected.
746 select * from tt_log;
753 -- test case for a whole-row-variable bug
754 create function foo1(n integer, out a text, out b text)
757 as $$ select 'foo ' || i, 'bar ' || i from generate_series(1,$1) i $$;
759 select t.a, t, t.a from foo1(10000) t limit 1;
761 -------+-------------------+-------
762 foo 1 | ("foo 1","bar 1") | foo 1
766 select t.a, t, t.a from foo1(10000) t limit 1;
768 -------+-------------------+-------
769 foo 1 | ("foo 1","bar 1") | foo 1
772 drop function foo1(n integer);
773 -- test use of SQL functions returning record
774 -- this is supported in some cases where the query doesn't specify
775 -- the actual record type ...
776 create function array_to_set(anyarray) returns setof record as $$
777 select i AS "index", $1[i] AS "value" from generate_subscripts($1, 1) i
778 $$ language sql strict immutable;
779 select array_to_set(array['one', 'two']);
786 select * from array_to_set(array['one', 'two']) as t(f1 int,f2 text);
793 select * from array_to_set(array['one', 'two']); -- fail
794 ERROR: a column definition list is required for functions returning "record"
795 LINE 1: select * from array_to_set(array['one', 'two']);
797 create temp table foo(f1 int8, f2 int8);
798 create function testfoo() returns record as $$
799 insert into foo values (1,2) returning *;
807 select * from testfoo() as t(f1 int8,f2 int8);
813 select * from testfoo(); -- fail
814 ERROR: a column definition list is required for functions returning "record"
815 LINE 1: select * from testfoo();
817 drop function testfoo();
818 create function testfoo() returns setof record as $$
819 insert into foo values (1,2), (3,4) returning *;
828 select * from testfoo() as t(f1 int8,f2 int8);
835 select * from testfoo(); -- fail
836 ERROR: a column definition list is required for functions returning "record"
837 LINE 1: select * from testfoo();
839 drop function testfoo();
841 -- Check some cases involving dropped columns in a rowtype result
843 create temp table users (userid text, email text, todrop bool, enabled bool);
844 insert into users values ('id','email',true,true);
845 insert into users values ('id2','email2',true,true);
846 alter table users drop column todrop;
847 create or replace function get_first_user() returns users as
848 $$ SELECT * FROM users ORDER BY userid LIMIT 1; $$
850 SELECT get_first_user();
856 SELECT * FROM get_first_user();
857 userid | email | enabled
858 --------+-------+---------
862 create or replace function get_users() returns setof users as
863 $$ SELECT * FROM users ORDER BY userid; $$
872 SELECT * FROM get_users();
873 userid | email | enabled
874 --------+--------+---------
879 drop function get_first_user();
880 drop function get_users();
882 -- this won't get inlined because of type coercion, but it shouldn't fail
883 create or replace function foobar() returns setof text as
884 $$ select 'foo'::varchar union all select 'bar'::varchar ; $$
893 select * from foobar();
900 drop function foobar();