From ae0032dff86ab495fea3a4c24b74062ba7867b73 Mon Sep 17 00:00:00 2001 From: Murat Tuncer Date: Tue, 11 Sep 2018 15:16:57 +0300 Subject: [PATCH] Add regression tests for procedure calls PG11 introduced PROCEDURE concept similar to FUNCTION Procedure's allow committing/rolling back behavior. This commmit adds regression tests for procedure calls. --- src/test/regress/expected/sql_procedure.out | 189 ++++++++++++++ src/test/regress/expected/sql_procedure_0.out | 234 ++++++++++++++++++ src/test/regress/multi_schedule | 1 + src/test/regress/sql/sql_procedure.sql | 141 +++++++++++ 4 files changed, 565 insertions(+) create mode 100644 src/test/regress/expected/sql_procedure.out create mode 100644 src/test/regress/expected/sql_procedure_0.out create mode 100644 src/test/regress/sql/sql_procedure.sql diff --git a/src/test/regress/expected/sql_procedure.out b/src/test/regress/expected/sql_procedure.out new file mode 100644 index 000000000..0ab70f943 --- /dev/null +++ b/src/test/regress/expected/sql_procedure.out @@ -0,0 +1,189 @@ +-- +-- SQL_PROCEDURE +-- +-- Tests basic PROCEDURE functionality with SQL and PLPGSQL procedures. +-- +-- print whether we're using version > 10 to make version-specific tests clear +SHOW server_version \gset +SELECT substring(:'server_version', '\d+')::int > 10 AS version_above_ten; + version_above_ten +------------------- + t +(1 row) + +SET citus.next_shard_id TO 100500; +CREATE SCHEMA procedure_schema; +SET SEARCH_PATH = procedure_schema; +CREATE TABLE test_table(id integer , org_id integer); +CREATE UNIQUE INDEX idx_table ON test_table(id, org_id); +SELECT create_distributed_table('test_table','id'); + create_distributed_table +-------------------------- + +(1 row) + +INSERT INTO test_table VALUES(1, 1); +-- test CREATE PROCEDURE +CREATE PROCEDURE test_procedure_delete_insert(id int, org_id int) LANGUAGE SQL AS $$ + DELETE FROM test_table; + INSERT INTO test_table VALUES(id, org_id); +$$; +CALL test_procedure_delete_insert(2,3); +SELECT * FROM test_table ORDER BY 1, 2; + id | org_id +----+-------- + 2 | 3 +(1 row) + +-- commit/rollback is not allowed in procedures in SQL +-- following calls should fail +CREATE PROCEDURE test_procedure_commit(tt_id int, tt_org_id int) LANGUAGE SQL AS $$ + DELETE FROM test_table; + COMMIT; + INSERT INTO test_table VALUES(tt_id, -1); + UPDATE test_table SET org_id = tt_org_id WHERE id = tt_id; + COMMIT; +$$; +CALL test_procedure_commit(2,5); +ERROR: COMMIT is not allowed in a SQL function +CONTEXT: SQL function "test_procedure_commit" during startup +SELECT * FROM test_table ORDER BY 1, 2; + id | org_id +----+-------- + 2 | 3 +(1 row) + +CREATE PROCEDURE test_procedure_rollback(tt_id int, tt_org_id int) LANGUAGE SQL AS $$ + DELETE FROM test_table; + ROLLBACK; + UPDATE test_table SET org_id = tt_org_id WHERE id = tt_id; + COMMIT; +$$; +CALL test_procedure_rollback(2,15); +ERROR: ROLLBACK is not allowed in a SQL function +CONTEXT: SQL function "test_procedure_rollback" during startup +SELECT * FROM test_table ORDER BY 1, 2; + id | org_id +----+-------- + 2 | 3 +(1 row) + +DROP PROCEDURE test_procedure_delete_insert(int, int); +DROP PROCEDURE test_procedure_commit(int, int); +DROP PROCEDURE test_procedure_rollback(int, int); +-- same tests with plpgsql +-- test CREATE PROCEDURE +CREATE PROCEDURE test_procedure_delete_insert(id int, org_id int) LANGUAGE PLPGSQL AS $$ +BEGIN + DELETE FROM test_table; + INSERT INTO test_table VALUES(id, org_id); +END; +$$; +CALL test_procedure_delete_insert(2,3); +SELECT * FROM test_table ORDER BY 1, 2; + id | org_id +----+-------- + 2 | 3 +(1 row) + +-- notice that the update succeed and committed +CREATE PROCEDURE test_procedure_modify_insert(tt_id int, tt_org_id int) LANGUAGE PLPGSQL AS $$ +BEGIN + UPDATE test_table SET org_id = tt_org_id WHERE id = tt_id; + COMMIT; + INSERT INTO test_table VALUES (tt_id, tt_org_id); + ROLLBACK; +END; +$$; +CALL test_procedure_modify_insert(2,12); +ERROR: duplicate key value violates unique constraint "idx_table_100503" +DETAIL: Key (id, org_id)=(2, 12) already exists. +CONTEXT: while executing command on localhost:57637 +SQL statement "INSERT INTO test_table VALUES (tt_id, tt_org_id)" +PL/pgSQL function test_procedure_modify_insert(integer,integer) line 5 at SQL statement +SELECT * FROM test_table ORDER BY 1, 2; + id | org_id +----+-------- + 2 | 12 +(1 row) + +CREATE PROCEDURE test_procedure_modify_insert_commit(tt_id int, tt_org_id int) LANGUAGE PLPGSQL AS $$ +BEGIN + UPDATE test_table SET org_id = tt_org_id WHERE id = tt_id; + COMMIT; + INSERT INTO test_table VALUES (tt_id, tt_org_id); + COMMIT; +END; +$$; +CALL test_procedure_modify_insert_commit(2,30); +ERROR: duplicate key value violates unique constraint "idx_table_100503" +DETAIL: Key (id, org_id)=(2, 30) already exists. +CONTEXT: while executing command on localhost:57637 +SQL statement "INSERT INTO test_table VALUES (tt_id, tt_org_id)" +PL/pgSQL function test_procedure_modify_insert_commit(integer,integer) line 5 at SQL statement +SELECT * FROM test_table ORDER BY 1, 2; + id | org_id +----+-------- + 2 | 30 +(1 row) + +-- delete is commited but insert is rolled back +-- there is a bug #2371 on that preventing rollback +CREATE PROCEDURE test_procedure_rollback(tt_id int, tt_org_id int) LANGUAGE PLPGSQL AS $$ +BEGIN + DELETE FROM test_table; + COMMIT; + INSERT INTO test_table VALUES (tt_id, tt_org_id); + ROLLBACK; +END; +$$; +CALL test_procedure_rollback(2,5); +SELECT * FROM test_table ORDER BY 1, 2; + id | org_id +----+-------- + 2 | 5 +(1 row) + +-- rollback is successfull when insert is on multiple rows +CREATE PROCEDURE test_procedure_rollback_2(tt_id int, tt_org_id int) LANGUAGE PLPGSQL AS $$ +BEGIN + DELETE FROM test_table; + COMMIT; + INSERT INTO test_table VALUES (tt_id, tt_org_id), (tt_id+1, tt_org_id+1); + ROLLBACK; +END; +$$; +CALL test_procedure_rollback_2(12, 15); +SELECT * FROM test_table ORDER BY 1, 2; + id | org_id +----+-------- +(0 rows) + +-- delete is rolled back, update is committed +CREATE PROCEDURE test_procedure_rollback_3(tt_id int, tt_org_id int) LANGUAGE PLPGSQL AS $$ +BEGIN + DELETE FROM test_table; + ROLLBACK; + UPDATE test_table SET org_id = tt_org_id WHERE id = tt_id; + COMMIT; +END; +$$; +INSERT INTO test_table VALUES (1, 1), (2, 2); +CALL test_procedure_rollback_3(2,15); +SELECT * FROM test_table ORDER BY 1, 2; + id | org_id +----+-------- + 1 | 1 + 2 | 15 +(2 rows) + +DROP SCHEMA procedure_schema CASCADE; +NOTICE: drop cascades to 7 other objects +DETAIL: drop cascades to table test_table +drop cascades to function test_procedure_delete_insert(integer,integer) +drop cascades to function test_procedure_modify_insert(integer,integer) +drop cascades to function test_procedure_modify_insert_commit(integer,integer) +drop cascades to function test_procedure_rollback(integer,integer) +drop cascades to function test_procedure_rollback_2(integer,integer) +drop cascades to function test_procedure_rollback_3(integer,integer) +RESET SEARCH_PATH; diff --git a/src/test/regress/expected/sql_procedure_0.out b/src/test/regress/expected/sql_procedure_0.out new file mode 100644 index 000000000..a58b1dee6 --- /dev/null +++ b/src/test/regress/expected/sql_procedure_0.out @@ -0,0 +1,234 @@ +-- +-- SQL_PROCEDURE +-- +-- Tests basic PROCEDURE functionality with SQL and PLPGSQL procedures. +-- +-- print whether we're using version > 10 to make version-specific tests clear +SHOW server_version \gset +SELECT substring(:'server_version', '\d+')::int > 10 AS version_above_ten; + version_above_ten +------------------- + f +(1 row) + +SET citus.next_shard_id TO 100500; +CREATE SCHEMA procedure_schema; +SET SEARCH_PATH = procedure_schema; +CREATE TABLE test_table(id integer , org_id integer); +CREATE UNIQUE INDEX idx_table ON test_table(id, org_id); +SELECT create_distributed_table('test_table','id'); + create_distributed_table +-------------------------- + +(1 row) + +INSERT INTO test_table VALUES(1, 1); +-- test CREATE PROCEDURE +CREATE PROCEDURE test_procedure_delete_insert(id int, org_id int) LANGUAGE SQL AS $$ + DELETE FROM test_table; + INSERT INTO test_table VALUES(id, org_id); +$$; +ERROR: syntax error at or near "PROCEDURE" +LINE 1: CREATE PROCEDURE test_procedure_delete_insert(id int, org_id... + ^ +CALL test_procedure_delete_insert(2,3); +ERROR: syntax error at or near "CALL" +LINE 1: CALL test_procedure_delete_insert(2,3); + ^ +SELECT * FROM test_table ORDER BY 1, 2; + id | org_id +----+-------- + 1 | 1 +(1 row) + +-- commit/rollback is not allowed in procedures in SQL +-- following calls should fail +CREATE PROCEDURE test_procedure_commit(tt_id int, tt_org_id int) LANGUAGE SQL AS $$ + DELETE FROM test_table; + COMMIT; + INSERT INTO test_table VALUES(tt_id, -1); + UPDATE test_table SET org_id = tt_org_id WHERE id = tt_id; + COMMIT; +$$; +ERROR: syntax error at or near "PROCEDURE" +LINE 1: CREATE PROCEDURE test_procedure_commit(tt_id int, tt_org_id ... + ^ +CALL test_procedure_commit(2,5); +ERROR: syntax error at or near "CALL" +LINE 1: CALL test_procedure_commit(2,5); + ^ +SELECT * FROM test_table ORDER BY 1, 2; + id | org_id +----+-------- + 1 | 1 +(1 row) + +CREATE PROCEDURE test_procedure_rollback(tt_id int, tt_org_id int) LANGUAGE SQL AS $$ + DELETE FROM test_table; + ROLLBACK; + UPDATE test_table SET org_id = tt_org_id WHERE id = tt_id; + COMMIT; +$$; +ERROR: syntax error at or near "PROCEDURE" +LINE 1: CREATE PROCEDURE test_procedure_rollback(tt_id int, tt_org_i... + ^ +CALL test_procedure_rollback(2,15); +ERROR: syntax error at or near "CALL" +LINE 1: CALL test_procedure_rollback(2,15); + ^ +SELECT * FROM test_table ORDER BY 1, 2; + id | org_id +----+-------- + 1 | 1 +(1 row) + +DROP PROCEDURE test_procedure_delete_insert(int, int); +ERROR: syntax error at or near "PROCEDURE" +LINE 1: DROP PROCEDURE test_procedure_delete_insert(int, int); + ^ +DROP PROCEDURE test_procedure_commit(int, int); +ERROR: syntax error at or near "PROCEDURE" +LINE 1: DROP PROCEDURE test_procedure_commit(int, int); + ^ +DROP PROCEDURE test_procedure_rollback(int, int); +ERROR: syntax error at or near "PROCEDURE" +LINE 1: DROP PROCEDURE test_procedure_rollback(int, int); + ^ +-- same tests with plpgsql +-- test CREATE PROCEDURE +CREATE PROCEDURE test_procedure_delete_insert(id int, org_id int) LANGUAGE PLPGSQL AS $$ +BEGIN + DELETE FROM test_table; + INSERT INTO test_table VALUES(id, org_id); +END; +$$; +ERROR: syntax error at or near "PROCEDURE" +LINE 1: CREATE PROCEDURE test_procedure_delete_insert(id int, org_id... + ^ +CALL test_procedure_delete_insert(2,3); +ERROR: syntax error at or near "CALL" +LINE 1: CALL test_procedure_delete_insert(2,3); + ^ +SELECT * FROM test_table ORDER BY 1, 2; + id | org_id +----+-------- + 1 | 1 +(1 row) + +-- notice that the update succeed and committed +CREATE PROCEDURE test_procedure_modify_insert(tt_id int, tt_org_id int) LANGUAGE PLPGSQL AS $$ +BEGIN + UPDATE test_table SET org_id = tt_org_id WHERE id = tt_id; + COMMIT; + INSERT INTO test_table VALUES (tt_id, tt_org_id); + ROLLBACK; +END; +$$; +ERROR: syntax error at or near "PROCEDURE" +LINE 1: CREATE PROCEDURE test_procedure_modify_insert(tt_id int, tt_... + ^ +CALL test_procedure_modify_insert(2,12); +ERROR: syntax error at or near "CALL" +LINE 1: CALL test_procedure_modify_insert(2,12); + ^ +SELECT * FROM test_table ORDER BY 1, 2; + id | org_id +----+-------- + 1 | 1 +(1 row) + +CREATE PROCEDURE test_procedure_modify_insert_commit(tt_id int, tt_org_id int) LANGUAGE PLPGSQL AS $$ +BEGIN + UPDATE test_table SET org_id = tt_org_id WHERE id = tt_id; + COMMIT; + INSERT INTO test_table VALUES (tt_id, tt_org_id); + COMMIT; +END; +$$; +ERROR: syntax error at or near "PROCEDURE" +LINE 1: CREATE PROCEDURE test_procedure_modify_insert_commit(tt_id i... + ^ +CALL test_procedure_modify_insert_commit(2,30); +ERROR: syntax error at or near "CALL" +LINE 1: CALL test_procedure_modify_insert_commit(2,30); + ^ +SELECT * FROM test_table ORDER BY 1, 2; + id | org_id +----+-------- + 1 | 1 +(1 row) + +-- delete is commited but insert is rolled back +-- there is a bug #2371 on that preventing rollback +CREATE PROCEDURE test_procedure_rollback(tt_id int, tt_org_id int) LANGUAGE PLPGSQL AS $$ +BEGIN + DELETE FROM test_table; + COMMIT; + INSERT INTO test_table VALUES (tt_id, tt_org_id); + ROLLBACK; +END; +$$; +ERROR: syntax error at or near "PROCEDURE" +LINE 1: CREATE PROCEDURE test_procedure_rollback(tt_id int, tt_org_i... + ^ +CALL test_procedure_rollback(2,5); +ERROR: syntax error at or near "CALL" +LINE 1: CALL test_procedure_rollback(2,5); + ^ +SELECT * FROM test_table ORDER BY 1, 2; + id | org_id +----+-------- + 1 | 1 +(1 row) + +-- rollback is successfull when insert is on multiple rows +CREATE PROCEDURE test_procedure_rollback_2(tt_id int, tt_org_id int) LANGUAGE PLPGSQL AS $$ +BEGIN + DELETE FROM test_table; + COMMIT; + INSERT INTO test_table VALUES (tt_id, tt_org_id), (tt_id+1, tt_org_id+1); + ROLLBACK; +END; +$$; +ERROR: syntax error at or near "PROCEDURE" +LINE 1: CREATE PROCEDURE test_procedure_rollback_2(tt_id int, tt_org... + ^ +CALL test_procedure_rollback_2(12, 15); +ERROR: syntax error at or near "CALL" +LINE 1: CALL test_procedure_rollback_2(12, 15); + ^ +SELECT * FROM test_table ORDER BY 1, 2; + id | org_id +----+-------- + 1 | 1 +(1 row) + +-- delete is rolled back, update is committed +CREATE PROCEDURE test_procedure_rollback_3(tt_id int, tt_org_id int) LANGUAGE PLPGSQL AS $$ +BEGIN + DELETE FROM test_table; + ROLLBACK; + UPDATE test_table SET org_id = tt_org_id WHERE id = tt_id; + COMMIT; +END; +$$; +ERROR: syntax error at or near "PROCEDURE" +LINE 1: CREATE PROCEDURE test_procedure_rollback_3(tt_id int, tt_org... + ^ +INSERT INTO test_table VALUES (1, 1), (2, 2); +ERROR: duplicate key value violates unique constraint "idx_table_100500" +DETAIL: Key (id, org_id)=(1, 1) already exists. +CONTEXT: while executing command on localhost:57638 +CALL test_procedure_rollback_3(2,15); +ERROR: syntax error at or near "CALL" +LINE 1: CALL test_procedure_rollback_3(2,15); + ^ +SELECT * FROM test_table ORDER BY 1, 2; + id | org_id +----+-------- + 1 | 1 +(1 row) + +DROP SCHEMA procedure_schema CASCADE; +NOTICE: drop cascades to table test_table +RESET SEARCH_PATH; diff --git a/src/test/regress/multi_schedule b/src/test/regress/multi_schedule index 31949fe9f..367015ea5 100644 --- a/src/test/regress/multi_schedule +++ b/src/test/regress/multi_schedule @@ -55,6 +55,7 @@ test: multi_deparse_shard_query multi_distributed_transaction_id multi_real_time test: multi_explain test: multi_basic_queries multi_complex_expressions multi_subquery multi_subquery_complex_queries multi_subquery_behavioral_analytics test: multi_subquery_complex_reference_clause multi_subquery_window_functions multi_view multi_sql_function multi_prepare_sql +test: sql_procedure test: multi_subquery_in_where_reference_clause test: multi_subquery_union multi_subquery_in_where_clause multi_subquery_misc test: multi_agg_distinct multi_agg_approximate_distinct multi_limit_clause_approximate multi_outer_join_reference multi_single_relation_subquery multi_prepare_plsql diff --git a/src/test/regress/sql/sql_procedure.sql b/src/test/regress/sql/sql_procedure.sql new file mode 100644 index 000000000..a54bd2375 --- /dev/null +++ b/src/test/regress/sql/sql_procedure.sql @@ -0,0 +1,141 @@ +-- +-- SQL_PROCEDURE +-- +-- Tests basic PROCEDURE functionality with SQL and PLPGSQL procedures. +-- +-- print whether we're using version > 10 to make version-specific tests clear + +SHOW server_version \gset +SELECT substring(:'server_version', '\d+')::int > 10 AS version_above_ten; + +SET citus.next_shard_id TO 100500; + +CREATE SCHEMA procedure_schema; +SET SEARCH_PATH = procedure_schema; + +CREATE TABLE test_table(id integer , org_id integer); +CREATE UNIQUE INDEX idx_table ON test_table(id, org_id); +SELECT create_distributed_table('test_table','id'); + +INSERT INTO test_table VALUES(1, 1); + + +-- test CREATE PROCEDURE +CREATE PROCEDURE test_procedure_delete_insert(id int, org_id int) LANGUAGE SQL AS $$ + DELETE FROM test_table; + INSERT INTO test_table VALUES(id, org_id); +$$; + +CALL test_procedure_delete_insert(2,3); +SELECT * FROM test_table ORDER BY 1, 2; + +-- commit/rollback is not allowed in procedures in SQL +-- following calls should fail +CREATE PROCEDURE test_procedure_commit(tt_id int, tt_org_id int) LANGUAGE SQL AS $$ + DELETE FROM test_table; + COMMIT; + INSERT INTO test_table VALUES(tt_id, -1); + UPDATE test_table SET org_id = tt_org_id WHERE id = tt_id; + COMMIT; +$$; + +CALL test_procedure_commit(2,5); +SELECT * FROM test_table ORDER BY 1, 2; + +CREATE PROCEDURE test_procedure_rollback(tt_id int, tt_org_id int) LANGUAGE SQL AS $$ + DELETE FROM test_table; + ROLLBACK; + UPDATE test_table SET org_id = tt_org_id WHERE id = tt_id; + COMMIT; +$$; + +CALL test_procedure_rollback(2,15); +SELECT * FROM test_table ORDER BY 1, 2; + +DROP PROCEDURE test_procedure_delete_insert(int, int); +DROP PROCEDURE test_procedure_commit(int, int); +DROP PROCEDURE test_procedure_rollback(int, int); + +-- same tests with plpgsql + +-- test CREATE PROCEDURE +CREATE PROCEDURE test_procedure_delete_insert(id int, org_id int) LANGUAGE PLPGSQL AS $$ +BEGIN + DELETE FROM test_table; + INSERT INTO test_table VALUES(id, org_id); +END; +$$; + +CALL test_procedure_delete_insert(2,3); +SELECT * FROM test_table ORDER BY 1, 2; + +-- notice that the update succeed and committed +CREATE PROCEDURE test_procedure_modify_insert(tt_id int, tt_org_id int) LANGUAGE PLPGSQL AS $$ +BEGIN + UPDATE test_table SET org_id = tt_org_id WHERE id = tt_id; + COMMIT; + INSERT INTO test_table VALUES (tt_id, tt_org_id); + ROLLBACK; +END; +$$; + +CALL test_procedure_modify_insert(2,12); +SELECT * FROM test_table ORDER BY 1, 2; + + +CREATE PROCEDURE test_procedure_modify_insert_commit(tt_id int, tt_org_id int) LANGUAGE PLPGSQL AS $$ +BEGIN + UPDATE test_table SET org_id = tt_org_id WHERE id = tt_id; + COMMIT; + INSERT INTO test_table VALUES (tt_id, tt_org_id); + COMMIT; +END; +$$; + +CALL test_procedure_modify_insert_commit(2,30); +SELECT * FROM test_table ORDER BY 1, 2; + +-- delete is commited but insert is rolled back +-- there is a bug #2371 on that preventing rollback +CREATE PROCEDURE test_procedure_rollback(tt_id int, tt_org_id int) LANGUAGE PLPGSQL AS $$ +BEGIN + DELETE FROM test_table; + COMMIT; + INSERT INTO test_table VALUES (tt_id, tt_org_id); + ROLLBACK; +END; +$$; + +CALL test_procedure_rollback(2,5); +SELECT * FROM test_table ORDER BY 1, 2; + +-- rollback is successfull when insert is on multiple rows +CREATE PROCEDURE test_procedure_rollback_2(tt_id int, tt_org_id int) LANGUAGE PLPGSQL AS $$ +BEGIN + DELETE FROM test_table; + COMMIT; + INSERT INTO test_table VALUES (tt_id, tt_org_id), (tt_id+1, tt_org_id+1); + ROLLBACK; +END; +$$; + +CALL test_procedure_rollback_2(12, 15); +SELECT * FROM test_table ORDER BY 1, 2; + +-- delete is rolled back, update is committed +CREATE PROCEDURE test_procedure_rollback_3(tt_id int, tt_org_id int) LANGUAGE PLPGSQL AS $$ +BEGIN + DELETE FROM test_table; + ROLLBACK; + UPDATE test_table SET org_id = tt_org_id WHERE id = tt_id; + COMMIT; +END; +$$; + +INSERT INTO test_table VALUES (1, 1), (2, 2); +CALL test_procedure_rollback_3(2,15); +SELECT * FROM test_table ORDER BY 1, 2; + +DROP SCHEMA procedure_schema CASCADE; + +RESET SEARCH_PATH; \ No newline at end of file