-- -- 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;