Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

plpgsql: add support for INTO STRICT option #120486

Merged
merged 3 commits into from
Mar 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
527 changes: 527 additions & 0 deletions pkg/ccl/logictestccl/testdata/logic_test/plpgsql_into

Large diffs are not rendered by default.

302 changes: 0 additions & 302 deletions pkg/ccl/logictestccl/testdata/logic_test/udf_plpgsql
Original file line number Diff line number Diff line change
Expand Up @@ -1641,308 +1641,6 @@ CREATE OR REPLACE FUNCTION f() RETURNS INT AS $$
END
$$ LANGUAGE PLpgSQL;

# Testing SQL statements with INTO.
statement ok
CREATE OR REPLACE FUNCTION f() RETURNS INT AS $$
DECLARE
i INT;
BEGIN
SELECT 1 INTO i;
RETURN i;
END
$$ LANGUAGE PLpgSQL;

query I
SELECT f();
----
1

statement ok
CREATE OR REPLACE FUNCTION f() RETURNS INT AS $$
DECLARE
i INT;
BEGIN
SELECT x INTO i FROM xy ORDER BY x DESC LIMIT 1;
RETURN i;
END
$$ LANGUAGE PLpgSQL;

query I
SELECT f();
----
3

# If the INTO query returns more than one row, only the first is used.
statement ok
CREATE OR REPLACE FUNCTION f() RETURNS INT AS $$
DECLARE
i INT;
BEGIN
SELECT x INTO i FROM xy ORDER BY x DESC;
RETURN i;
END
$$ LANGUAGE PLpgSQL;

query I
SELECT f();
----
3

# If the INTO query returns no rows, the target variables are set to NULL.
statement ok
DELETE FROM xy WHERE true;

statement ok
CREATE OR REPLACE FUNCTION f() RETURNS INT AS $$
DECLARE
i INT;
BEGIN
SELECT x INTO i FROM xy ORDER BY x DESC;
RETURN i;
END
$$ LANGUAGE PLpgSQL;

query I
SELECT f();
----
NULL

statement ok
INSERT INTO xy VALUES (1, 2), (3, 4);

query I
SELECT f();
----
3

statement ok
CREATE OR REPLACE FUNCTION f() RETURNS INT AS $$
DECLARE
i INT;
BEGIN
INSERT INTO xy VALUES (100, 100) RETURNING x INTO i;
RETURN i;
END
$$ LANGUAGE PLpgSQL;

query I
SELECT f();
----
100

query II rowsort
SELECT * FROM xy;
----
1 2
3 4
100 100

statement ok
CREATE OR REPLACE FUNCTION f() RETURNS INT AS $$
DECLARE
i INT;
BEGIN
UPDATE xy SET y = y * 2 WHERE x = 100 RETURNING x INTO i;
RETURN i;
END
$$ LANGUAGE PLpgSQL;

query I
SELECT f();
----
100

query II rowsort
SELECT * FROM xy;
----
1 2
3 4
100 200

statement ok
CREATE OR REPLACE FUNCTION f() RETURNS INT AS $$
DECLARE
i INT;
BEGIN
DELETE FROM xy WHERE x = 100 RETURNING x INTO i;
RETURN i;
END
$$ LANGUAGE PLpgSQL;

query I
SELECT f();
----
100

query II rowsort
SELECT * FROM xy;
----
1 2
3 4

statement ok
DROP FUNCTION f(INT);
CREATE OR REPLACE FUNCTION f(n INT) RETURNS INT AS $$
DECLARE
foo INT;
bar INT;
i INT := 0;
BEGIN
LOOP IF i >= n THEN EXIT; END IF;
INSERT INTO xy VALUES (100+i, 200+i) RETURNING y INTO bar;
SELECT x INTO foo FROM xy ORDER BY x DESC LIMIT 1;
RAISE NOTICE 'foo: %, bar: %', foo, bar;
i := i + 1;
END LOOP;
RETURN 0;
END
$$ LANGUAGE PLpgSQL;

query T noticetrace
SELECT f(5);
----
NOTICE: foo: 100, bar: 200
NOTICE: foo: 101, bar: 201
NOTICE: foo: 102, bar: 202
NOTICE: foo: 103, bar: 203
NOTICE: foo: 104, bar: 204

query II rowsort
SELECT * FROM xy;
----
1 2
3 4
100 200
101 201
102 202
103 203
104 204

# If there are more INTO targets than output columns, the left over variables
# are set to NULL.
statement ok
CREATE OR REPLACE FUNCTION f() RETURNS INT AS $$
DECLARE
i INT;
j INT;
BEGIN
SELECT x INTO i, j FROM xy ORDER BY x DESC;
RAISE NOTICE 'i = %', i;
IF j IS NULL THEN
RAISE NOTICE 'j is null!';
END IF;
RETURN 0;
END
$$ LANGUAGE PLpgSQL;

query T noticetrace
SELECT f();
----
NOTICE: i = 104
NOTICE: j is null!

# If there are less INTO targets than output columns, the left over columns
# are ignored.
statement ok
CREATE OR REPLACE FUNCTION f() RETURNS INT AS $$
DECLARE
i INT;
BEGIN
SELECT x, y INTO i FROM xy ORDER BY x DESC;
RETURN i;
END
$$ LANGUAGE PLpgSQL;

query I
SELECT f();
----
104

query II rowsort
SELECT * FROM xy;
----
1 2
3 4
100 200
101 201
102 202
103 203
104 204

# It is possible to SELECT INTO multiple targets.
statement ok
CREATE OR REPLACE FUNCTION f() RETURNS INT AS $$
DECLARE
i INT;
j INT;
BEGIN
SELECT x, y INTO i, j FROM xy ORDER BY x DESC;
RETURN i + j;
END
$$ LANGUAGE PLpgSQL;

query I
SELECT f();
----
308

# It is possible to reference a previous value of a target variable in a
# SELECT INTO statement.
statement ok
CREATE OR REPLACE FUNCTION f() RETURNS INT AS $$
DECLARE
i INT;
BEGIN
SELECT x INTO i FROM xy ORDER BY x DESC;
RAISE NOTICE 'i = %', i;
SELECT x INTO i FROM xy WHERE x < i ORDER BY x DESC;
RAISE NOTICE 'i = %', i;
RETURN 0;
END
$$ LANGUAGE PLpgSQL;

query T noticetrace
SELECT f();
----
NOTICE: i = 104
NOTICE: i = 103

# When the SQL statement returns zero rows, the target variables are all set
# to NULL.
statement ok
CREATE OR REPLACE FUNCTION f() RETURNS INT AS $$
DECLARE
i INT := 0;
BEGIN
RAISE NOTICE 'i = %', i;
SELECT x INTO i FROM xy WHERE False;
RAISE NOTICE 'i = %', i;
i := 1;
RAISE NOTICE 'i = %', i;
INSERT INTO xy (SELECT 1, 2 FROM generate_series(1, 0)) RETURNING x INTO i;
RAISE NOTICE 'i = %', i;
RETURN 0;
END
$$ LANGUAGE PLpgSQL;

query T noticetrace
SELECT f();
----
NOTICE: i = 0
NOTICE: i = <NULL>
NOTICE: i = 1
NOTICE: i = <NULL>

statement error pgcode 0A000 pq: unimplemented: assigning to a variable more than once in the same INTO statement is not supported
CREATE OR REPLACE FUNCTION f() RETURNS INT AS $$
DECLARE
i INT;
BEGIN
SELECT x, y INTO i, i FROM xy ORDER BY x DESC;
RETURN i;
END
$$ LANGUAGE PLpgSQL;

# Functions with VOID return types do not need explicit RETURN statements
# for all possible control flows.
statement ok
Expand Down
7 changes: 7 additions & 0 deletions pkg/ccl/logictestccl/tests/3node-tenant/generated_test.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pkg/ccl/logictestccl/tests/fakedist-disk/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ go_test(
"//build/toolchains:is_heavy": {"test.Pool": "heavy"},
"//conditions:default": {"test.Pool": "large"},
}),
shard_count = 25,
shard_count = 26,
tags = [
"ccl_test",
"cpu:2",
Expand Down
7 changes: 7 additions & 0 deletions pkg/ccl/logictestccl/tests/fakedist-disk/generated_test.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pkg/ccl/logictestccl/tests/fakedist-vec-off/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ go_test(
"//build/toolchains:is_heavy": {"test.Pool": "heavy"},
"//conditions:default": {"test.Pool": "large"},
}),
shard_count = 25,
shard_count = 26,
tags = [
"ccl_test",
"cpu:2",
Expand Down
7 changes: 7 additions & 0 deletions pkg/ccl/logictestccl/tests/fakedist-vec-off/generated_test.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pkg/ccl/logictestccl/tests/fakedist/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ go_test(
"//build/toolchains:is_heavy": {"test.Pool": "heavy"},
"//conditions:default": {"test.Pool": "large"},
}),
shard_count = 26,
shard_count = 27,
tags = [
"ccl_test",
"cpu:2",
Expand Down
7 changes: 7 additions & 0 deletions pkg/ccl/logictestccl/tests/fakedist/generated_test.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.