Skip to content

Commit e53fa91

Browse files
craig[bot]rafiss
andcommitted
Merge #153625
153625: builtins: implement pg_get_function_arg_default r=rafiss a=rafiss fixes #153352 Release note (sql change): The pg_get_function_arg_default builtin function has been implemented. This also causes the information_schema.parameters(parameter_default) column to be populated correctly. Co-authored-by: Rafi Shamim <[email protected]>
2 parents c931ab6 + 0867670 commit e53fa91

File tree

3 files changed

+128
-4
lines changed

3 files changed

+128
-4
lines changed

docs/generated/sql/functions.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3615,7 +3615,7 @@ may increase either contention or retry errors, or both.</p>
36153615
</span></td><td>Stable</td></tr>
36163616
<tr><td><a name="pg_function_is_visible"></a><code>pg_function_is_visible(oid: oid) &rarr; <a href="bool.html">bool</a></code></td><td><span class="funcdesc"><p>Returns whether the function with the given OID belongs to one of the schemas on the search path.</p>
36173617
</span></td><td>Stable</td></tr>
3618-
<tr><td><a name="pg_get_function_arg_default"></a><code>pg_get_function_arg_default(func_oid: oid, arg_num: int4) &rarr; <a href="string.html">string</a></code></td><td><span class="funcdesc"><p>Get textual representation of a function argument’s default value. The second argument of this function is the argument number among all arguments (i.e. proallargtypes, <em>not</em> proargtypes), starting with 1, because that’s how information_schema.sql uses it. Currently, this always returns NULL, since CockroachDB does not support default values.</p>
3618+
<tr><td><a name="pg_get_function_arg_default"></a><code>pg_get_function_arg_default(func_oid: oid, arg_num: int4) &rarr; <a href="string.html">string</a></code></td><td><span class="funcdesc"><p>Get textual representation of a function argument’s default value. The second argument of this function is the argument number among all arguments (i.e. proallargtypes, <em>not</em> proargtypes), starting with 1, because that’s how information_schema.sql uses it.</p>
36193619
</span></td><td>Stable</td></tr>
36203620
<tr><td><a name="pg_get_function_arguments"></a><code>pg_get_function_arguments(func_oid: oid) &rarr; <a href="string.html">string</a></code></td><td><span class="funcdesc"><p>Returns the argument list (with defaults) necessary to identify a function, in the form it would need to appear in within CREATE FUNCTION.</p>
36213621
</span></td><td>Stable</td></tr>

pkg/sql/logictest/testdata/logic_test/information_schema

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3528,6 +3528,97 @@ specific_catalog specific_schema specific_name ordinal_position parameter_mo
35283528
test pg_catalog get_byte_854 1 IN NO NO NULL bytea NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL test pg_catalog bytea NULL NULL NULL NULL 1 NULL
35293529
test pg_catalog get_byte_854 2 IN NO NO NULL bigint NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL test pg_catalog int8 NULL NULL NULL NULL 2 NULL
35303530

3531+
# Test that default values are populated correctly.
3532+
statement ok
3533+
CREATE OR REPLACE FUNCTION f_default(
3534+
p_no_default INT,
3535+
p_int INT DEFAULT 0,
3536+
p_string STRING DEFAULT '0'
3537+
)
3538+
RETURNS varchar
3539+
LANGUAGE plpgsql
3540+
AS
3541+
$$
3542+
BEGIN
3543+
RETURN p_no_default::varchar || ':' || p_int::varchar || ':' || p_string;
3544+
END;
3545+
$$
3546+
3547+
query TT
3548+
SELECT p.parameter_name, p.parameter_default
3549+
FROM information_schema.routines AS r
3550+
JOIN information_schema.parameters AS p ON r.specific_name = p.specific_name
3551+
WHERE r.routine_name = 'f_default'
3552+
ORDER BY p.ordinal_position;
3553+
----
3554+
p_no_default NULL
3555+
p_int 0:::INT8
3556+
p_string '0':::STRING
3557+
3558+
# Test INOUT parameters with defaults.
3559+
statement ok
3560+
CREATE FUNCTION f_inout_default(
3561+
INOUT p_inout_no_default INT,
3562+
INOUT p_inout_with_default INT DEFAULT 42
3563+
) RETURNS RECORD AS $$ SELECT p_inout_no_default + 1, p_inout_with_default + 1; $$ LANGUAGE SQL;
3564+
3565+
query TT
3566+
SELECT p.parameter_name, p.parameter_default
3567+
FROM information_schema.routines AS r
3568+
JOIN information_schema.parameters AS p ON r.specific_name = p.specific_name
3569+
WHERE r.routine_name = 'f_inout_default'
3570+
ORDER BY p.ordinal_position;
3571+
----
3572+
p_inout_no_default NULL
3573+
p_inout_with_default 42:::INT8
3574+
3575+
# Test mixed parameter modes with defaults. Note that parameters with
3576+
# defaults must appear after all parameters without defaults.
3577+
statement ok
3578+
CREATE FUNCTION f_mixed_defaults(
3579+
p_in_no_default INT,
3580+
OUT p_out_param INT,
3581+
INOUT p_inout_no_default INT,
3582+
p_in_default INT DEFAULT 10,
3583+
INOUT p_inout_default INT DEFAULT 20
3584+
) RETURNS RECORD AS $$
3585+
SELECT p_in_no_default + p_in_default, p_inout_no_default + 1, p_inout_default + 1;
3586+
$$ LANGUAGE SQL;
3587+
3588+
query TT
3589+
SELECT p.parameter_name, p.parameter_default
3590+
FROM information_schema.routines AS r
3591+
JOIN information_schema.parameters AS p ON r.specific_name = p.specific_name
3592+
WHERE r.routine_name = 'f_mixed_defaults'
3593+
ORDER BY p.ordinal_position;
3594+
----
3595+
p_in_no_default NULL
3596+
p_out_param NULL
3597+
p_inout_no_default NULL
3598+
p_in_default 10:::INT8
3599+
p_inout_default 20:::INT8
3600+
3601+
# Test complex default expressions with different parameter modes.
3602+
statement ok
3603+
CREATE FUNCTION f_complex_defaults(
3604+
OUT p_out_result INT,
3605+
INOUT p_complex_default INT DEFAULT length('test'),
3606+
p_function_default INT DEFAULT length('hello')
3607+
) RETURNS RECORD AS $$
3608+
SELECT p_complex_default + p_function_default, p_complex_default;
3609+
$$ LANGUAGE SQL;
3610+
3611+
query TT
3612+
SELECT p.parameter_name, p.parameter_default
3613+
FROM information_schema.routines AS r
3614+
JOIN information_schema.parameters AS p ON r.specific_name = p.specific_name
3615+
WHERE r.routine_name = 'f_complex_defaults'
3616+
ORDER BY p.ordinal_position;
3617+
----
3618+
p_out_result NULL
3619+
p_complex_default length('test':::STRING)
3620+
p_function_default length('hello':::STRING)
3621+
35313622
skipif config local-mixed-25.2
35323623
query TTTTTTTT colnames,rowsort
35333624
SELECT * FROM system.information_schema.column_privileges WHERE table_name = 'eventlog'

pkg/sql/sem/builtins/pg_builtins.go

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -773,12 +773,45 @@ var pgBuiltins = map[string]builtinDefinition{
773773
tree.Overload{
774774
Types: tree.ParamTypes{{Name: "func_oid", Typ: types.Oid}, {Name: "arg_num", Typ: types.Int4}},
775775
ReturnType: tree.FixedReturnType(types.String),
776-
Body: "SELECT NULL",
776+
Body: `
777+
WITH defaults_parsed AS (
778+
SELECT
779+
proargdefaults,
780+
pronargs,
781+
proargmodes,
782+
array_upper(proargmodes, 1) AS total_args,
783+
CASE
784+
WHEN proargdefaults IS NULL THEN 0
785+
ELSE array_length(string_to_array(trim('()' FROM proargdefaults), '}, {'), 1)
786+
END AS num_defaults,
787+
trim('()' FROM proargdefaults) AS defaults_trimmed,
788+
-- Count input arguments up to position $2
789+
CASE
790+
WHEN proargmodes IS NULL THEN $2
791+
ELSE (
792+
SELECT count(*)
793+
FROM generate_series(1, $2) AS i
794+
WHERE proargmodes[i] IN ('i', 'b', 'v')
795+
)
796+
END AS nth_input_arg
797+
FROM pg_catalog.pg_proc
798+
WHERE oid = $1
799+
LIMIT 1
800+
)
801+
SELECT
802+
CASE
803+
WHEN proargdefaults IS NULL THEN NULL
804+
WHEN $2 < 1 OR $2 > COALESCE(total_args, pronargs) THEN NULL
805+
WHEN (proargmodes IS NOT NULL AND proargmodes[$2] NOT IN ('i', 'b', 'v')) THEN NULL
806+
WHEN nth_input_arg <= (pronargs - num_defaults) THEN NULL
807+
ELSE trim('{}' FROM split_part(defaults_trimmed, '}, {', nth_input_arg - (pronargs - num_defaults)))
808+
END
809+
FROM defaults_parsed
810+
`,
777811
Info: "Get textual representation of a function argument's default value. " +
778812
"The second argument of this function is the argument number among all " +
779813
"arguments (i.e. proallargtypes, *not* proargtypes), starting with 1, " +
780-
"because that's how information_schema.sql uses it. Currently, this " +
781-
"always returns NULL, since CockroachDB does not support default values.",
814+
"because that's how information_schema.sql uses it.",
782815
Volatility: volatility.Stable,
783816
CalledOnNullInput: true,
784817
Language: tree.RoutineLangSQL,

0 commit comments

Comments
 (0)