2012-02-14 04:20:27 +01:00
|
|
|
--
|
|
|
|
-- CREATE FUNCTION
|
|
|
|
--
|
2018-03-16 17:48:13 +01:00
|
|
|
-- Assorted tests using SQL-language functions
|
2012-02-14 04:20:27 +01:00
|
|
|
--
|
2018-03-16 17:48:13 +01:00
|
|
|
-- All objects made in this test are in temp_func_test schema
|
2016-07-18 00:42:31 +02:00
|
|
|
CREATE USER regress_unpriv_user;
|
2012-02-14 04:20:27 +01:00
|
|
|
CREATE SCHEMA temp_func_test;
|
2012-02-15 16:56:26 +01:00
|
|
|
GRANT ALL ON SCHEMA temp_func_test TO public;
|
2012-02-14 04:20:27 +01:00
|
|
|
SET search_path TO temp_func_test, public;
|
|
|
|
--
|
2018-03-16 17:48:13 +01:00
|
|
|
-- Make sanity checks on the pg_proc entries created by CREATE FUNCTION
|
|
|
|
--
|
|
|
|
--
|
2012-05-15 21:19:04 +02:00
|
|
|
-- ARGUMENT and RETURN TYPES
|
2012-02-14 04:20:27 +01:00
|
|
|
--
|
|
|
|
CREATE FUNCTION functest_A_1(text, date) RETURNS bool LANGUAGE 'sql'
|
|
|
|
AS 'SELECT $1 = ''abcd'' AND $2 > ''2001-01-01''';
|
|
|
|
CREATE FUNCTION functest_A_2(text[]) RETURNS int LANGUAGE 'sql'
|
2020-09-05 13:28:05 +02:00
|
|
|
AS 'SELECT $1[1]::int';
|
2012-02-14 04:20:27 +01:00
|
|
|
CREATE FUNCTION functest_A_3() RETURNS bool LANGUAGE 'sql'
|
|
|
|
AS 'SELECT false';
|
|
|
|
SELECT proname, prorettype::regtype, proargtypes::regtype[] FROM pg_proc
|
|
|
|
WHERE oid in ('functest_A_1'::regproc,
|
|
|
|
'functest_A_2'::regproc,
|
2012-02-14 04:49:07 +01:00
|
|
|
'functest_A_3'::regproc) ORDER BY proname;
|
2012-02-14 04:20:27 +01:00
|
|
|
proname | prorettype | proargtypes
|
|
|
|
--------------+------------+-------------------
|
|
|
|
functest_a_1 | boolean | [0:1]={text,date}
|
|
|
|
functest_a_2 | integer | [0:0]={text[]}
|
|
|
|
functest_a_3 | boolean | {}
|
|
|
|
(3 rows)
|
|
|
|
|
2020-09-05 13:28:05 +02:00
|
|
|
SELECT functest_A_1('abcd', '2020-01-01');
|
|
|
|
functest_a_1
|
|
|
|
--------------
|
|
|
|
t
|
|
|
|
(1 row)
|
|
|
|
|
|
|
|
SELECT functest_A_2(ARRAY['1', '2', '3']);
|
|
|
|
functest_a_2
|
|
|
|
--------------
|
|
|
|
1
|
|
|
|
(1 row)
|
|
|
|
|
|
|
|
SELECT functest_A_3();
|
|
|
|
functest_a_3
|
|
|
|
--------------
|
|
|
|
f
|
|
|
|
(1 row)
|
|
|
|
|
2012-02-14 04:20:27 +01:00
|
|
|
--
|
|
|
|
-- IMMUTABLE | STABLE | VOLATILE
|
|
|
|
--
|
|
|
|
CREATE FUNCTION functest_B_1(int) RETURNS bool LANGUAGE 'sql'
|
|
|
|
AS 'SELECT $1 > 0';
|
|
|
|
CREATE FUNCTION functest_B_2(int) RETURNS bool LANGUAGE 'sql'
|
|
|
|
IMMUTABLE AS 'SELECT $1 > 0';
|
|
|
|
CREATE FUNCTION functest_B_3(int) RETURNS bool LANGUAGE 'sql'
|
|
|
|
STABLE AS 'SELECT $1 = 0';
|
|
|
|
CREATE FUNCTION functest_B_4(int) RETURNS bool LANGUAGE 'sql'
|
|
|
|
VOLATILE AS 'SELECT $1 < 0';
|
|
|
|
SELECT proname, provolatile FROM pg_proc
|
|
|
|
WHERE oid in ('functest_B_1'::regproc,
|
|
|
|
'functest_B_2'::regproc,
|
|
|
|
'functest_B_3'::regproc,
|
2012-02-14 04:49:07 +01:00
|
|
|
'functest_B_4'::regproc) ORDER BY proname;
|
2012-02-14 04:20:27 +01:00
|
|
|
proname | provolatile
|
|
|
|
--------------+-------------
|
|
|
|
functest_b_1 | v
|
|
|
|
functest_b_2 | i
|
|
|
|
functest_b_3 | s
|
|
|
|
functest_b_4 | v
|
|
|
|
(4 rows)
|
|
|
|
|
|
|
|
ALTER FUNCTION functest_B_2(int) VOLATILE;
|
|
|
|
ALTER FUNCTION functest_B_3(int) COST 100; -- unrelated change, no effect
|
|
|
|
SELECT proname, provolatile FROM pg_proc
|
|
|
|
WHERE oid in ('functest_B_1'::regproc,
|
|
|
|
'functest_B_2'::regproc,
|
|
|
|
'functest_B_3'::regproc,
|
2012-02-14 04:49:07 +01:00
|
|
|
'functest_B_4'::regproc) ORDER BY proname;
|
2012-02-14 04:20:27 +01:00
|
|
|
proname | provolatile
|
|
|
|
--------------+-------------
|
|
|
|
functest_b_1 | v
|
|
|
|
functest_b_2 | v
|
|
|
|
functest_b_3 | s
|
|
|
|
functest_b_4 | v
|
|
|
|
(4 rows)
|
|
|
|
|
|
|
|
--
|
|
|
|
-- SECURITY DEFINER | INVOKER
|
|
|
|
--
|
2018-02-12 19:47:18 +01:00
|
|
|
CREATE FUNCTION functest_C_1(int) RETURNS bool LANGUAGE 'sql'
|
2012-02-14 04:20:27 +01:00
|
|
|
AS 'SELECT $1 > 0';
|
2018-02-12 19:47:18 +01:00
|
|
|
CREATE FUNCTION functest_C_2(int) RETURNS bool LANGUAGE 'sql'
|
2012-02-14 04:20:27 +01:00
|
|
|
SECURITY DEFINER AS 'SELECT $1 = 0';
|
2018-02-12 19:47:18 +01:00
|
|
|
CREATE FUNCTION functest_C_3(int) RETURNS bool LANGUAGE 'sql'
|
2012-02-14 04:20:27 +01:00
|
|
|
SECURITY INVOKER AS 'SELECT $1 < 0';
|
|
|
|
SELECT proname, prosecdef FROM pg_proc
|
2018-02-12 19:47:18 +01:00
|
|
|
WHERE oid in ('functest_C_1'::regproc,
|
|
|
|
'functest_C_2'::regproc,
|
|
|
|
'functest_C_3'::regproc) ORDER BY proname;
|
2012-02-14 04:20:27 +01:00
|
|
|
proname | prosecdef
|
|
|
|
--------------+-----------
|
2018-02-12 19:47:18 +01:00
|
|
|
functest_c_1 | f
|
|
|
|
functest_c_2 | t
|
|
|
|
functest_c_3 | f
|
2012-02-14 04:20:27 +01:00
|
|
|
(3 rows)
|
|
|
|
|
2018-02-12 19:47:18 +01:00
|
|
|
ALTER FUNCTION functest_C_1(int) IMMUTABLE; -- unrelated change, no effect
|
|
|
|
ALTER FUNCTION functest_C_2(int) SECURITY INVOKER;
|
|
|
|
ALTER FUNCTION functest_C_3(int) SECURITY DEFINER;
|
2012-02-14 04:20:27 +01:00
|
|
|
SELECT proname, prosecdef FROM pg_proc
|
2018-02-12 19:47:18 +01:00
|
|
|
WHERE oid in ('functest_C_1'::regproc,
|
|
|
|
'functest_C_2'::regproc,
|
|
|
|
'functest_C_3'::regproc) ORDER BY proname;
|
2012-02-14 04:20:27 +01:00
|
|
|
proname | prosecdef
|
|
|
|
--------------+-----------
|
2018-02-12 19:47:18 +01:00
|
|
|
functest_c_1 | f
|
|
|
|
functest_c_2 | f
|
|
|
|
functest_c_3 | t
|
2012-02-14 04:20:27 +01:00
|
|
|
(3 rows)
|
|
|
|
|
|
|
|
--
|
|
|
|
-- LEAKPROOF
|
|
|
|
--
|
2018-02-12 19:47:18 +01:00
|
|
|
CREATE FUNCTION functest_E_1(int) RETURNS bool LANGUAGE 'sql'
|
2012-02-14 04:20:27 +01:00
|
|
|
AS 'SELECT $1 > 100';
|
2018-02-12 19:47:18 +01:00
|
|
|
CREATE FUNCTION functest_E_2(int) RETURNS bool LANGUAGE 'sql'
|
2012-02-14 04:20:27 +01:00
|
|
|
LEAKPROOF AS 'SELECT $1 > 100';
|
|
|
|
SELECT proname, proleakproof FROM pg_proc
|
2018-02-12 19:47:18 +01:00
|
|
|
WHERE oid in ('functest_E_1'::regproc,
|
|
|
|
'functest_E_2'::regproc) ORDER BY proname;
|
2012-02-14 04:20:27 +01:00
|
|
|
proname | proleakproof
|
|
|
|
--------------+--------------
|
2018-02-12 19:47:18 +01:00
|
|
|
functest_e_1 | f
|
|
|
|
functest_e_2 | t
|
2012-02-14 04:20:27 +01:00
|
|
|
(2 rows)
|
|
|
|
|
2018-02-12 19:47:18 +01:00
|
|
|
ALTER FUNCTION functest_E_1(int) LEAKPROOF;
|
|
|
|
ALTER FUNCTION functest_E_2(int) STABLE; -- unrelated change, no effect
|
2012-02-14 04:20:27 +01:00
|
|
|
SELECT proname, proleakproof FROM pg_proc
|
2018-02-12 19:47:18 +01:00
|
|
|
WHERE oid in ('functest_E_1'::regproc,
|
|
|
|
'functest_E_2'::regproc) ORDER BY proname;
|
2012-02-14 04:20:27 +01:00
|
|
|
proname | proleakproof
|
|
|
|
--------------+--------------
|
2018-02-12 19:47:18 +01:00
|
|
|
functest_e_1 | t
|
|
|
|
functest_e_2 | t
|
2012-02-14 04:20:27 +01:00
|
|
|
(2 rows)
|
|
|
|
|
2018-03-16 17:48:13 +01:00
|
|
|
ALTER FUNCTION functest_E_2(int) NOT LEAKPROOF; -- remove leakproof attribute
|
2012-02-15 16:56:26 +01:00
|
|
|
SELECT proname, proleakproof FROM pg_proc
|
2018-02-12 19:47:18 +01:00
|
|
|
WHERE oid in ('functest_E_1'::regproc,
|
|
|
|
'functest_E_2'::regproc) ORDER BY proname;
|
2012-02-15 16:56:26 +01:00
|
|
|
proname | proleakproof
|
|
|
|
--------------+--------------
|
2018-02-12 19:47:18 +01:00
|
|
|
functest_e_1 | t
|
|
|
|
functest_e_2 | f
|
2012-02-15 16:56:26 +01:00
|
|
|
(2 rows)
|
|
|
|
|
2018-03-16 17:48:13 +01:00
|
|
|
-- it takes superuser privilege to turn on leakproof, but not to turn off
|
2018-02-12 19:47:18 +01:00
|
|
|
ALTER FUNCTION functest_E_1(int) OWNER TO regress_unpriv_user;
|
|
|
|
ALTER FUNCTION functest_E_2(int) OWNER TO regress_unpriv_user;
|
2016-07-18 00:42:31 +02:00
|
|
|
SET SESSION AUTHORIZATION regress_unpriv_user;
|
2012-02-15 16:56:26 +01:00
|
|
|
SET search_path TO temp_func_test, public;
|
2018-02-12 19:47:18 +01:00
|
|
|
ALTER FUNCTION functest_E_1(int) NOT LEAKPROOF;
|
|
|
|
ALTER FUNCTION functest_E_2(int) LEAKPROOF;
|
2012-02-15 16:56:26 +01:00
|
|
|
ERROR: only superuser can define a leakproof function
|
2018-02-12 19:47:18 +01:00
|
|
|
CREATE FUNCTION functest_E_3(int) RETURNS bool LANGUAGE 'sql'
|
2018-03-16 17:48:13 +01:00
|
|
|
LEAKPROOF AS 'SELECT $1 < 200'; -- fail
|
2012-02-15 16:56:26 +01:00
|
|
|
ERROR: only superuser can define a leakproof function
|
|
|
|
RESET SESSION AUTHORIZATION;
|
2012-02-14 04:20:27 +01:00
|
|
|
--
|
|
|
|
-- CALLED ON NULL INPUT | RETURNS NULL ON NULL INPUT | STRICT
|
|
|
|
--
|
2018-02-12 19:47:18 +01:00
|
|
|
CREATE FUNCTION functest_F_1(int) RETURNS bool LANGUAGE 'sql'
|
2012-02-14 04:20:27 +01:00
|
|
|
AS 'SELECT $1 > 50';
|
2018-02-12 19:47:18 +01:00
|
|
|
CREATE FUNCTION functest_F_2(int) RETURNS bool LANGUAGE 'sql'
|
2012-02-14 04:20:27 +01:00
|
|
|
CALLED ON NULL INPUT AS 'SELECT $1 = 50';
|
2018-02-12 19:47:18 +01:00
|
|
|
CREATE FUNCTION functest_F_3(int) RETURNS bool LANGUAGE 'sql'
|
2012-02-14 04:20:27 +01:00
|
|
|
RETURNS NULL ON NULL INPUT AS 'SELECT $1 < 50';
|
2018-02-12 19:47:18 +01:00
|
|
|
CREATE FUNCTION functest_F_4(int) RETURNS bool LANGUAGE 'sql'
|
2012-02-14 04:20:27 +01:00
|
|
|
STRICT AS 'SELECT $1 = 50';
|
|
|
|
SELECT proname, proisstrict FROM pg_proc
|
2018-02-12 19:47:18 +01:00
|
|
|
WHERE oid in ('functest_F_1'::regproc,
|
|
|
|
'functest_F_2'::regproc,
|
|
|
|
'functest_F_3'::regproc,
|
|
|
|
'functest_F_4'::regproc) ORDER BY proname;
|
2012-02-14 04:20:27 +01:00
|
|
|
proname | proisstrict
|
|
|
|
--------------+-------------
|
2018-02-12 19:47:18 +01:00
|
|
|
functest_f_1 | f
|
|
|
|
functest_f_2 | f
|
|
|
|
functest_f_3 | t
|
|
|
|
functest_f_4 | t
|
2012-02-14 04:20:27 +01:00
|
|
|
(4 rows)
|
|
|
|
|
2018-02-12 19:47:18 +01:00
|
|
|
ALTER FUNCTION functest_F_1(int) IMMUTABLE; -- unrelated change, no effect
|
|
|
|
ALTER FUNCTION functest_F_2(int) STRICT;
|
|
|
|
ALTER FUNCTION functest_F_3(int) CALLED ON NULL INPUT;
|
2012-02-14 04:20:27 +01:00
|
|
|
SELECT proname, proisstrict FROM pg_proc
|
2018-02-12 19:47:18 +01:00
|
|
|
WHERE oid in ('functest_F_1'::regproc,
|
|
|
|
'functest_F_2'::regproc,
|
|
|
|
'functest_F_3'::regproc,
|
|
|
|
'functest_F_4'::regproc) ORDER BY proname;
|
2012-02-14 04:20:27 +01:00
|
|
|
proname | proisstrict
|
|
|
|
--------------+-------------
|
2018-02-12 19:47:18 +01:00
|
|
|
functest_f_1 | f
|
|
|
|
functest_f_2 | t
|
|
|
|
functest_f_3 | f
|
|
|
|
functest_f_4 | t
|
2012-02-14 04:20:27 +01:00
|
|
|
(4 rows)
|
|
|
|
|
2018-02-12 20:03:04 +01:00
|
|
|
-- pg_get_functiondef tests
|
|
|
|
SELECT pg_get_functiondef('functest_A_1'::regproc);
|
|
|
|
pg_get_functiondef
|
|
|
|
--------------------------------------------------------------------
|
|
|
|
CREATE OR REPLACE FUNCTION temp_func_test.functest_a_1(text, date)+
|
|
|
|
RETURNS boolean +
|
|
|
|
LANGUAGE sql +
|
|
|
|
AS $function$SELECT $1 = 'abcd' AND $2 > '2001-01-01'$function$ +
|
|
|
|
|
|
|
|
(1 row)
|
|
|
|
|
|
|
|
SELECT pg_get_functiondef('functest_B_3'::regproc);
|
|
|
|
pg_get_functiondef
|
|
|
|
-----------------------------------------------------------------
|
|
|
|
CREATE OR REPLACE FUNCTION temp_func_test.functest_b_3(integer)+
|
|
|
|
RETURNS boolean +
|
|
|
|
LANGUAGE sql +
|
|
|
|
STABLE +
|
|
|
|
AS $function$SELECT $1 = 0$function$ +
|
|
|
|
|
|
|
|
(1 row)
|
|
|
|
|
|
|
|
SELECT pg_get_functiondef('functest_C_3'::regproc);
|
|
|
|
pg_get_functiondef
|
|
|
|
-----------------------------------------------------------------
|
|
|
|
CREATE OR REPLACE FUNCTION temp_func_test.functest_c_3(integer)+
|
|
|
|
RETURNS boolean +
|
|
|
|
LANGUAGE sql +
|
|
|
|
SECURITY DEFINER +
|
|
|
|
AS $function$SELECT $1 < 0$function$ +
|
|
|
|
|
|
|
|
(1 row)
|
|
|
|
|
|
|
|
SELECT pg_get_functiondef('functest_F_2'::regproc);
|
|
|
|
pg_get_functiondef
|
|
|
|
-----------------------------------------------------------------
|
|
|
|
CREATE OR REPLACE FUNCTION temp_func_test.functest_f_2(integer)+
|
|
|
|
RETURNS boolean +
|
|
|
|
LANGUAGE sql +
|
|
|
|
STRICT +
|
|
|
|
AS $function$SELECT $1 = 50$function$ +
|
|
|
|
|
|
|
|
(1 row)
|
|
|
|
|
2021-04-07 21:30:08 +02:00
|
|
|
--
|
|
|
|
-- SQL-standard body
|
|
|
|
--
|
|
|
|
CREATE FUNCTION functest_S_1(a text, b date) RETURNS boolean
|
|
|
|
LANGUAGE SQL
|
|
|
|
RETURN a = 'abcd' AND b > '2001-01-01';
|
|
|
|
CREATE FUNCTION functest_S_2(a text[]) RETURNS int
|
|
|
|
RETURN a[1]::int;
|
|
|
|
CREATE FUNCTION functest_S_3() RETURNS boolean
|
|
|
|
RETURN false;
|
|
|
|
CREATE FUNCTION functest_S_3a() RETURNS boolean
|
|
|
|
BEGIN ATOMIC
|
2021-06-08 17:59:34 +02:00
|
|
|
;;RETURN false;;
|
2021-04-07 21:30:08 +02:00
|
|
|
END;
|
|
|
|
CREATE FUNCTION functest_S_10(a text, b date) RETURNS boolean
|
|
|
|
LANGUAGE SQL
|
|
|
|
BEGIN ATOMIC
|
|
|
|
SELECT a = 'abcd' AND b > '2001-01-01';
|
|
|
|
END;
|
|
|
|
CREATE FUNCTION functest_S_13() RETURNS boolean
|
|
|
|
BEGIN ATOMIC
|
|
|
|
SELECT 1;
|
|
|
|
SELECT false;
|
|
|
|
END;
|
Fix display of SQL-standard function's arguments in INSERT/SELECT.
If a SQL-standard function body contains an INSERT ... SELECT statement,
any function parameters referenced within the SELECT were always printed
in $N style, rather than using the parameter name if any. While not
strictly incorrect, this wasn't the intention, and it's inconsistent
with the way that such parameters would be printed in any other kind
of statement.
The cause is that the recursion to get_query_def from
get_insert_query_def neglected to pass down the context->namespaces
list, passing constant NIL instead. This is a very ancient oversight,
but AFAICT it had no visible consequences before commit e717a9a18
added an outermost namespace with function parameters. We don't allow
INSERT ... SELECT as a sub-query, except in a top-level WITH clause,
where it couldn't contain any outer references that might need to access
upper namespaces. So although that's arguably a bug, I don't see any
point in changing it before v14.
In passing, harden the code added to get_parameter by e717a9a18 so that
it won't crash if a PARAM_EXTERN Param appears in an unexpected place.
Per report from Erki Eessaar. Code fix by me, regression test case
by Masahiko Sawada.
Discussion: https://postgr.es/m/AM9PR01MB8268347BED344848555167FAFE949@AM9PR01MB8268.eurprd01.prod.exchangelabs.com
2021-11-17 17:31:31 +01:00
|
|
|
-- check display of function argments in sub-SELECT
|
|
|
|
CREATE TABLE functest1 (i int);
|
|
|
|
CREATE FUNCTION functest_S_16(a int, b int) RETURNS void
|
|
|
|
LANGUAGE SQL
|
|
|
|
BEGIN ATOMIC
|
|
|
|
INSERT INTO functest1 SELECT a + $2;
|
|
|
|
END;
|
2021-04-07 21:30:08 +02:00
|
|
|
-- error: duplicate function body
|
|
|
|
CREATE FUNCTION functest_S_xxx(x int) RETURNS int
|
|
|
|
LANGUAGE SQL
|
|
|
|
AS $$ SELECT x * 2 $$
|
|
|
|
RETURN x * 3;
|
|
|
|
ERROR: duplicate function body specified
|
|
|
|
-- polymorphic arguments not allowed in this form
|
|
|
|
CREATE FUNCTION functest_S_xx(x anyarray) RETURNS anyelement
|
|
|
|
LANGUAGE SQL
|
|
|
|
RETURN x[1];
|
|
|
|
ERROR: SQL function with unquoted function body cannot have polymorphic arguments
|
2021-04-15 23:17:20 +02:00
|
|
|
-- check reporting of parse-analysis errors
|
|
|
|
CREATE FUNCTION functest_S_xx(x date) RETURNS boolean
|
|
|
|
LANGUAGE SQL
|
|
|
|
RETURN x > 1;
|
|
|
|
ERROR: operator does not exist: date > integer
|
2021-04-15 23:24:12 +02:00
|
|
|
LINE 3: RETURN x > 1;
|
|
|
|
^
|
2021-04-15 23:17:20 +02:00
|
|
|
HINT: No operator matches the given name and argument types. You might need to add explicit type casts.
|
2021-04-07 21:30:08 +02:00
|
|
|
-- tricky parsing
|
|
|
|
CREATE FUNCTION functest_S_15(x int) RETURNS boolean
|
|
|
|
LANGUAGE SQL
|
|
|
|
BEGIN ATOMIC
|
|
|
|
select case when x % 2 = 0 then true else false end;
|
|
|
|
END;
|
|
|
|
SELECT functest_S_1('abcd', '2020-01-01');
|
|
|
|
functest_s_1
|
|
|
|
--------------
|
|
|
|
t
|
|
|
|
(1 row)
|
|
|
|
|
|
|
|
SELECT functest_S_2(ARRAY['1', '2', '3']);
|
|
|
|
functest_s_2
|
|
|
|
--------------
|
|
|
|
1
|
|
|
|
(1 row)
|
|
|
|
|
|
|
|
SELECT functest_S_3();
|
|
|
|
functest_s_3
|
|
|
|
--------------
|
|
|
|
f
|
|
|
|
(1 row)
|
|
|
|
|
|
|
|
SELECT functest_S_10('abcd', '2020-01-01');
|
|
|
|
functest_s_10
|
|
|
|
---------------
|
|
|
|
t
|
|
|
|
(1 row)
|
|
|
|
|
|
|
|
SELECT functest_S_13();
|
|
|
|
functest_s_13
|
|
|
|
---------------
|
|
|
|
f
|
|
|
|
(1 row)
|
|
|
|
|
|
|
|
SELECT pg_get_functiondef('functest_S_1'::regproc);
|
|
|
|
pg_get_functiondef
|
|
|
|
------------------------------------------------------------------------
|
|
|
|
CREATE OR REPLACE FUNCTION temp_func_test.functest_s_1(a text, b date)+
|
|
|
|
RETURNS boolean +
|
|
|
|
LANGUAGE sql +
|
|
|
|
RETURN ((a = 'abcd'::text) AND (b > '01-01-2001'::date)) +
|
|
|
|
|
|
|
|
(1 row)
|
|
|
|
|
|
|
|
SELECT pg_get_functiondef('functest_S_2'::regproc);
|
|
|
|
pg_get_functiondef
|
|
|
|
------------------------------------------------------------------
|
|
|
|
CREATE OR REPLACE FUNCTION temp_func_test.functest_s_2(a text[])+
|
|
|
|
RETURNS integer +
|
|
|
|
LANGUAGE sql +
|
|
|
|
RETURN ((a)[1])::integer +
|
|
|
|
|
|
|
|
(1 row)
|
|
|
|
|
|
|
|
SELECT pg_get_functiondef('functest_S_3'::regproc);
|
|
|
|
pg_get_functiondef
|
|
|
|
----------------------------------------------------------
|
|
|
|
CREATE OR REPLACE FUNCTION temp_func_test.functest_s_3()+
|
|
|
|
RETURNS boolean +
|
|
|
|
LANGUAGE sql +
|
|
|
|
RETURN false +
|
|
|
|
|
|
|
|
(1 row)
|
|
|
|
|
|
|
|
SELECT pg_get_functiondef('functest_S_3a'::regproc);
|
|
|
|
pg_get_functiondef
|
|
|
|
-----------------------------------------------------------
|
|
|
|
CREATE OR REPLACE FUNCTION temp_func_test.functest_s_3a()+
|
|
|
|
RETURNS boolean +
|
|
|
|
LANGUAGE sql +
|
|
|
|
BEGIN ATOMIC +
|
|
|
|
RETURN false; +
|
|
|
|
END +
|
|
|
|
|
|
|
|
(1 row)
|
|
|
|
|
|
|
|
SELECT pg_get_functiondef('functest_S_10'::regproc);
|
|
|
|
pg_get_functiondef
|
|
|
|
-------------------------------------------------------------------------
|
|
|
|
CREATE OR REPLACE FUNCTION temp_func_test.functest_s_10(a text, b date)+
|
|
|
|
RETURNS boolean +
|
|
|
|
LANGUAGE sql +
|
|
|
|
BEGIN ATOMIC +
|
|
|
|
SELECT ((a = 'abcd'::text) AND (b > '01-01-2001'::date)); +
|
|
|
|
END +
|
|
|
|
|
|
|
|
(1 row)
|
|
|
|
|
|
|
|
SELECT pg_get_functiondef('functest_S_13'::regproc);
|
|
|
|
pg_get_functiondef
|
|
|
|
-----------------------------------------------------------
|
|
|
|
CREATE OR REPLACE FUNCTION temp_func_test.functest_s_13()+
|
|
|
|
RETURNS boolean +
|
|
|
|
LANGUAGE sql +
|
|
|
|
BEGIN ATOMIC +
|
|
|
|
SELECT 1; +
|
|
|
|
SELECT false AS bool; +
|
|
|
|
END +
|
|
|
|
|
|
|
|
(1 row)
|
|
|
|
|
|
|
|
SELECT pg_get_functiondef('functest_S_15'::regproc);
|
|
|
|
pg_get_functiondef
|
|
|
|
--------------------------------------------------------------------
|
|
|
|
CREATE OR REPLACE FUNCTION temp_func_test.functest_s_15(x integer)+
|
|
|
|
RETURNS boolean +
|
|
|
|
LANGUAGE sql +
|
|
|
|
BEGIN ATOMIC +
|
|
|
|
SELECT +
|
|
|
|
CASE +
|
|
|
|
WHEN ((x % 2) = 0) THEN true +
|
|
|
|
ELSE false +
|
|
|
|
END AS "case"; +
|
|
|
|
END +
|
|
|
|
|
|
|
|
(1 row)
|
|
|
|
|
Fix display of SQL-standard function's arguments in INSERT/SELECT.
If a SQL-standard function body contains an INSERT ... SELECT statement,
any function parameters referenced within the SELECT were always printed
in $N style, rather than using the parameter name if any. While not
strictly incorrect, this wasn't the intention, and it's inconsistent
with the way that such parameters would be printed in any other kind
of statement.
The cause is that the recursion to get_query_def from
get_insert_query_def neglected to pass down the context->namespaces
list, passing constant NIL instead. This is a very ancient oversight,
but AFAICT it had no visible consequences before commit e717a9a18
added an outermost namespace with function parameters. We don't allow
INSERT ... SELECT as a sub-query, except in a top-level WITH clause,
where it couldn't contain any outer references that might need to access
upper namespaces. So although that's arguably a bug, I don't see any
point in changing it before v14.
In passing, harden the code added to get_parameter by e717a9a18 so that
it won't crash if a PARAM_EXTERN Param appears in an unexpected place.
Per report from Erki Eessaar. Code fix by me, regression test case
by Masahiko Sawada.
Discussion: https://postgr.es/m/AM9PR01MB8268347BED344848555167FAFE949@AM9PR01MB8268.eurprd01.prod.exchangelabs.com
2021-11-17 17:31:31 +01:00
|
|
|
SELECT pg_get_functiondef('functest_S_16'::regproc);
|
|
|
|
pg_get_functiondef
|
|
|
|
-------------------------------------------------------------------------------
|
|
|
|
CREATE OR REPLACE FUNCTION temp_func_test.functest_s_16(a integer, b integer)+
|
|
|
|
RETURNS void +
|
|
|
|
LANGUAGE sql +
|
|
|
|
BEGIN ATOMIC +
|
|
|
|
INSERT INTO functest1 (i) SELECT (functest_s_16.a + functest_s_16.b); +
|
|
|
|
END +
|
|
|
|
|
|
|
|
(1 row)
|
|
|
|
|
|
|
|
DROP TABLE functest1 CASCADE;
|
|
|
|
NOTICE: drop cascades to function functest_s_16(integer,integer)
|
2021-04-07 21:30:08 +02:00
|
|
|
-- test with views
|
|
|
|
CREATE TABLE functest3 (a int);
|
|
|
|
INSERT INTO functest3 VALUES (1), (2);
|
|
|
|
CREATE VIEW functestv3 AS SELECT * FROM functest3;
|
|
|
|
CREATE FUNCTION functest_S_14() RETURNS bigint
|
|
|
|
RETURN (SELECT count(*) FROM functestv3);
|
|
|
|
SELECT functest_S_14();
|
|
|
|
functest_s_14
|
|
|
|
---------------
|
|
|
|
2
|
|
|
|
(1 row)
|
|
|
|
|
|
|
|
DROP TABLE functest3 CASCADE;
|
|
|
|
NOTICE: drop cascades to 2 other objects
|
|
|
|
DETAIL: drop cascades to view functestv3
|
|
|
|
drop cascades to function functest_s_14()
|
2013-11-27 05:18:58 +01:00
|
|
|
-- information_schema tests
|
|
|
|
CREATE FUNCTION functest_IS_1(a int, b int default 1, c text default 'foo')
|
|
|
|
RETURNS int
|
|
|
|
LANGUAGE SQL
|
|
|
|
AS 'SELECT $1 + $2';
|
|
|
|
CREATE FUNCTION functest_IS_2(out a int, b int default 1)
|
|
|
|
RETURNS int
|
|
|
|
LANGUAGE SQL
|
|
|
|
AS 'SELECT $1';
|
|
|
|
CREATE FUNCTION functest_IS_3(a int default 1, out b int)
|
|
|
|
RETURNS int
|
|
|
|
LANGUAGE SQL
|
|
|
|
AS 'SELECT $1';
|
|
|
|
SELECT routine_name, ordinal_position, parameter_name, parameter_default
|
|
|
|
FROM information_schema.parameters JOIN information_schema.routines USING (specific_schema, specific_name)
|
|
|
|
WHERE routine_schema = 'temp_func_test' AND routine_name ~ '^functest_is_'
|
|
|
|
ORDER BY 1, 2;
|
|
|
|
routine_name | ordinal_position | parameter_name | parameter_default
|
|
|
|
---------------+------------------+----------------+-------------------
|
|
|
|
functest_is_1 | 1 | a |
|
|
|
|
functest_is_1 | 2 | b | 1
|
|
|
|
functest_is_1 | 3 | c | 'foo'::text
|
|
|
|
functest_is_2 | 1 | a |
|
|
|
|
functest_is_2 | 2 | b | 1
|
|
|
|
functest_is_3 | 1 | a | 1
|
|
|
|
functest_is_3 | 2 | b |
|
|
|
|
(7 rows)
|
|
|
|
|
2016-12-28 18:00:00 +01:00
|
|
|
DROP FUNCTION functest_IS_1(int, int, text), functest_IS_2(int), functest_IS_3(int);
|
2021-02-17 17:53:18 +01:00
|
|
|
-- routine usage views
|
|
|
|
CREATE FUNCTION functest_IS_4a() RETURNS int LANGUAGE SQL AS 'SELECT 1';
|
|
|
|
CREATE FUNCTION functest_IS_4b(x int DEFAULT functest_IS_4a()) RETURNS int LANGUAGE SQL AS 'SELECT x';
|
|
|
|
CREATE SEQUENCE functest1;
|
|
|
|
CREATE FUNCTION functest_IS_5(x int DEFAULT nextval('functest1'))
|
|
|
|
RETURNS int
|
|
|
|
LANGUAGE SQL
|
|
|
|
AS 'SELECT x';
|
2021-04-07 21:30:08 +02:00
|
|
|
CREATE FUNCTION functest_IS_6()
|
|
|
|
RETURNS int
|
|
|
|
LANGUAGE SQL
|
|
|
|
RETURN nextval('functest1');
|
|
|
|
CREATE TABLE functest2 (a int, b int);
|
|
|
|
CREATE FUNCTION functest_IS_7()
|
|
|
|
RETURNS int
|
|
|
|
LANGUAGE SQL
|
|
|
|
RETURN (SELECT count(a) FROM functest2);
|
2021-02-17 17:53:18 +01:00
|
|
|
SELECT r0.routine_name, r1.routine_name
|
|
|
|
FROM information_schema.routine_routine_usage rru
|
|
|
|
JOIN information_schema.routines r0 ON r0.specific_name = rru.specific_name
|
2021-04-08 12:20:11 +02:00
|
|
|
JOIN information_schema.routines r1 ON r1.specific_name = rru.routine_name
|
2021-04-15 22:31:36 +02:00
|
|
|
WHERE r0.routine_schema = 'temp_func_test' AND
|
|
|
|
r1.routine_schema = 'temp_func_test'
|
2021-04-08 12:20:11 +02:00
|
|
|
ORDER BY 1, 2;
|
2021-02-17 17:53:18 +01:00
|
|
|
routine_name | routine_name
|
|
|
|
----------------+----------------
|
|
|
|
functest_is_4b | functest_is_4a
|
|
|
|
(1 row)
|
|
|
|
|
2021-04-15 22:31:36 +02:00
|
|
|
SELECT routine_name, sequence_name FROM information_schema.routine_sequence_usage
|
|
|
|
WHERE routine_schema = 'temp_func_test'
|
|
|
|
ORDER BY 1, 2;
|
2021-02-17 17:53:18 +01:00
|
|
|
routine_name | sequence_name
|
|
|
|
---------------+---------------
|
|
|
|
functest_is_5 | functest1
|
2021-04-07 21:30:08 +02:00
|
|
|
functest_is_6 | functest1
|
|
|
|
(2 rows)
|
2021-02-17 17:53:18 +01:00
|
|
|
|
2021-04-15 22:31:36 +02:00
|
|
|
SELECT routine_name, table_name, column_name FROM information_schema.routine_column_usage
|
|
|
|
WHERE routine_schema = 'temp_func_test'
|
|
|
|
ORDER BY 1, 2;
|
2021-04-07 21:30:08 +02:00
|
|
|
routine_name | table_name | column_name
|
|
|
|
---------------+------------+-------------
|
|
|
|
functest_is_7 | functest2 | a
|
|
|
|
(1 row)
|
2021-02-17 17:53:18 +01:00
|
|
|
|
2021-04-15 22:31:36 +02:00
|
|
|
SELECT routine_name, table_name FROM information_schema.routine_table_usage
|
|
|
|
WHERE routine_schema = 'temp_func_test'
|
|
|
|
ORDER BY 1, 2;
|
2021-04-07 21:30:08 +02:00
|
|
|
routine_name | table_name
|
|
|
|
---------------+------------
|
|
|
|
functest_is_7 | functest2
|
|
|
|
(1 row)
|
2021-02-17 17:53:18 +01:00
|
|
|
|
|
|
|
DROP FUNCTION functest_IS_4a CASCADE;
|
|
|
|
NOTICE: drop cascades to function functest_is_4b(integer)
|
|
|
|
DROP SEQUENCE functest1 CASCADE;
|
2021-04-07 21:30:08 +02:00
|
|
|
NOTICE: drop cascades to 2 other objects
|
|
|
|
DETAIL: drop cascades to function functest_is_5(integer)
|
|
|
|
drop cascades to function functest_is_6()
|
|
|
|
DROP TABLE functest2 CASCADE;
|
|
|
|
NOTICE: drop cascades to function functest_is_7()
|
2017-03-10 05:58:48 +01:00
|
|
|
-- overload
|
|
|
|
CREATE FUNCTION functest_B_2(bigint) RETURNS bool LANGUAGE 'sql'
|
|
|
|
IMMUTABLE AS 'SELECT $1 > 0';
|
|
|
|
DROP FUNCTION functest_b_1;
|
|
|
|
DROP FUNCTION functest_b_1; -- error, not found
|
|
|
|
ERROR: could not find a function named "functest_b_1"
|
|
|
|
DROP FUNCTION functest_b_2; -- error, ambiguous
|
|
|
|
ERROR: function name "functest_b_2" is not unique
|
|
|
|
HINT: Specify the argument list to select the function unambiguously.
|
2018-03-02 14:57:38 +01:00
|
|
|
-- CREATE OR REPLACE tests
|
|
|
|
CREATE FUNCTION functest1(a int) RETURNS int LANGUAGE SQL AS 'SELECT $1';
|
|
|
|
CREATE OR REPLACE FUNCTION functest1(a int) RETURNS int LANGUAGE SQL WINDOW AS 'SELECT $1';
|
|
|
|
ERROR: cannot change routine kind
|
|
|
|
DETAIL: "functest1" is a function.
|
|
|
|
CREATE OR REPLACE PROCEDURE functest1(a int) LANGUAGE SQL AS 'SELECT $1';
|
|
|
|
ERROR: cannot change routine kind
|
|
|
|
DETAIL: "functest1" is a function.
|
|
|
|
DROP FUNCTION functest1(a int);
|
2021-04-07 21:30:08 +02:00
|
|
|
-- inlining of set-returning functions
|
Fix missed lock acquisition while inlining new-style SQL functions.
When starting to use a query parsetree loaded from the catalogs,
we must begin by applying AcquireRewriteLocks(), to obtain the same
relation locks that the parser would have gotten if the query were
entered interactively, and to do some other cleanup such as dealing
with later-dropped columns. New-style SQL functions are just as
subject to this rule as other stored parsetrees; however, of the
places dealing with such functions, only init_sql_fcache had gotten
the memo. In particular, if we successfully inlined a new-style
set-returning SQL function that contained any relation references,
we'd either get an assertion failure or attempt to use those
relation(s) sans locks.
I also added AcquireRewriteLocks calls to fmgr_sql_validator and
print_function_sqlbody. Desultory experiments didn't demonstrate any
failures in those, but I suspect that I just didn't try hard enough.
Certainly we don't expect nearby code paths to operate without locks.
On the same logic of it-ought-to-have-the-same-effects-as-the-old-code,
call pg_rewrite_query() in fmgr_sql_validator, too. It's possible
that neither code path there needs to bother with rewriting, but
doing the analysis to prove that is beyond my goals for today.
Per bug #17161 from Alexander Lakhin.
Discussion: https://postgr.es/m/17161-048a1cdff8422800@postgresql.org
2021-08-31 18:02:36 +02:00
|
|
|
CREATE TABLE functest3 (a int);
|
|
|
|
INSERT INTO functest3 VALUES (1), (2), (3);
|
2021-04-07 21:30:08 +02:00
|
|
|
CREATE FUNCTION functest_sri1() RETURNS SETOF int
|
|
|
|
LANGUAGE SQL
|
|
|
|
STABLE
|
|
|
|
AS '
|
Fix missed lock acquisition while inlining new-style SQL functions.
When starting to use a query parsetree loaded from the catalogs,
we must begin by applying AcquireRewriteLocks(), to obtain the same
relation locks that the parser would have gotten if the query were
entered interactively, and to do some other cleanup such as dealing
with later-dropped columns. New-style SQL functions are just as
subject to this rule as other stored parsetrees; however, of the
places dealing with such functions, only init_sql_fcache had gotten
the memo. In particular, if we successfully inlined a new-style
set-returning SQL function that contained any relation references,
we'd either get an assertion failure or attempt to use those
relation(s) sans locks.
I also added AcquireRewriteLocks calls to fmgr_sql_validator and
print_function_sqlbody. Desultory experiments didn't demonstrate any
failures in those, but I suspect that I just didn't try hard enough.
Certainly we don't expect nearby code paths to operate without locks.
On the same logic of it-ought-to-have-the-same-effects-as-the-old-code,
call pg_rewrite_query() in fmgr_sql_validator, too. It's possible
that neither code path there needs to bother with rewriting, but
doing the analysis to prove that is beyond my goals for today.
Per bug #17161 from Alexander Lakhin.
Discussion: https://postgr.es/m/17161-048a1cdff8422800@postgresql.org
2021-08-31 18:02:36 +02:00
|
|
|
SELECT * FROM functest3;
|
2021-04-07 21:30:08 +02:00
|
|
|
';
|
|
|
|
SELECT * FROM functest_sri1();
|
|
|
|
functest_sri1
|
|
|
|
---------------
|
|
|
|
1
|
|
|
|
2
|
|
|
|
3
|
|
|
|
(3 rows)
|
|
|
|
|
|
|
|
EXPLAIN (verbose, costs off) SELECT * FROM functest_sri1();
|
Fix missed lock acquisition while inlining new-style SQL functions.
When starting to use a query parsetree loaded from the catalogs,
we must begin by applying AcquireRewriteLocks(), to obtain the same
relation locks that the parser would have gotten if the query were
entered interactively, and to do some other cleanup such as dealing
with later-dropped columns. New-style SQL functions are just as
subject to this rule as other stored parsetrees; however, of the
places dealing with such functions, only init_sql_fcache had gotten
the memo. In particular, if we successfully inlined a new-style
set-returning SQL function that contained any relation references,
we'd either get an assertion failure or attempt to use those
relation(s) sans locks.
I also added AcquireRewriteLocks calls to fmgr_sql_validator and
print_function_sqlbody. Desultory experiments didn't demonstrate any
failures in those, but I suspect that I just didn't try hard enough.
Certainly we don't expect nearby code paths to operate without locks.
On the same logic of it-ought-to-have-the-same-effects-as-the-old-code,
call pg_rewrite_query() in fmgr_sql_validator, too. It's possible
that neither code path there needs to bother with rewriting, but
doing the analysis to prove that is beyond my goals for today.
Per bug #17161 from Alexander Lakhin.
Discussion: https://postgr.es/m/17161-048a1cdff8422800@postgresql.org
2021-08-31 18:02:36 +02:00
|
|
|
QUERY PLAN
|
|
|
|
--------------------------------------
|
|
|
|
Seq Scan on temp_func_test.functest3
|
|
|
|
Output: functest3.a
|
2021-04-07 21:30:08 +02:00
|
|
|
(2 rows)
|
|
|
|
|
|
|
|
CREATE FUNCTION functest_sri2() RETURNS SETOF int
|
|
|
|
LANGUAGE SQL
|
|
|
|
STABLE
|
|
|
|
BEGIN ATOMIC
|
Fix missed lock acquisition while inlining new-style SQL functions.
When starting to use a query parsetree loaded from the catalogs,
we must begin by applying AcquireRewriteLocks(), to obtain the same
relation locks that the parser would have gotten if the query were
entered interactively, and to do some other cleanup such as dealing
with later-dropped columns. New-style SQL functions are just as
subject to this rule as other stored parsetrees; however, of the
places dealing with such functions, only init_sql_fcache had gotten
the memo. In particular, if we successfully inlined a new-style
set-returning SQL function that contained any relation references,
we'd either get an assertion failure or attempt to use those
relation(s) sans locks.
I also added AcquireRewriteLocks calls to fmgr_sql_validator and
print_function_sqlbody. Desultory experiments didn't demonstrate any
failures in those, but I suspect that I just didn't try hard enough.
Certainly we don't expect nearby code paths to operate without locks.
On the same logic of it-ought-to-have-the-same-effects-as-the-old-code,
call pg_rewrite_query() in fmgr_sql_validator, too. It's possible
that neither code path there needs to bother with rewriting, but
doing the analysis to prove that is beyond my goals for today.
Per bug #17161 from Alexander Lakhin.
Discussion: https://postgr.es/m/17161-048a1cdff8422800@postgresql.org
2021-08-31 18:02:36 +02:00
|
|
|
SELECT * FROM functest3;
|
2021-04-07 21:30:08 +02:00
|
|
|
END;
|
|
|
|
SELECT * FROM functest_sri2();
|
|
|
|
functest_sri2
|
|
|
|
---------------
|
|
|
|
1
|
|
|
|
2
|
|
|
|
3
|
|
|
|
(3 rows)
|
|
|
|
|
|
|
|
EXPLAIN (verbose, costs off) SELECT * FROM functest_sri2();
|
Fix missed lock acquisition while inlining new-style SQL functions.
When starting to use a query parsetree loaded from the catalogs,
we must begin by applying AcquireRewriteLocks(), to obtain the same
relation locks that the parser would have gotten if the query were
entered interactively, and to do some other cleanup such as dealing
with later-dropped columns. New-style SQL functions are just as
subject to this rule as other stored parsetrees; however, of the
places dealing with such functions, only init_sql_fcache had gotten
the memo. In particular, if we successfully inlined a new-style
set-returning SQL function that contained any relation references,
we'd either get an assertion failure or attempt to use those
relation(s) sans locks.
I also added AcquireRewriteLocks calls to fmgr_sql_validator and
print_function_sqlbody. Desultory experiments didn't demonstrate any
failures in those, but I suspect that I just didn't try hard enough.
Certainly we don't expect nearby code paths to operate without locks.
On the same logic of it-ought-to-have-the-same-effects-as-the-old-code,
call pg_rewrite_query() in fmgr_sql_validator, too. It's possible
that neither code path there needs to bother with rewriting, but
doing the analysis to prove that is beyond my goals for today.
Per bug #17161 from Alexander Lakhin.
Discussion: https://postgr.es/m/17161-048a1cdff8422800@postgresql.org
2021-08-31 18:02:36 +02:00
|
|
|
QUERY PLAN
|
|
|
|
--------------------------------------
|
|
|
|
Seq Scan on temp_func_test.functest3
|
|
|
|
Output: functest3.a
|
2021-04-07 21:30:08 +02:00
|
|
|
(2 rows)
|
|
|
|
|
Fix missed lock acquisition while inlining new-style SQL functions.
When starting to use a query parsetree loaded from the catalogs,
we must begin by applying AcquireRewriteLocks(), to obtain the same
relation locks that the parser would have gotten if the query were
entered interactively, and to do some other cleanup such as dealing
with later-dropped columns. New-style SQL functions are just as
subject to this rule as other stored parsetrees; however, of the
places dealing with such functions, only init_sql_fcache had gotten
the memo. In particular, if we successfully inlined a new-style
set-returning SQL function that contained any relation references,
we'd either get an assertion failure or attempt to use those
relation(s) sans locks.
I also added AcquireRewriteLocks calls to fmgr_sql_validator and
print_function_sqlbody. Desultory experiments didn't demonstrate any
failures in those, but I suspect that I just didn't try hard enough.
Certainly we don't expect nearby code paths to operate without locks.
On the same logic of it-ought-to-have-the-same-effects-as-the-old-code,
call pg_rewrite_query() in fmgr_sql_validator, too. It's possible
that neither code path there needs to bother with rewriting, but
doing the analysis to prove that is beyond my goals for today.
Per bug #17161 from Alexander Lakhin.
Discussion: https://postgr.es/m/17161-048a1cdff8422800@postgresql.org
2021-08-31 18:02:36 +02:00
|
|
|
DROP TABLE functest3 CASCADE;
|
|
|
|
NOTICE: drop cascades to function functest_sri2()
|
2018-03-16 17:48:13 +01:00
|
|
|
-- Check behavior of VOID-returning SQL functions
|
|
|
|
CREATE FUNCTION voidtest1(a int) RETURNS VOID LANGUAGE SQL AS
|
|
|
|
$$ SELECT a + 1 $$;
|
|
|
|
SELECT voidtest1(42);
|
|
|
|
voidtest1
|
|
|
|
-----------
|
|
|
|
|
|
|
|
(1 row)
|
|
|
|
|
|
|
|
CREATE FUNCTION voidtest2(a int, b int) RETURNS VOID LANGUAGE SQL AS
|
|
|
|
$$ SELECT voidtest1(a + b) $$;
|
|
|
|
SELECT voidtest2(11,22);
|
|
|
|
voidtest2
|
|
|
|
-----------
|
|
|
|
|
|
|
|
(1 row)
|
|
|
|
|
|
|
|
-- currently, we can inline voidtest2 but not voidtest1
|
|
|
|
EXPLAIN (verbose, costs off) SELECT voidtest2(11,22);
|
|
|
|
QUERY PLAN
|
|
|
|
-------------------------
|
|
|
|
Result
|
|
|
|
Output: voidtest1(33)
|
|
|
|
(2 rows)
|
|
|
|
|
|
|
|
CREATE TEMP TABLE sometable(f1 int);
|
|
|
|
CREATE FUNCTION voidtest3(a int) RETURNS VOID LANGUAGE SQL AS
|
|
|
|
$$ INSERT INTO sometable VALUES(a + 1) $$;
|
|
|
|
SELECT voidtest3(17);
|
|
|
|
voidtest3
|
|
|
|
-----------
|
|
|
|
|
|
|
|
(1 row)
|
|
|
|
|
|
|
|
CREATE FUNCTION voidtest4(a int) RETURNS VOID LANGUAGE SQL AS
|
|
|
|
$$ INSERT INTO sometable VALUES(a - 1) RETURNING f1 $$;
|
|
|
|
SELECT voidtest4(39);
|
|
|
|
voidtest4
|
|
|
|
-----------
|
|
|
|
|
|
|
|
(1 row)
|
|
|
|
|
|
|
|
TABLE sometable;
|
|
|
|
f1
|
|
|
|
----
|
|
|
|
18
|
|
|
|
38
|
|
|
|
(2 rows)
|
|
|
|
|
|
|
|
CREATE FUNCTION voidtest5(a int) RETURNS SETOF VOID LANGUAGE SQL AS
|
|
|
|
$$ SELECT generate_series(1, a) $$ STABLE;
|
|
|
|
SELECT * FROM voidtest5(3);
|
|
|
|
voidtest5
|
|
|
|
-----------
|
|
|
|
(0 rows)
|
|
|
|
|
|
|
|
-- Cleanup
|
2012-02-14 04:20:27 +01:00
|
|
|
DROP SCHEMA temp_func_test CASCADE;
|
Fix missed lock acquisition while inlining new-style SQL functions.
When starting to use a query parsetree loaded from the catalogs,
we must begin by applying AcquireRewriteLocks(), to obtain the same
relation locks that the parser would have gotten if the query were
entered interactively, and to do some other cleanup such as dealing
with later-dropped columns. New-style SQL functions are just as
subject to this rule as other stored parsetrees; however, of the
places dealing with such functions, only init_sql_fcache had gotten
the memo. In particular, if we successfully inlined a new-style
set-returning SQL function that contained any relation references,
we'd either get an assertion failure or attempt to use those
relation(s) sans locks.
I also added AcquireRewriteLocks calls to fmgr_sql_validator and
print_function_sqlbody. Desultory experiments didn't demonstrate any
failures in those, but I suspect that I just didn't try hard enough.
Certainly we don't expect nearby code paths to operate without locks.
On the same logic of it-ought-to-have-the-same-effects-as-the-old-code,
call pg_rewrite_query() in fmgr_sql_validator, too. It's possible
that neither code path there needs to bother with rewriting, but
doing the analysis to prove that is beyond my goals for today.
Per bug #17161 from Alexander Lakhin.
Discussion: https://postgr.es/m/17161-048a1cdff8422800@postgresql.org
2021-08-31 18:02:36 +02:00
|
|
|
NOTICE: drop cascades to 29 other objects
|
2019-03-25 00:15:37 +01:00
|
|
|
DETAIL: drop cascades to function functest_a_1(text,date)
|
|
|
|
drop cascades to function functest_a_2(text[])
|
|
|
|
drop cascades to function functest_a_3()
|
|
|
|
drop cascades to function functest_b_2(integer)
|
|
|
|
drop cascades to function functest_b_3(integer)
|
|
|
|
drop cascades to function functest_b_4(integer)
|
|
|
|
drop cascades to function functest_c_1(integer)
|
|
|
|
drop cascades to function functest_c_2(integer)
|
|
|
|
drop cascades to function functest_c_3(integer)
|
|
|
|
drop cascades to function functest_e_1(integer)
|
|
|
|
drop cascades to function functest_e_2(integer)
|
|
|
|
drop cascades to function functest_f_1(integer)
|
|
|
|
drop cascades to function functest_f_2(integer)
|
|
|
|
drop cascades to function functest_f_3(integer)
|
|
|
|
drop cascades to function functest_f_4(integer)
|
2021-04-07 21:30:08 +02:00
|
|
|
drop cascades to function functest_s_1(text,date)
|
|
|
|
drop cascades to function functest_s_2(text[])
|
|
|
|
drop cascades to function functest_s_3()
|
|
|
|
drop cascades to function functest_s_3a()
|
|
|
|
drop cascades to function functest_s_10(text,date)
|
|
|
|
drop cascades to function functest_s_13()
|
|
|
|
drop cascades to function functest_s_15(integer)
|
2019-03-25 00:15:37 +01:00
|
|
|
drop cascades to function functest_b_2(bigint)
|
2021-04-07 21:30:08 +02:00
|
|
|
drop cascades to function functest_sri1()
|
2019-03-25 00:15:37 +01:00
|
|
|
drop cascades to function voidtest1(integer)
|
|
|
|
drop cascades to function voidtest2(integer,integer)
|
|
|
|
drop cascades to function voidtest3(integer)
|
|
|
|
drop cascades to function voidtest4(integer)
|
|
|
|
drop cascades to function voidtest5(integer)
|
2016-07-18 00:42:31 +02:00
|
|
|
DROP USER regress_unpriv_user;
|
2012-02-14 04:20:27 +01:00
|
|
|
RESET search_path;
|