diff --git a/pkg/sql/logictest/testdata/logic_test/procedure b/pkg/sql/logictest/testdata/logic_test/procedure index f9a471d1b6dc..11c3f9a392d1 100644 --- a/pkg/sql/logictest/testdata/logic_test/procedure +++ b/pkg/sql/logictest/testdata/logic_test/procedure @@ -412,20 +412,3 @@ statement error pgcode 42P13 null input attribute not allowed in procedure defin CREATE PROCEDURE pv() AS 'SELECT 1' STRICT LANGUAGE SQL; subtest end - - -subtest udf_calling_udfs - -# Validate we can have UDF's both in the select and from clauses. -statement ok -CREATE FUNCTION udfCall(i int) RETURNS INT LANGUAGE SQL AS 'SELECT 100+i'; -CREATE FUNCTION udfCallNest(i int, j int) RETURNS INT LANGUAGE SQL AS 'SELECT udfCall(i) + j'; -CREATE FUNCTION udfCallNest_2(i int, j int) RETURNS INT LANGUAGE SQL AS 'SELECT udfCall(i) + udfCall(j) + udfCallNest(i, j)'; -CREATE FUNCTION udfCallNest_3(i int, j int) RETURNS INT LANGUAGE SQL AS 'SELECT udfCall(j) + udfCallNest(i, j) + udfCallNest_2(i, j) + 1 FROM udfCallNest_2(i, j)'; - -query I -SELECT * FROM udfCallNest_3(1, 2) ----- -512 - -subtest end diff --git a/pkg/sql/logictest/testdata/logic_test/udf_calling_udf b/pkg/sql/logictest/testdata/logic_test/udf_calling_udf index 493949122b80..d68792b8618e 100644 --- a/pkg/sql/logictest/testdata/logic_test/udf_calling_udf +++ b/pkg/sql/logictest/testdata/logic_test/udf_calling_udf @@ -1,3 +1,5 @@ +# LogicTest: !local-mixed-23.1 + statement ok CREATE FUNCTION lower_hello() RETURNS STRING LANGUAGE SQL AS $$ SELECT lower('hello') $$; @@ -15,6 +17,18 @@ SELECT upper_hello(), nested_udf_for_from(), lower_hello(), concat_hello() ---- HELLO HELLO hello HELLOHELLOhello +# Validate we can have UDF's both in the select and from clauses. +statement ok +CREATE FUNCTION udfCall(i int) RETURNS INT LANGUAGE SQL AS 'SELECT 100+i'; +CREATE FUNCTION udfCallNest(i int, j int) RETURNS INT LANGUAGE SQL AS 'SELECT udfCall(i) + j'; +CREATE FUNCTION udfCallNest_2(i int, j int) RETURNS INT LANGUAGE SQL AS 'SELECT udfCall(i) + udfCall(j) + udfCallNest(i, j)'; +CREATE FUNCTION udfCallNest_3(i int, j int) RETURNS INT LANGUAGE SQL AS 'SELECT udfCall(j) + udfCallNest(i, j) + udfCallNest_2(i, j) + 1 FROM udfCallNest_2(i, j)'; + +query I +SELECT * FROM udfCallNest_3(1, 2) +---- +512 + # Validate recursion doesn't work today. statement error pgcode 42883 unknown function: recursion_check\(\) CREATE FUNCTION recursion_check() RETURNS STRING LANGUAGE SQL AS $$ SELECT recursion_check() $$; @@ -22,3 +36,81 @@ CREATE FUNCTION recursion_check() RETURNS STRING LANGUAGE SQL AS $$ SELECT recu # Validate that function renaming is blocked. statement error pgcode 0A000 cannot rename function \"lower_hello\" because other functions \(\[test.public.upper_hello, test.public.concat_hello\]\) still depend on it ALTER FUNCTION lower_hello rename to lower_hello_new + +statement ok +CREATE FUNCTION f() RETURNS INT LANGUAGE SQL AS $$ + SELECT 1; +$$ + +statement ok +CREATE FUNCTION g() RETURNS INT LANGUAGE SQL AS $$ + SELECT f(); +$$ + +# Mutual recursion is not currently allowed. +statement error pgcode 42P13 cannot add dependency from descriptor \d+ to function g \(\d+\) because there will be a dependency cycle +CREATE OR REPLACE FUNCTION f() RETURNS INT LANGUAGE SQL AS $$ + SELECT g(); +$$ + +statement ok +DROP FUNCTION g(); +DROP FUNCTION f(); + +statement ok +CREATE TABLE ab ( + a INT PRIMARY KEY, + b INT +) + +statement ok +CREATE FUNCTION ins_ab(new_a INT, new_b INT) RETURNS INT LANGUAGE SQL AS $$ + INSERT INTO ab VALUES (new_a, new_b) RETURNING a; +$$ + +statement ok +CREATE FUNCTION ins(new_a INT) RETURNS INT LANGUAGE SQL AS $$ + SELECT ins_ab(new_a, new_a * 10); + SELECT b FROM ab WHERE a = new_a; +$$ + +query I rowsort +SELECT ins(i) FROM generate_series(1, 3) g(i) +---- +10 +20 +30 + +query II +SELECT ins(5), ins(6) FROM (VALUES (1)) v(i) WHERE i < ins(4) +---- +50 60 + +query II rowsort +SELECT * FROM ab +---- +1 10 +2 20 +3 30 +4 40 +5 50 +6 60 + +statement error pgcode 23505 duplicate key value violates unique constraint \"ab_pkey\" +SELECT ins(4) + +skipif config local-legacy-schema-changer +statement error pgcode 2BP01 cannot drop table ab because other objects depend on it +DROP TABLE ab + +onlyif config local-legacy-schema-changer +statement error pgcode 2BP01 pq: cannot drop relation \"ab\" because function \"ins\" depends on it\nHINT: consider dropping \"ins\" first. +DROP TABLE ab + +statement error pgcode 2BP01 cannot drop function \"ins_ab\" because other objects \(\[test.public.ins\]\) still depend on it +DROP FUNCTION ins_ab + +statement ok +DROP FUNCTION ins; +DROP FUNCTION ins_ab; +DROP TABLE ab; diff --git a/pkg/sql/logictest/tests/local-mixed-23.1/generated_test.go b/pkg/sql/logictest/tests/local-mixed-23.1/generated_test.go index 4d2a3bb537e6..4736bc72e4e8 100644 --- a/pkg/sql/logictest/tests/local-mixed-23.1/generated_test.go +++ b/pkg/sql/logictest/tests/local-mixed-23.1/generated_test.go @@ -2101,13 +2101,6 @@ func TestLogic_udf( runLogicTest(t, "udf") } -func TestLogic_udf_calling_udf( - t *testing.T, -) { - defer leaktest.AfterTest(t)() - runLogicTest(t, "udf_calling_udf") -} - func TestLogic_udf_in_column_defaults( t *testing.T, ) { diff --git a/pkg/sql/opt/optbuilder/routine.go b/pkg/sql/opt/optbuilder/routine.go index 067c636108e1..84f97f195051 100644 --- a/pkg/sql/opt/optbuilder/routine.go +++ b/pkg/sql/opt/optbuilder/routine.go @@ -280,7 +280,7 @@ func (b *Builder) buildRoutine( } // Add a VALUES (NULL) statement if the return type of the function is // VOID. We cannot simply project NULL from the last statement because - // all column would be pruned and the contents of last statement would + // all columns would be pruned and the contents of last statement would // not be executed. // TODO(mgartner): This will add some planning overhead for every // invocation of the function. Is there a more efficient way to do this?