From 27616cca52446906e62e40d6ddb1279963e9451b Mon Sep 17 00:00:00 2001 From: Metin Doslu Date: Thu, 29 Sep 2016 13:37:15 +0300 Subject: [PATCH] Add regression tests for parameterized queries --- .../regress/expected/multi_prepare_plsql.out | 749 ++++++++++++++---- .../regress/expected/multi_prepare_sql.out | 482 +++++++++++ .../regress/expected/multi_sql_function.out | 330 ++++++++ src/test/regress/multi_schedule | 1 + src/test/regress/sql/multi_prepare_plsql.sql | 365 ++++++--- src/test/regress/sql/multi_prepare_sql.sql | 247 ++++++ src/test/regress/sql/multi_sql_function.sql | 154 ++++ 7 files changed, 2058 insertions(+), 270 deletions(-) create mode 100644 src/test/regress/expected/multi_sql_function.out create mode 100644 src/test/regress/sql/multi_sql_function.sql diff --git a/src/test/regress/expected/multi_prepare_plsql.out b/src/test/regress/expected/multi_prepare_plsql.out index 918c5919c..6f41b00f3 100644 --- a/src/test/regress/expected/multi_prepare_plsql.out +++ b/src/test/regress/expected/multi_prepare_plsql.out @@ -6,47 +6,7 @@ -- use prepared statements internally. ALTER SEQUENCE pg_catalog.pg_dist_shardid_seq RESTART 780000; ALTER SEQUENCE pg_catalog.pg_dist_jobid_seq RESTART 780000; -CREATE FUNCTION sql_test_no_1() RETURNS bigint AS ' - SELECT - count(*) - FROM - orders; -' LANGUAGE SQL; -CREATE FUNCTION sql_test_no_2() RETURNS bigint AS ' - SELECT - count(*) - FROM - orders, lineitem - WHERE - o_orderkey = l_orderkey; -' LANGUAGE SQL; -CREATE FUNCTION sql_test_no_3() RETURNS bigint AS ' - SELECT - count(*) - FROM - orders, customer - WHERE - o_custkey = c_custkey; -' LANGUAGE SQL; -CREATE FUNCTION sql_test_no_4() RETURNS bigint AS ' - SELECT - count(*) - FROM - orders, customer, lineitem - WHERE - o_custkey = c_custkey AND - o_orderkey = l_orderkey; -' LANGUAGE SQL; -CREATE OR REPLACE FUNCTION sql_test_no_6(integer) RETURNS bigint AS $$ - SELECT - count(*) - FROM - orders, lineitem - WHERE - o_orderkey = l_orderkey AND - l_suppkey > $1; -$$ LANGUAGE SQL RETURNS NULL ON NULL INPUT; -CREATE OR REPLACE FUNCTION plpgsql_test_1() RETURNS TABLE(count bigint) AS $$ +CREATE FUNCTION plpgsql_test_1() RETURNS TABLE(count bigint) AS $$ DECLARE BEGIN RETURN QUERY @@ -57,7 +17,7 @@ BEGIN END; $$ LANGUAGE plpgsql; -CREATE OR REPLACE FUNCTION plpgsql_test_2() RETURNS TABLE(count bigint) AS $$ +CREATE FUNCTION plpgsql_test_2() RETURNS TABLE(count bigint) AS $$ DECLARE BEGIN RETURN QUERY @@ -70,7 +30,7 @@ BEGIN END; $$ LANGUAGE plpgsql; -CREATE OR REPLACE FUNCTION plpgsql_test_3() RETURNS TABLE(count bigint) AS $$ +CREATE FUNCTION plpgsql_test_3() RETURNS TABLE(count bigint) AS $$ DECLARE BEGIN RETURN QUERY @@ -83,7 +43,7 @@ BEGIN END; $$ LANGUAGE plpgsql; -CREATE OR REPLACE FUNCTION plpgsql_test_4() RETURNS TABLE(count bigint) AS $$ +CREATE FUNCTION plpgsql_test_4() RETURNS TABLE(count bigint) AS $$ DECLARE BEGIN RETURN QUERY @@ -96,7 +56,7 @@ BEGIN o_orderkey = l_orderkey; END; $$ LANGUAGE plpgsql; -CREATE OR REPLACE FUNCTION plpgsql_test_5() RETURNS TABLE(count bigint) AS $$ +CREATE FUNCTION plpgsql_test_5() RETURNS TABLE(count bigint) AS $$ DECLARE BEGIN RETURN QUERY @@ -108,7 +68,7 @@ BEGIN l_partkey = c_nationkey; END; $$ LANGUAGE plpgsql; -CREATE OR REPLACE FUNCTION plpgsql_test_6(int) RETURNS TABLE(count bigint) AS $$ +CREATE FUNCTION plpgsql_test_6(int) RETURNS TABLE(count bigint) AS $$ DECLARE BEGIN RETURN QUERY @@ -121,7 +81,7 @@ BEGIN l_suppkey > $1; END; $$ LANGUAGE plpgsql; -CREATE OR REPLACE FUNCTION plpgsql_test_7(text, text) RETURNS TABLE(supp_natadsion text, cusasdt_nation text, l_yeasdar int, sasdaum double precision) AS $$ +CREATE FUNCTION plpgsql_test_7(text, text) RETURNS TABLE(supp_natadsion text, cusasdt_nation text, l_yeasdar int, sasdaum double precision) AS $$ DECLARE BEGIN RETURN QUERY @@ -177,31 +137,6 @@ END; $$ LANGUAGE plpgsql; SET citus.task_executor_type TO 'task-tracker'; SET client_min_messages TO INFO; --- now, run plain SQL functions -SELECT sql_test_no_1(); - sql_test_no_1 ---------------- - 2984 -(1 row) - -SELECT sql_test_no_2(); - sql_test_no_2 ---------------- - 11998 -(1 row) - -SELECT sql_test_no_3(); - sql_test_no_3 ---------------- - 1955 -(1 row) - -SELECT sql_test_no_4(); - sql_test_no_4 ---------------- - 7804 -(1 row) - -- now, run PL/pgsql functions SELECT plpgsql_test_1(); plpgsql_test_1 @@ -316,23 +251,6 @@ SELECT plpgsql_test_2(); -- run the tests which do not require re-partition -- with real-time executor SET citus.task_executor_type TO 'real-time'; --- now, run plain SQL functions -SELECT sql_test_no_1(); - sql_test_no_1 ---------------- - 2984 -(1 row) - -SELECT sql_test_no_2(); - sql_test_no_2 ---------------- - 11998 -(1 row) - --- plain SQL functions with parameters cannot be executed --- FIXME: temporarily disabled, bad error message - waiting for proper parametrized query --- FIXME: support --- SELECT sql_test_no_6(155); -- now, run PL/pgsql functions SELECT plpgsql_test_1(); plpgsql_test_1 @@ -351,25 +269,25 @@ SELECT plpgsql_test_2(); -- SELECT plpgsql_test_6(155); -- SELECT plpgsql_test_6(1555); -- test router executor parameterized PL/pgsql functions -CREATE TABLE temp_table ( +CREATE TABLE plpgsql_table ( key int, value int ); -SELECT master_create_distributed_table('temp_table','key','hash'); +SELECT master_create_distributed_table('plpgsql_table','key','hash'); master_create_distributed_table --------------------------------- (1 row) -SELECT master_create_worker_shards('temp_table',4,1); +SELECT master_create_worker_shards('plpgsql_table',4,1); master_create_worker_shards ----------------------------- (1 row) -CREATE OR REPLACE FUNCTION no_parameter_insert() RETURNS void as $$ +CREATE FUNCTION no_parameter_insert() RETURNS void as $$ BEGIN - INSERT INTO temp_table (key) VALUES (0); + INSERT INTO plpgsql_table (key) VALUES (0); END; $$ LANGUAGE plpgsql; -- execute 6 times to trigger prepared statement usage @@ -409,9 +327,10 @@ SELECT no_parameter_insert(); (1 row) -CREATE OR REPLACE FUNCTION single_parameter_insert(key_arg int) RETURNS void as $$ +CREATE FUNCTION single_parameter_insert(key_arg int) + RETURNS void as $$ BEGIN - INSERT INTO temp_table (key) VALUES (key_arg); + INSERT INTO plpgsql_table (key) VALUES (key_arg); END; $$ LANGUAGE plpgsql; -- execute 6 times to trigger prepared statement usage @@ -447,11 +366,12 @@ SELECT single_parameter_insert(5); SELECT single_parameter_insert(6); ERROR: values given for the partition column must be constants or constant expressions -CONTEXT: SQL statement "INSERT INTO temp_table (key) VALUES (key_arg)" +CONTEXT: SQL statement "INSERT INTO plpgsql_table (key) VALUES (key_arg)" PL/pgSQL function single_parameter_insert(integer) line 3 at SQL statement -CREATE OR REPLACE FUNCTION double_parameter_insert(key_arg int, value_arg int) RETURNS void as $$ +CREATE FUNCTION double_parameter_insert(key_arg int, value_arg int) + RETURNS void as $$ BEGIN - INSERT INTO temp_table (key, value) VALUES (key_arg, value_arg); + INSERT INTO plpgsql_table (key, value) VALUES (key_arg, value_arg); END; $$ LANGUAGE plpgsql; -- execute 6 times to trigger prepared statement usage @@ -487,12 +407,61 @@ SELECT double_parameter_insert(5, 50); SELECT double_parameter_insert(6, 60); ERROR: values given for the partition column must be constants or constant expressions -CONTEXT: SQL statement "INSERT INTO temp_table (key, value) VALUES (key_arg, value_arg)" +CONTEXT: SQL statement "INSERT INTO plpgsql_table (key, value) VALUES (key_arg, value_arg)" PL/pgSQL function double_parameter_insert(integer,integer) line 3 at SQL statement +CREATE FUNCTION non_partition_parameter_insert(value_arg int) + RETURNS void as $$ +BEGIN + INSERT INTO plpgsql_table (key, value) VALUES (0, value_arg); +END; +$$ LANGUAGE plpgsql; +-- execute 6 times to trigger prepared statement usage +SELECT non_partition_parameter_insert(10); + non_partition_parameter_insert +-------------------------------- + +(1 row) + +SELECT non_partition_parameter_insert(20); + non_partition_parameter_insert +-------------------------------- + +(1 row) + +SELECT non_partition_parameter_insert(30); + non_partition_parameter_insert +-------------------------------- + +(1 row) + +SELECT non_partition_parameter_insert(40); + non_partition_parameter_insert +-------------------------------- + +(1 row) + +SELECT non_partition_parameter_insert(50); + non_partition_parameter_insert +-------------------------------- + +(1 row) + +SELECT non_partition_parameter_insert(60); + non_partition_parameter_insert +-------------------------------- + +(1 row) + -- check inserted values -SELECT * FROM temp_table ORDER BY key, value; +SELECT * FROM plpgsql_table ORDER BY key, value; key | value -----+------- + 0 | 10 + 0 | 20 + 0 | 30 + 0 | 40 + 0 | 50 + 0 | 60 0 | 0 | 0 | @@ -509,119 +478,570 @@ SELECT * FROM temp_table ORDER BY key, value; 4 | 5 | 50 5 | -(16 rows) +(22 rows) -- check router executor select -CREATE OR REPLACE FUNCTION partition_column_select(key_arg int) RETURNS TABLE(key int, value int) AS $$ +CREATE FUNCTION router_partition_column_select(key_arg int) + RETURNS TABLE(key int, value int) AS $$ DECLARE BEGIN RETURN QUERY SELECT - temp_table.key, - temp_table.value + plpgsql_table.key, + plpgsql_table.value FROM - temp_table + plpgsql_table WHERE - temp_table.key = key_arg + plpgsql_table.key = key_arg ORDER BY key, value; END; $$ LANGUAGE plpgsql; -SELECT partition_column_select(1); - partition_column_select -------------------------- +SELECT router_partition_column_select(1); + router_partition_column_select +-------------------------------- (1,10) (1,) (2 rows) -SELECT partition_column_select(2); - partition_column_select -------------------------- +SELECT router_partition_column_select(2); + router_partition_column_select +-------------------------------- (2,20) (2,) (2 rows) -SELECT partition_column_select(3); - partition_column_select -------------------------- +SELECT router_partition_column_select(3); + router_partition_column_select +-------------------------------- (3,30) (3,) (2 rows) -SELECT partition_column_select(4); - partition_column_select -------------------------- +SELECT router_partition_column_select(4); + router_partition_column_select +-------------------------------- (4,40) (4,) (2 rows) -SELECT partition_column_select(5); - partition_column_select -------------------------- +SELECT router_partition_column_select(5); + router_partition_column_select +-------------------------------- (5,50) (5,) (2 rows) --- 6th execution is failing. We don't want to run the failing test because of --- changing output. After implementing this feature, uncomment this. --- SELECT partition_column_select(6); --- check real-time executor -CREATE OR REPLACE FUNCTION non_partition_column_select(value_arg int) RETURNS TABLE(key int, value int) AS $$ +-- FIXME: 6th execution is failing. We don't want to run the failing test +-- because of changing output. After implementing this feature, uncomment this. +-- SELECT router_partition_column_select(6); +CREATE FUNCTION router_non_partition_column_select(value_arg int) + RETURNS TABLE(key int, value int) AS $$ DECLARE BEGIN RETURN QUERY SELECT - temp_table.key, - temp_table.value + plpgsql_table.key, + plpgsql_table.value FROM - temp_table + plpgsql_table WHERE - temp_table.value = value_arg + plpgsql_table.key = 0 AND + plpgsql_table.value = value_arg ORDER BY key, value; END; $$ LANGUAGE plpgsql; -SELECT non_partition_column_select(10); - non_partition_column_select ------------------------------ +SELECT router_non_partition_column_select(10); + router_non_partition_column_select +------------------------------------ + (0,10) +(1 row) + +SELECT router_non_partition_column_select(20); + router_non_partition_column_select +------------------------------------ + (0,20) +(1 row) + +SELECT router_non_partition_column_select(30); + router_non_partition_column_select +------------------------------------ + (0,30) +(1 row) + +SELECT router_non_partition_column_select(40); + router_non_partition_column_select +------------------------------------ + (0,40) +(1 row) + +SELECT router_non_partition_column_select(50); + router_non_partition_column_select +------------------------------------ + (0,50) +(1 row) + +SELECT router_non_partition_column_select(60); + router_non_partition_column_select +------------------------------------ + (0,60) +(1 row) + +-- check real-time executor +CREATE FUNCTION real_time_non_partition_column_select(value_arg int) + RETURNS TABLE(key int, value int) AS $$ +DECLARE +BEGIN + RETURN QUERY + SELECT + plpgsql_table.key, + plpgsql_table.value + FROM + plpgsql_table + WHERE + plpgsql_table.value = value_arg + ORDER BY + key, + value; +END; +$$ LANGUAGE plpgsql; +SELECT real_time_non_partition_column_select(10); + real_time_non_partition_column_select +--------------------------------------- + (0,10) (1,10) -(1 row) +(2 rows) -SELECT non_partition_column_select(20); - non_partition_column_select ------------------------------ +SELECT real_time_non_partition_column_select(20); + real_time_non_partition_column_select +--------------------------------------- + (0,20) (2,20) -(1 row) +(2 rows) -SELECT non_partition_column_select(30); - non_partition_column_select ------------------------------ +SELECT real_time_non_partition_column_select(30); + real_time_non_partition_column_select +--------------------------------------- + (0,30) (3,30) -(1 row) +(2 rows) -SELECT non_partition_column_select(40); - non_partition_column_select ------------------------------ +SELECT real_time_non_partition_column_select(40); + real_time_non_partition_column_select +--------------------------------------- + (0,40) (4,40) -(1 row) +(2 rows) -SELECT non_partition_column_select(50); - non_partition_column_select ------------------------------ +SELECT real_time_non_partition_column_select(50); + real_time_non_partition_column_select +--------------------------------------- + (0,50) (5,50) +(2 rows) + +-- FIXME: 6th execution is failing. We don't want to run the failing test +-- because of changing output. After implementing this feature, uncomment this. +-- SELECT real_time_non_partition_column_select(60); +CREATE FUNCTION real_time_partition_column_select(key_arg int) + RETURNS TABLE(key int, value int) AS $$ +DECLARE +BEGIN + RETURN QUERY + SELECT + plpgsql_table.key, + plpgsql_table.value + FROM + plpgsql_table + WHERE + plpgsql_table.key = key_arg OR + plpgsql_table.value = 10 + ORDER BY + key, + value; +END; +$$ LANGUAGE plpgsql; +SELECT real_time_partition_column_select(1); + real_time_partition_column_select +----------------------------------- + (0,10) + (1,10) + (1,) +(3 rows) + +SELECT real_time_partition_column_select(2); + real_time_partition_column_select +----------------------------------- + (0,10) + (1,10) + (2,20) + (2,) +(4 rows) + +SELECT real_time_partition_column_select(3); + real_time_partition_column_select +----------------------------------- + (0,10) + (1,10) + (3,30) + (3,) +(4 rows) + +SELECT real_time_partition_column_select(4); + real_time_partition_column_select +----------------------------------- + (0,10) + (1,10) + (4,40) + (4,) +(4 rows) + +SELECT real_time_partition_column_select(5); + real_time_partition_column_select +----------------------------------- + (0,10) + (1,10) + (5,50) + (5,) +(4 rows) + +-- FIXME: 6th execution is failing. We don't want to run the failing test +-- because of changing output. After implementing this feature, uncomment this. +-- SELECT real_time_partition_column_select(6); +-- check task-tracker executor +SET citus.task_executor_type TO 'task-tracker'; +CREATE FUNCTION task_tracker_non_partition_column_select(value_arg int) + RETURNS TABLE(key int, value int) AS $$ +DECLARE +BEGIN + RETURN QUERY + SELECT + plpgsql_table.key, + plpgsql_table.value + FROM + plpgsql_table + WHERE + plpgsql_table.value = value_arg + ORDER BY + key, + value; +END; +$$ LANGUAGE plpgsql; +SELECT task_tracker_non_partition_column_select(10); + task_tracker_non_partition_column_select +------------------------------------------ + (0,10) + (1,10) +(2 rows) + +SELECT task_tracker_non_partition_column_select(20); + task_tracker_non_partition_column_select +------------------------------------------ + (0,20) + (2,20) +(2 rows) + +SELECT task_tracker_non_partition_column_select(30); + task_tracker_non_partition_column_select +------------------------------------------ + (0,30) + (3,30) +(2 rows) + +SELECT task_tracker_non_partition_column_select(40); + task_tracker_non_partition_column_select +------------------------------------------ + (0,40) + (4,40) +(2 rows) + +SELECT task_tracker_non_partition_column_select(50); + task_tracker_non_partition_column_select +------------------------------------------ + (0,50) + (5,50) +(2 rows) + +-- FIXME: 6th execution is failing. We don't want to run the failing test +-- because of changing output. After implementing this feature, uncomment this. +-- SELECT real_time_non_partition_column_select(60); +CREATE FUNCTION task_tracker_partition_column_select(key_arg int) + RETURNS TABLE(key int, value int) AS $$ +DECLARE +BEGIN + RETURN QUERY + SELECT + plpgsql_table.key, + plpgsql_table.value + FROM + plpgsql_table + WHERE + plpgsql_table.key = key_arg OR + plpgsql_table.value = 10 + ORDER BY + key, + value; +END; +$$ LANGUAGE plpgsql; +SELECT task_tracker_partition_column_select(1); + task_tracker_partition_column_select +-------------------------------------- + (0,10) + (1,10) + (1,) +(3 rows) + +SELECT task_tracker_partition_column_select(2); + task_tracker_partition_column_select +-------------------------------------- + (0,10) + (1,10) + (2,20) + (2,) +(4 rows) + +SELECT task_tracker_partition_column_select(3); + task_tracker_partition_column_select +-------------------------------------- + (0,10) + (1,10) + (3,30) + (3,) +(4 rows) + +SELECT task_tracker_partition_column_select(4); + task_tracker_partition_column_select +-------------------------------------- + (0,10) + (1,10) + (4,40) + (4,) +(4 rows) + +SELECT task_tracker_partition_column_select(5); + task_tracker_partition_column_select +-------------------------------------- + (0,10) + (1,10) + (5,50) + (5,) +(4 rows) + +-- FIXME: 6th execution is failing. We don't want to run the failing test +-- because of changing output. After implementing this feature, uncomment this. +-- SELECT task_tracker_partition_column_select(6); +SET citus.task_executor_type TO 'real-time'; +-- check updates +CREATE FUNCTION partition_parameter_update(int, int) RETURNS void as $$ +BEGIN + UPDATE plpgsql_table SET value = $2 WHERE key = $1; +END; +$$ LANGUAGE plpgsql; +-- execute 6 times to trigger prepared statement usage +SELECT partition_parameter_update(1, 11); + partition_parameter_update +---------------------------- + (1 row) --- 6th execution is failing. We don't want to run the failing test because of --- changing output. After implementing this feature, uncomment this. --- SELECT partition_column_select(6); +SELECT partition_parameter_update(2, 21); + partition_parameter_update +---------------------------- + +(1 row) + +SELECT partition_parameter_update(3, 31); + partition_parameter_update +---------------------------- + +(1 row) + +SELECT partition_parameter_update(4, 41); + partition_parameter_update +---------------------------- + +(1 row) + +SELECT partition_parameter_update(5, 51); + partition_parameter_update +---------------------------- + +(1 row) + +-- This fails with an unexpected error message +SELECT partition_parameter_update(5, 52); +ERROR: distributed modifications must target exactly one shard +CONTEXT: SQL statement "UPDATE plpgsql_table SET value = $2 WHERE key = $1" +PL/pgSQL function partition_parameter_update(integer,integer) line 3 at SQL statement +CREATE FUNCTION non_partition_parameter_update(int, int) RETURNS void as $$ +BEGIN + UPDATE plpgsql_table SET value = $2 WHERE key = 0 AND value = $1; +END; +$$ LANGUAGE plpgsql; +-- execute 6 times to trigger prepared statement usage +SELECT non_partition_parameter_update(10, 12); + non_partition_parameter_update +-------------------------------- + +(1 row) + +SELECT non_partition_parameter_update(20, 22); + non_partition_parameter_update +-------------------------------- + +(1 row) + +SELECT non_partition_parameter_update(30, 32); + non_partition_parameter_update +-------------------------------- + +(1 row) + +SELECT non_partition_parameter_update(40, 42); + non_partition_parameter_update +-------------------------------- + +(1 row) + +SELECT non_partition_parameter_update(50, 52); + non_partition_parameter_update +-------------------------------- + +(1 row) + +SELECT non_partition_parameter_update(60, 62); + non_partition_parameter_update +-------------------------------- + +(1 row) + +-- check table after updates +SELECT * FROM plpgsql_table ORDER BY key, value; + key | value +-----+------- + 0 | 12 + 0 | 22 + 0 | 32 + 0 | 42 + 0 | 52 + 0 | 62 + 0 | + 0 | + 0 | + 0 | + 0 | + 0 | + 1 | 11 + 1 | 11 + 2 | 21 + 2 | 21 + 3 | 31 + 3 | 31 + 4 | 41 + 4 | 41 + 5 | 51 + 5 | 51 +(22 rows) + +-- check deletes +CREATE FUNCTION partition_parameter_delete(int, int) RETURNS void as $$ +BEGIN + DELETE FROM plpgsql_table WHERE key = $1 AND value = $2; +END; +$$ LANGUAGE plpgsql; +SELECT partition_parameter_delete(1, 11); + partition_parameter_delete +---------------------------- + +(1 row) + +SELECT partition_parameter_delete(2, 21); + partition_parameter_delete +---------------------------- + +(1 row) + +SELECT partition_parameter_delete(3, 31); + partition_parameter_delete +---------------------------- + +(1 row) + +SELECT partition_parameter_delete(4, 41); + partition_parameter_delete +---------------------------- + +(1 row) + +SELECT partition_parameter_delete(5, 51); + partition_parameter_delete +---------------------------- + +(1 row) + +-- This fails with an unexpected error message +SELECT partition_parameter_delete(0, 10); +ERROR: distributed modifications must target exactly one shard +CONTEXT: SQL statement "DELETE FROM plpgsql_table WHERE key = $1 AND value = $2" +PL/pgSQL function partition_parameter_delete(integer,integer) line 3 at SQL statement +CREATE FUNCTION non_partition_parameter_delete(int) RETURNS void as $$ +BEGIN + DELETE FROM plpgsql_table WHERE key = 0 AND value = $1; +END; +$$ LANGUAGE plpgsql; +-- execute 6 times to trigger prepared statement usage +SELECT non_partition_parameter_delete(12); + non_partition_parameter_delete +-------------------------------- + +(1 row) + +SELECT non_partition_parameter_delete(22); + non_partition_parameter_delete +-------------------------------- + +(1 row) + +SELECT non_partition_parameter_delete(32); + non_partition_parameter_delete +-------------------------------- + +(1 row) + +SELECT non_partition_parameter_delete(42); + non_partition_parameter_delete +-------------------------------- + +(1 row) + +SELECT non_partition_parameter_delete(52); + non_partition_parameter_delete +-------------------------------- + +(1 row) + +SELECT non_partition_parameter_delete(62); + non_partition_parameter_delete +-------------------------------- + +(1 row) + +-- check table after deletes +SELECT * FROM plpgsql_table ORDER BY key, value; + key | value +-----+------- + 0 | + 0 | + 0 | + 0 | + 0 | + 0 | +(6 rows) + -- clean-up functions -DROP FUNCTION sql_test_no_1(); -DROP FUNCTION sql_test_no_2(); -DROP FUNCTION sql_test_no_3(); -DROP FUNCTION sql_test_no_4(); -DROP FUNCTION sql_test_no_6(int); DROP FUNCTION plpgsql_test_1(); DROP FUNCTION plpgsql_test_2(); DROP FUNCTION plpgsql_test_3(); @@ -632,5 +1052,14 @@ DROP FUNCTION plpgsql_test_7(text, text); DROP FUNCTION no_parameter_insert(); DROP FUNCTION single_parameter_insert(int); DROP FUNCTION double_parameter_insert(int, int); -DROP FUNCTION partition_column_select(int); -DROP FUNCTION non_partition_column_select(int); +DROP FUNCTION non_partition_parameter_insert(int); +DROP FUNCTION router_partition_column_select(int); +DROP FUNCTION router_non_partition_column_select(int); +DROP FUNCTION real_time_non_partition_column_select(int); +DROP FUNCTION real_time_partition_column_select(int); +DROP FUNCTION task_tracker_non_partition_column_select(int); +DROP FUNCTION task_tracker_partition_column_select(int); +DROP FUNCTION partition_parameter_update(int, int); +DROP FUNCTION non_partition_parameter_update(int, int); +DROP FUNCTION partition_parameter_delete(int, int); +DROP FUNCTION non_partition_parameter_delete(int); diff --git a/src/test/regress/expected/multi_prepare_sql.out b/src/test/regress/expected/multi_prepare_sql.out index ae04d6ee0..15b4de64d 100644 --- a/src/test/regress/expected/multi_prepare_sql.out +++ b/src/test/regress/expected/multi_prepare_sql.out @@ -338,5 +338,487 @@ EXECUTE prepared_partition_column_insert(6); ERROR: values given for the partition column must be constants or constant expressions DROP TYPE test_composite_type CASCADE; NOTICE: drop cascades to table router_executor_table column stats +-- test router executor with prepare statements +CREATE TABLE prepare_table ( + key int, + value int +); +SELECT master_create_distributed_table('prepare_table','key','hash'); + master_create_distributed_table +--------------------------------- + +(1 row) + +SELECT master_create_worker_shards('prepare_table',4,1); + master_create_worker_shards +----------------------------- + +(1 row) + +PREPARE prepared_no_parameter_insert AS + INSERT INTO prepare_table (key) VALUES (0); +-- execute 6 times to trigger prepared statement usage +EXECUTE prepared_no_parameter_insert; +EXECUTE prepared_no_parameter_insert; +EXECUTE prepared_no_parameter_insert; +EXECUTE prepared_no_parameter_insert; +EXECUTE prepared_no_parameter_insert; +EXECUTE prepared_no_parameter_insert; +PREPARE prepared_single_parameter_insert(int) AS + INSERT INTO prepare_table (key) VALUES ($1); +-- execute 6 times to trigger prepared statement usage +EXECUTE prepared_single_parameter_insert(1); +EXECUTE prepared_single_parameter_insert(2); +EXECUTE prepared_single_parameter_insert(3); +EXECUTE prepared_single_parameter_insert(4); +EXECUTE prepared_single_parameter_insert(5); +EXECUTE prepared_single_parameter_insert(6); +ERROR: values given for the partition column must be constants or constant expressions +PREPARE prepared_double_parameter_insert(int, int) AS + INSERT INTO prepare_table (key, value) VALUES ($1, $2); +-- execute 6 times to trigger prepared statement usage +EXECUTE prepared_double_parameter_insert(1, 10); +EXECUTE prepared_double_parameter_insert(2, 20); +EXECUTE prepared_double_parameter_insert(3, 30); +EXECUTE prepared_double_parameter_insert(4, 40); +EXECUTE prepared_double_parameter_insert(5, 50); +EXECUTE prepared_double_parameter_insert(6, 60); +ERROR: values given for the partition column must be constants or constant expressions +PREPARE prepared_non_partition_parameter_insert(int) AS + INSERT INTO prepare_table (key, value) VALUES (0, $1); +-- execute 6 times to trigger prepared statement usage +EXECUTE prepared_non_partition_parameter_insert(10); +EXECUTE prepared_non_partition_parameter_insert(20); +EXECUTE prepared_non_partition_parameter_insert(30); +EXECUTE prepared_non_partition_parameter_insert(40); +EXECUTE prepared_non_partition_parameter_insert(50); +EXECUTE prepared_non_partition_parameter_insert(60); +-- check inserted values +SELECT * FROM prepare_table ORDER BY key, value; + key | value +-----+------- + 0 | 10 + 0 | 20 + 0 | 30 + 0 | 40 + 0 | 50 + 0 | 60 + 0 | + 0 | + 0 | + 0 | + 0 | + 0 | + 1 | 10 + 1 | + 2 | 20 + 2 | + 3 | 30 + 3 | + 4 | 40 + 4 | + 5 | 50 + 5 | +(22 rows) + +-- check router executor select +PREPARE prepared_router_partition_column_select(int) AS + SELECT + prepare_table.key, + prepare_table.value + FROM + prepare_table + WHERE + prepare_table.key = $1 + ORDER BY + key, + value; +EXECUTE prepared_router_partition_column_select(1); + key | value +-----+------- + 1 | 10 + 1 | +(2 rows) + +EXECUTE prepared_router_partition_column_select(2); + key | value +-----+------- + 2 | 20 + 2 | +(2 rows) + +EXECUTE prepared_router_partition_column_select(3); + key | value +-----+------- + 3 | 30 + 3 | +(2 rows) + +EXECUTE prepared_router_partition_column_select(4); + key | value +-----+------- + 4 | 40 + 4 | +(2 rows) + +EXECUTE prepared_router_partition_column_select(5); + key | value +-----+------- + 5 | 50 + 5 | +(2 rows) + +-- FIXME: 6th execution is failing. We don't want to run the failing test +-- because of changing output. After implementing this feature, uncomment this. +-- EXECUTE prepared_router_partition_column_select(6); +PREPARE prepared_router_non_partition_column_select(int) AS + SELECT + prepare_table.key, + prepare_table.value + FROM + prepare_table + WHERE + prepare_table.key = 0 AND + prepare_table.value = $1 + ORDER BY + key, + value; +EXECUTE prepared_router_non_partition_column_select(10); + key | value +-----+------- + 0 | 10 +(1 row) + +EXECUTE prepared_router_non_partition_column_select(20); + key | value +-----+------- + 0 | 20 +(1 row) + +EXECUTE prepared_router_non_partition_column_select(30); + key | value +-----+------- + 0 | 30 +(1 row) + +EXECUTE prepared_router_non_partition_column_select(40); + key | value +-----+------- + 0 | 40 +(1 row) + +EXECUTE prepared_router_non_partition_column_select(50); + key | value +-----+------- + 0 | 50 +(1 row) + +EXECUTE prepared_router_non_partition_column_select(60); + key | value +-----+------- + 0 | 60 +(1 row) + +-- check real-time executor +PREPARE prepared_real_time_non_partition_column_select(int) AS + SELECT + prepare_table.key, + prepare_table.value + FROM + prepare_table + WHERE + prepare_table.value = $1 + ORDER BY + key, + value; +EXECUTE prepared_real_time_non_partition_column_select(10); + key | value +-----+------- + 0 | 10 + 1 | 10 +(2 rows) + +EXECUTE prepared_real_time_non_partition_column_select(20); + key | value +-----+------- + 0 | 20 + 2 | 20 +(2 rows) + +EXECUTE prepared_real_time_non_partition_column_select(30); + key | value +-----+------- + 0 | 30 + 3 | 30 +(2 rows) + +EXECUTE prepared_real_time_non_partition_column_select(40); + key | value +-----+------- + 0 | 40 + 4 | 40 +(2 rows) + +EXECUTE prepared_real_time_non_partition_column_select(50); + key | value +-----+------- + 0 | 50 + 5 | 50 +(2 rows) + +-- FIXME: 6th execution is failing. We don't want to run the failing test +-- because of changing output. After implementing this feature, uncomment this. +-- EXECUTE prepared_real_time_non_partition_column_select(60); +PREPARE prepared_real_time_partition_column_select(int) AS + SELECT + prepare_table.key, + prepare_table.value + FROM + prepare_table + WHERE + prepare_table.key = $1 OR + prepare_table.value = 10 + ORDER BY + key, + value; +EXECUTE prepared_real_time_partition_column_select(1); + key | value +-----+------- + 0 | 10 + 1 | 10 + 1 | +(3 rows) + +EXECUTE prepared_real_time_partition_column_select(2); + key | value +-----+------- + 0 | 10 + 1 | 10 + 2 | 20 + 2 | +(4 rows) + +EXECUTE prepared_real_time_partition_column_select(3); + key | value +-----+------- + 0 | 10 + 1 | 10 + 3 | 30 + 3 | +(4 rows) + +EXECUTE prepared_real_time_partition_column_select(4); + key | value +-----+------- + 0 | 10 + 1 | 10 + 4 | 40 + 4 | +(4 rows) + +EXECUTE prepared_real_time_partition_column_select(5); + key | value +-----+------- + 0 | 10 + 1 | 10 + 5 | 50 + 5 | +(4 rows) + +-- FIXME: 6th execution is failing. We don't want to run the failing test +-- because of changing output. After implementing this feature, uncomment this. +-- EXECUTE prepared_real_time_partition_column_select(6); +-- check task-tracker executor +SET citus.task_executor_type TO 'task-tracker'; +PREPARE prepared_task_tracker_non_partition_column_select(int) AS + SELECT + prepare_table.key, + prepare_table.value + FROM + prepare_table + WHERE + prepare_table.value = $1 + ORDER BY + key, + value; +EXECUTE prepared_task_tracker_non_partition_column_select(10); + key | value +-----+------- + 0 | 10 + 1 | 10 +(2 rows) + +EXECUTE prepared_task_tracker_non_partition_column_select(20); + key | value +-----+------- + 0 | 20 + 2 | 20 +(2 rows) + +EXECUTE prepared_task_tracker_non_partition_column_select(30); + key | value +-----+------- + 0 | 30 + 3 | 30 +(2 rows) + +EXECUTE prepared_task_tracker_non_partition_column_select(40); + key | value +-----+------- + 0 | 40 + 4 | 40 +(2 rows) + +EXECUTE prepared_task_tracker_non_partition_column_select(50); + key | value +-----+------- + 0 | 50 + 5 | 50 +(2 rows) + +-- FIXME: 6th execution is failing. We don't want to run the failing test +-- because of changing output. After implementing this feature, uncomment this. +-- EXECUTE prepared_task_tracker_non_partition_column_select(60); +PREPARE prepared_task_tracker_partition_column_select(int) AS + SELECT + prepare_table.key, + prepare_table.value + FROM + prepare_table + WHERE + prepare_table.key = $1 OR + prepare_table.value = 10 + ORDER BY + key, + value; +EXECUTE prepared_task_tracker_partition_column_select(1); + key | value +-----+------- + 0 | 10 + 1 | 10 + 1 | +(3 rows) + +EXECUTE prepared_task_tracker_partition_column_select(2); + key | value +-----+------- + 0 | 10 + 1 | 10 + 2 | 20 + 2 | +(4 rows) + +EXECUTE prepared_task_tracker_partition_column_select(3); + key | value +-----+------- + 0 | 10 + 1 | 10 + 3 | 30 + 3 | +(4 rows) + +EXECUTE prepared_task_tracker_partition_column_select(4); + key | value +-----+------- + 0 | 10 + 1 | 10 + 4 | 40 + 4 | +(4 rows) + +EXECUTE prepared_task_tracker_partition_column_select(5); + key | value +-----+------- + 0 | 10 + 1 | 10 + 5 | 50 + 5 | +(4 rows) + +-- FIXME: 6th execution is failing. We don't want to run the failing test +-- because of changing output. After implementing this feature, uncomment this. +-- EXECUTE prepared_task_tracker_partition_column_select(6); +SET citus.task_executor_type TO 'real-time'; +-- check updates +PREPARE prepared_partition_parameter_update(int, int) AS + UPDATE prepare_table SET value = $2 WHERE key = $1; +-- execute 6 times to trigger prepared statement usage +EXECUTE prepared_partition_parameter_update(1, 11); +EXECUTE prepared_partition_parameter_update(2, 21); +EXECUTE prepared_partition_parameter_update(3, 31); +EXECUTE prepared_partition_parameter_update(4, 41); +EXECUTE prepared_partition_parameter_update(5, 51); +-- This fails with an unexpected error message +EXECUTE prepared_partition_parameter_update(5, 52); +ERROR: distributed modifications must target exactly one shard +PREPARE prepared_non_partition_parameter_update(int, int) AS + UPDATE prepare_table SET value = $2 WHERE key = 0 AND value = $1; +-- execute 6 times to trigger prepared statement usage +EXECUTE prepared_non_partition_parameter_update(10, 12); +EXECUTE prepared_non_partition_parameter_update(20, 22); +EXECUTE prepared_non_partition_parameter_update(30, 32); +EXECUTE prepared_non_partition_parameter_update(40, 42); +EXECUTE prepared_non_partition_parameter_update(50, 52); +EXECUTE prepared_non_partition_parameter_update(60, 62); +-- check after updates +SELECT * FROM prepare_table ORDER BY key, value; + key | value +-----+------- + 0 | 12 + 0 | 22 + 0 | 32 + 0 | 42 + 0 | 52 + 0 | 62 + 0 | + 0 | + 0 | + 0 | + 0 | + 0 | + 1 | 11 + 1 | 11 + 2 | 21 + 2 | 21 + 3 | 31 + 3 | 31 + 4 | 41 + 4 | 41 + 5 | 51 + 5 | 51 +(22 rows) + +-- check deletes +PREPARE prepared_partition_parameter_delete(int, int) AS + DELETE FROM prepare_table WHERE key = $1 AND value = $2; +EXECUTE prepared_partition_parameter_delete(1, 11); +EXECUTE prepared_partition_parameter_delete(2, 21); +EXECUTE prepared_partition_parameter_delete(3, 31); +EXECUTE prepared_partition_parameter_delete(4, 41); +EXECUTE prepared_partition_parameter_delete(5, 51); +-- This fails with an unexpected error message +EXECUTE prepared_partition_parameter_delete(0, 10); +ERROR: distributed modifications must target exactly one shard +PREPARE prepared_non_partition_parameter_delete(int) AS + DELETE FROM prepare_table WHERE key = 0 AND value = $1; +-- execute 6 times to trigger prepared statement usage +EXECUTE prepared_non_partition_parameter_delete(12); +EXECUTE prepared_non_partition_parameter_delete(22); +EXECUTE prepared_non_partition_parameter_delete(32); +EXECUTE prepared_non_partition_parameter_delete(42); +EXECUTE prepared_non_partition_parameter_delete(52); +EXECUTE prepared_non_partition_parameter_delete(62); +-- check after deletes +SELECT * FROM prepare_table ORDER BY key, value; + key | value +-----+------- + 0 | + 0 | + 0 | + 0 | + 0 | + 0 | +(6 rows) + -- clean-up prepared statements DEALLOCATE ALL; diff --git a/src/test/regress/expected/multi_sql_function.out b/src/test/regress/expected/multi_sql_function.out new file mode 100644 index 000000000..e6882798d --- /dev/null +++ b/src/test/regress/expected/multi_sql_function.out @@ -0,0 +1,330 @@ +-- +-- MULTI_SQL_FUNCTION +-- +ALTER SEQUENCE pg_catalog.pg_dist_shardid_seq RESTART 1230000; +ALTER SEQUENCE pg_catalog.pg_dist_jobid_seq RESTART 1230000; +CREATE FUNCTION sql_test_no_1() RETURNS bigint AS ' + SELECT + count(*) + FROM + orders; +' LANGUAGE SQL; +CREATE FUNCTION sql_test_no_2() RETURNS bigint AS ' + SELECT + count(*) + FROM + orders, lineitem + WHERE + o_orderkey = l_orderkey; +' LANGUAGE SQL; +CREATE FUNCTION sql_test_no_3() RETURNS bigint AS ' + SELECT + count(*) + FROM + orders, customer + WHERE + o_custkey = c_custkey; +' LANGUAGE SQL; +CREATE FUNCTION sql_test_no_4() RETURNS bigint AS ' + SELECT + count(*) + FROM + orders, customer, lineitem + WHERE + o_custkey = c_custkey AND + o_orderkey = l_orderkey; +' LANGUAGE SQL; +CREATE FUNCTION sql_test_no_6(integer) RETURNS bigint AS $$ + SELECT + count(*) + FROM + orders, lineitem + WHERE + o_orderkey = l_orderkey AND + l_suppkey > $1; +$$ LANGUAGE SQL RETURNS NULL ON NULL INPUT; +SET citus.task_executor_type TO 'task-tracker'; +SET client_min_messages TO INFO; +-- now, run plain SQL functions +SELECT sql_test_no_1(); + sql_test_no_1 +--------------- + 2984 +(1 row) + +SELECT sql_test_no_2(); + sql_test_no_2 +--------------- + 11998 +(1 row) + +SELECT sql_test_no_3(); + sql_test_no_3 +--------------- + 1955 +(1 row) + +SELECT sql_test_no_4(); + sql_test_no_4 +--------------- + 7804 +(1 row) + +-- run the tests which do not require re-partition +-- with real-time executor +SET citus.task_executor_type TO 'real-time'; +-- now, run plain SQL functions +SELECT sql_test_no_1(); + sql_test_no_1 +--------------- + 2984 +(1 row) + +SELECT sql_test_no_2(); + sql_test_no_2 +--------------- + 11998 +(1 row) + +-- plain SQL functions with parameters cannot be executed +-- FIXME: temporarily disabled, bad error message - waiting for proper +-- parametrized query support +-- SELECT sql_test_no_6(155); +-- test router executor parameterized sql functions +CREATE TABLE temp_table ( + key int, + value int +); +SELECT master_create_distributed_table('temp_table','key','hash'); + master_create_distributed_table +--------------------------------- + +(1 row) + +SELECT master_create_worker_shards('temp_table',4,1); + master_create_worker_shards +----------------------------- + +(1 row) + +CREATE FUNCTION no_parameter_insert_sql() RETURNS void AS $$ + INSERT INTO temp_table (key) VALUES (0); +$$ LANGUAGE SQL; +-- execute 6 times +SELECT no_parameter_insert_sql(); + no_parameter_insert_sql +------------------------- + +(1 row) + +SELECT no_parameter_insert_sql(); + no_parameter_insert_sql +------------------------- + +(1 row) + +SELECT no_parameter_insert_sql(); + no_parameter_insert_sql +------------------------- + +(1 row) + +SELECT no_parameter_insert_sql(); + no_parameter_insert_sql +------------------------- + +(1 row) + +SELECT no_parameter_insert_sql(); + no_parameter_insert_sql +------------------------- + +(1 row) + +SELECT no_parameter_insert_sql(); + no_parameter_insert_sql +------------------------- + +(1 row) + +CREATE FUNCTION non_partition_parameter_insert_sql(int) RETURNS void AS $$ + INSERT INTO temp_table (key, value) VALUES (0, $1); +$$ LANGUAGE SQL; +-- execute 6 times +SELECT non_partition_parameter_insert_sql(10); + non_partition_parameter_insert_sql +------------------------------------ + +(1 row) + +SELECT non_partition_parameter_insert_sql(20); + non_partition_parameter_insert_sql +------------------------------------ + +(1 row) + +SELECT non_partition_parameter_insert_sql(30); + non_partition_parameter_insert_sql +------------------------------------ + +(1 row) + +SELECT non_partition_parameter_insert_sql(40); + non_partition_parameter_insert_sql +------------------------------------ + +(1 row) + +SELECT non_partition_parameter_insert_sql(50); + non_partition_parameter_insert_sql +------------------------------------ + +(1 row) + +SELECT non_partition_parameter_insert_sql(60); + non_partition_parameter_insert_sql +------------------------------------ + +(1 row) + +-- check inserted values +SELECT * FROM temp_table ORDER BY key, value; + key | value +-----+------- + 0 | 10 + 0 | 20 + 0 | 30 + 0 | 40 + 0 | 50 + 0 | 60 + 0 | + 0 | + 0 | + 0 | + 0 | + 0 | +(12 rows) + +-- check updates +CREATE FUNCTION non_partition_parameter_update_sql(int, int) RETURNS void AS $$ + UPDATE temp_table SET value = $2 WHERE key = 0 AND value = $1; +$$ LANGUAGE SQL; +-- execute 6 times +SELECT non_partition_parameter_update_sql(10, 12); + non_partition_parameter_update_sql +------------------------------------ + +(1 row) + +SELECT non_partition_parameter_update_sql(20, 22); + non_partition_parameter_update_sql +------------------------------------ + +(1 row) + +SELECT non_partition_parameter_update_sql(30, 32); + non_partition_parameter_update_sql +------------------------------------ + +(1 row) + +SELECT non_partition_parameter_update_sql(40, 42); + non_partition_parameter_update_sql +------------------------------------ + +(1 row) + +SELECT non_partition_parameter_update_sql(50, 52); + non_partition_parameter_update_sql +------------------------------------ + +(1 row) + +SELECT non_partition_parameter_update_sql(60, 62); + non_partition_parameter_update_sql +------------------------------------ + +(1 row) + +-- check after updates +SELECT * FROM temp_table ORDER BY key, value; + key | value +-----+------- + 0 | 12 + 0 | 22 + 0 | 32 + 0 | 42 + 0 | 52 + 0 | 62 + 0 | + 0 | + 0 | + 0 | + 0 | + 0 | +(12 rows) + +-- check deletes +CREATE FUNCTION non_partition_parameter_delete_sql(int) RETURNS void AS $$ + DELETE FROM prepare_table WHERE key = 0 AND value = $1; +$$ LANGUAGE SQL; +-- execute 6 times to trigger prepared statement usage +SELECT non_partition_parameter_delete_sql(12); + non_partition_parameter_delete_sql +------------------------------------ + +(1 row) + +SELECT non_partition_parameter_delete_sql(22); + non_partition_parameter_delete_sql +------------------------------------ + +(1 row) + +SELECT non_partition_parameter_delete_sql(32); + non_partition_parameter_delete_sql +------------------------------------ + +(1 row) + +SELECT non_partition_parameter_delete_sql(42); + non_partition_parameter_delete_sql +------------------------------------ + +(1 row) + +SELECT non_partition_parameter_delete_sql(52); + non_partition_parameter_delete_sql +------------------------------------ + +(1 row) + +SELECT non_partition_parameter_delete_sql(62); + non_partition_parameter_delete_sql +------------------------------------ + +(1 row) + +-- check after deletes +SELECT * FROM prepare_table ORDER BY key, value; + key | value +-----+------- + 0 | + 0 | + 0 | + 0 | + 0 | + 0 | +(6 rows) + +DROP TABLE temp_table; +-- clean-up functions +DROP FUNCTION sql_test_no_1(); +DROP FUNCTION sql_test_no_2(); +DROP FUNCTION sql_test_no_3(); +DROP FUNCTION sql_test_no_4(); +DROP FUNCTION sql_test_no_6(int); +DROP FUNCTION no_parameter_insert_sql(); +DROP FUNCTION non_partition_parameter_insert_sql(int); +DROP FUNCTION non_partition_parameter_update_sql(int, int); +DROP FUNCTION non_partition_parameter_delete_sql(int); diff --git a/src/test/regress/multi_schedule b/src/test/regress/multi_schedule index 0bcc143ad..5881b4792 100644 --- a/src/test/regress/multi_schedule +++ b/src/test/regress/multi_schedule @@ -49,6 +49,7 @@ test: multi_utility_statements test: multi_dropped_column_aliases test: multi_binary_master_copy_format test: multi_prepare_sql multi_prepare_plsql +test: multi_sql_function # ---------- # Parallel TPC-H tests to check our distributed execution behavior diff --git a/src/test/regress/sql/multi_prepare_plsql.sql b/src/test/regress/sql/multi_prepare_plsql.sql index 8b9673fe1..b7ee32d6e 100644 --- a/src/test/regress/sql/multi_prepare_plsql.sql +++ b/src/test/regress/sql/multi_prepare_plsql.sql @@ -11,52 +11,7 @@ ALTER SEQUENCE pg_catalog.pg_dist_shardid_seq RESTART 780000; ALTER SEQUENCE pg_catalog.pg_dist_jobid_seq RESTART 780000; -CREATE FUNCTION sql_test_no_1() RETURNS bigint AS ' - SELECT - count(*) - FROM - orders; -' LANGUAGE SQL; - -CREATE FUNCTION sql_test_no_2() RETURNS bigint AS ' - SELECT - count(*) - FROM - orders, lineitem - WHERE - o_orderkey = l_orderkey; -' LANGUAGE SQL; - -CREATE FUNCTION sql_test_no_3() RETURNS bigint AS ' - SELECT - count(*) - FROM - orders, customer - WHERE - o_custkey = c_custkey; -' LANGUAGE SQL; - -CREATE FUNCTION sql_test_no_4() RETURNS bigint AS ' - SELECT - count(*) - FROM - orders, customer, lineitem - WHERE - o_custkey = c_custkey AND - o_orderkey = l_orderkey; -' LANGUAGE SQL; - -CREATE OR REPLACE FUNCTION sql_test_no_6(integer) RETURNS bigint AS $$ - SELECT - count(*) - FROM - orders, lineitem - WHERE - o_orderkey = l_orderkey AND - l_suppkey > $1; -$$ LANGUAGE SQL RETURNS NULL ON NULL INPUT; - -CREATE OR REPLACE FUNCTION plpgsql_test_1() RETURNS TABLE(count bigint) AS $$ +CREATE FUNCTION plpgsql_test_1() RETURNS TABLE(count bigint) AS $$ DECLARE BEGIN RETURN QUERY @@ -68,7 +23,7 @@ BEGIN END; $$ LANGUAGE plpgsql; -CREATE OR REPLACE FUNCTION plpgsql_test_2() RETURNS TABLE(count bigint) AS $$ +CREATE FUNCTION plpgsql_test_2() RETURNS TABLE(count bigint) AS $$ DECLARE BEGIN RETURN QUERY @@ -82,7 +37,7 @@ BEGIN END; $$ LANGUAGE plpgsql; -CREATE OR REPLACE FUNCTION plpgsql_test_3() RETURNS TABLE(count bigint) AS $$ +CREATE FUNCTION plpgsql_test_3() RETURNS TABLE(count bigint) AS $$ DECLARE BEGIN RETURN QUERY @@ -96,7 +51,7 @@ BEGIN END; $$ LANGUAGE plpgsql; -CREATE OR REPLACE FUNCTION plpgsql_test_4() RETURNS TABLE(count bigint) AS $$ +CREATE FUNCTION plpgsql_test_4() RETURNS TABLE(count bigint) AS $$ DECLARE BEGIN RETURN QUERY @@ -110,7 +65,7 @@ BEGIN END; $$ LANGUAGE plpgsql; -CREATE OR REPLACE FUNCTION plpgsql_test_5() RETURNS TABLE(count bigint) AS $$ +CREATE FUNCTION plpgsql_test_5() RETURNS TABLE(count bigint) AS $$ DECLARE BEGIN RETURN QUERY @@ -123,7 +78,7 @@ BEGIN END; $$ LANGUAGE plpgsql; -CREATE OR REPLACE FUNCTION plpgsql_test_6(int) RETURNS TABLE(count bigint) AS $$ +CREATE FUNCTION plpgsql_test_6(int) RETURNS TABLE(count bigint) AS $$ DECLARE BEGIN RETURN QUERY @@ -137,7 +92,7 @@ BEGIN END; $$ LANGUAGE plpgsql; -CREATE OR REPLACE FUNCTION plpgsql_test_7(text, text) RETURNS TABLE(supp_natadsion text, cusasdt_nation text, l_yeasdar int, sasdaum double precision) AS $$ +CREATE FUNCTION plpgsql_test_7(text, text) RETURNS TABLE(supp_natadsion text, cusasdt_nation text, l_yeasdar int, sasdaum double precision) AS $$ DECLARE BEGIN RETURN QUERY @@ -195,12 +150,6 @@ $$ LANGUAGE plpgsql; SET citus.task_executor_type TO 'task-tracker'; SET client_min_messages TO INFO; --- now, run plain SQL functions -SELECT sql_test_no_1(); -SELECT sql_test_no_2(); -SELECT sql_test_no_3(); -SELECT sql_test_no_4(); - -- now, run PL/pgsql functions SELECT plpgsql_test_1(); SELECT plpgsql_test_2(); @@ -229,15 +178,6 @@ SELECT plpgsql_test_2(); -- with real-time executor SET citus.task_executor_type TO 'real-time'; --- now, run plain SQL functions -SELECT sql_test_no_1(); -SELECT sql_test_no_2(); - --- plain SQL functions with parameters cannot be executed --- FIXME: temporarily disabled, bad error message - waiting for proper parametrized query --- FIXME: support --- SELECT sql_test_no_6(155); - -- now, run PL/pgsql functions SELECT plpgsql_test_1(); SELECT plpgsql_test_2(); @@ -248,16 +188,16 @@ SELECT plpgsql_test_2(); -- SELECT plpgsql_test_6(1555); -- test router executor parameterized PL/pgsql functions -CREATE TABLE temp_table ( +CREATE TABLE plpgsql_table ( key int, value int ); -SELECT master_create_distributed_table('temp_table','key','hash'); -SELECT master_create_worker_shards('temp_table',4,1); +SELECT master_create_distributed_table('plpgsql_table','key','hash'); +SELECT master_create_worker_shards('plpgsql_table',4,1); -CREATE OR REPLACE FUNCTION no_parameter_insert() RETURNS void as $$ +CREATE FUNCTION no_parameter_insert() RETURNS void as $$ BEGIN - INSERT INTO temp_table (key) VALUES (0); + INSERT INTO plpgsql_table (key) VALUES (0); END; $$ LANGUAGE plpgsql; @@ -269,9 +209,10 @@ SELECT no_parameter_insert(); SELECT no_parameter_insert(); SELECT no_parameter_insert(); -CREATE OR REPLACE FUNCTION single_parameter_insert(key_arg int) RETURNS void as $$ +CREATE FUNCTION single_parameter_insert(key_arg int) + RETURNS void as $$ BEGIN - INSERT INTO temp_table (key) VALUES (key_arg); + INSERT INTO plpgsql_table (key) VALUES (key_arg); END; $$ LANGUAGE plpgsql; @@ -283,9 +224,10 @@ SELECT single_parameter_insert(4); SELECT single_parameter_insert(5); SELECT single_parameter_insert(6); -CREATE OR REPLACE FUNCTION double_parameter_insert(key_arg int, value_arg int) RETURNS void as $$ +CREATE FUNCTION double_parameter_insert(key_arg int, value_arg int) + RETURNS void as $$ BEGIN - INSERT INTO temp_table (key, value) VALUES (key_arg, value_arg); + INSERT INTO plpgsql_table (key, value) VALUES (key_arg, value_arg); END; $$ LANGUAGE plpgsql; @@ -297,71 +239,265 @@ SELECT double_parameter_insert(4, 40); SELECT double_parameter_insert(5, 50); SELECT double_parameter_insert(6, 60); +CREATE FUNCTION non_partition_parameter_insert(value_arg int) + RETURNS void as $$ +BEGIN + INSERT INTO plpgsql_table (key, value) VALUES (0, value_arg); +END; +$$ LANGUAGE plpgsql; + +-- execute 6 times to trigger prepared statement usage +SELECT non_partition_parameter_insert(10); +SELECT non_partition_parameter_insert(20); +SELECT non_partition_parameter_insert(30); +SELECT non_partition_parameter_insert(40); +SELECT non_partition_parameter_insert(50); +SELECT non_partition_parameter_insert(60); + -- check inserted values -SELECT * FROM temp_table ORDER BY key, value; +SELECT * FROM plpgsql_table ORDER BY key, value; -- check router executor select -CREATE OR REPLACE FUNCTION partition_column_select(key_arg int) RETURNS TABLE(key int, value int) AS $$ +CREATE FUNCTION router_partition_column_select(key_arg int) + RETURNS TABLE(key int, value int) AS $$ DECLARE BEGIN RETURN QUERY SELECT - temp_table.key, - temp_table.value + plpgsql_table.key, + plpgsql_table.value FROM - temp_table + plpgsql_table WHERE - temp_table.key = key_arg + plpgsql_table.key = key_arg ORDER BY key, value; END; $$ LANGUAGE plpgsql; -SELECT partition_column_select(1); -SELECT partition_column_select(2); -SELECT partition_column_select(3); -SELECT partition_column_select(4); -SELECT partition_column_select(5); +SELECT router_partition_column_select(1); +SELECT router_partition_column_select(2); +SELECT router_partition_column_select(3); +SELECT router_partition_column_select(4); +SELECT router_partition_column_select(5); --- 6th execution is failing. We don't want to run the failing test because of --- changing output. After implementing this feature, uncomment this. --- SELECT partition_column_select(6); +-- FIXME: 6th execution is failing. We don't want to run the failing test +-- because of changing output. After implementing this feature, uncomment this. +-- SELECT router_partition_column_select(6); + +CREATE FUNCTION router_non_partition_column_select(value_arg int) + RETURNS TABLE(key int, value int) AS $$ +DECLARE +BEGIN + RETURN QUERY + SELECT + plpgsql_table.key, + plpgsql_table.value + FROM + plpgsql_table + WHERE + plpgsql_table.key = 0 AND + plpgsql_table.value = value_arg + ORDER BY + key, + value; +END; +$$ LANGUAGE plpgsql; + +SELECT router_non_partition_column_select(10); +SELECT router_non_partition_column_select(20); +SELECT router_non_partition_column_select(30); +SELECT router_non_partition_column_select(40); +SELECT router_non_partition_column_select(50); +SELECT router_non_partition_column_select(60); -- check real-time executor -CREATE OR REPLACE FUNCTION non_partition_column_select(value_arg int) RETURNS TABLE(key int, value int) AS $$ +CREATE FUNCTION real_time_non_partition_column_select(value_arg int) + RETURNS TABLE(key int, value int) AS $$ DECLARE BEGIN RETURN QUERY SELECT - temp_table.key, - temp_table.value + plpgsql_table.key, + plpgsql_table.value FROM - temp_table + plpgsql_table WHERE - temp_table.value = value_arg + plpgsql_table.value = value_arg ORDER BY key, value; END; $$ LANGUAGE plpgsql; -SELECT non_partition_column_select(10); -SELECT non_partition_column_select(20); -SELECT non_partition_column_select(30); -SELECT non_partition_column_select(40); -SELECT non_partition_column_select(50); +SELECT real_time_non_partition_column_select(10); +SELECT real_time_non_partition_column_select(20); +SELECT real_time_non_partition_column_select(30); +SELECT real_time_non_partition_column_select(40); +SELECT real_time_non_partition_column_select(50); --- 6th execution is failing. We don't want to run the failing test because of --- changing output. After implementing this feature, uncomment this. --- SELECT partition_column_select(6); +-- FIXME: 6th execution is failing. We don't want to run the failing test +-- because of changing output. After implementing this feature, uncomment this. +-- SELECT real_time_non_partition_column_select(60); + +CREATE FUNCTION real_time_partition_column_select(key_arg int) + RETURNS TABLE(key int, value int) AS $$ +DECLARE +BEGIN + RETURN QUERY + SELECT + plpgsql_table.key, + plpgsql_table.value + FROM + plpgsql_table + WHERE + plpgsql_table.key = key_arg OR + plpgsql_table.value = 10 + ORDER BY + key, + value; +END; +$$ LANGUAGE plpgsql; + +SELECT real_time_partition_column_select(1); +SELECT real_time_partition_column_select(2); +SELECT real_time_partition_column_select(3); +SELECT real_time_partition_column_select(4); +SELECT real_time_partition_column_select(5); + +-- FIXME: 6th execution is failing. We don't want to run the failing test +-- because of changing output. After implementing this feature, uncomment this. +-- SELECT real_time_partition_column_select(6); + +-- check task-tracker executor +SET citus.task_executor_type TO 'task-tracker'; + +CREATE FUNCTION task_tracker_non_partition_column_select(value_arg int) + RETURNS TABLE(key int, value int) AS $$ +DECLARE +BEGIN + RETURN QUERY + SELECT + plpgsql_table.key, + plpgsql_table.value + FROM + plpgsql_table + WHERE + plpgsql_table.value = value_arg + ORDER BY + key, + value; +END; +$$ LANGUAGE plpgsql; + +SELECT task_tracker_non_partition_column_select(10); +SELECT task_tracker_non_partition_column_select(20); +SELECT task_tracker_non_partition_column_select(30); +SELECT task_tracker_non_partition_column_select(40); +SELECT task_tracker_non_partition_column_select(50); + +-- FIXME: 6th execution is failing. We don't want to run the failing test +-- because of changing output. After implementing this feature, uncomment this. +-- SELECT real_time_non_partition_column_select(60); + +CREATE FUNCTION task_tracker_partition_column_select(key_arg int) + RETURNS TABLE(key int, value int) AS $$ +DECLARE +BEGIN + RETURN QUERY + SELECT + plpgsql_table.key, + plpgsql_table.value + FROM + plpgsql_table + WHERE + plpgsql_table.key = key_arg OR + plpgsql_table.value = 10 + ORDER BY + key, + value; +END; +$$ LANGUAGE plpgsql; + +SELECT task_tracker_partition_column_select(1); +SELECT task_tracker_partition_column_select(2); +SELECT task_tracker_partition_column_select(3); +SELECT task_tracker_partition_column_select(4); +SELECT task_tracker_partition_column_select(5); + +-- FIXME: 6th execution is failing. We don't want to run the failing test +-- because of changing output. After implementing this feature, uncomment this. +-- SELECT task_tracker_partition_column_select(6); + +SET citus.task_executor_type TO 'real-time'; + +-- check updates +CREATE FUNCTION partition_parameter_update(int, int) RETURNS void as $$ +BEGIN + UPDATE plpgsql_table SET value = $2 WHERE key = $1; +END; +$$ LANGUAGE plpgsql; + +-- execute 6 times to trigger prepared statement usage +SELECT partition_parameter_update(1, 11); +SELECT partition_parameter_update(2, 21); +SELECT partition_parameter_update(3, 31); +SELECT partition_parameter_update(4, 41); +SELECT partition_parameter_update(5, 51); +-- This fails with an unexpected error message +SELECT partition_parameter_update(5, 52); + +CREATE FUNCTION non_partition_parameter_update(int, int) RETURNS void as $$ +BEGIN + UPDATE plpgsql_table SET value = $2 WHERE key = 0 AND value = $1; +END; +$$ LANGUAGE plpgsql; + +-- execute 6 times to trigger prepared statement usage +SELECT non_partition_parameter_update(10, 12); +SELECT non_partition_parameter_update(20, 22); +SELECT non_partition_parameter_update(30, 32); +SELECT non_partition_parameter_update(40, 42); +SELECT non_partition_parameter_update(50, 52); +SELECT non_partition_parameter_update(60, 62); + +-- check table after updates +SELECT * FROM plpgsql_table ORDER BY key, value; + +-- check deletes +CREATE FUNCTION partition_parameter_delete(int, int) RETURNS void as $$ +BEGIN + DELETE FROM plpgsql_table WHERE key = $1 AND value = $2; +END; +$$ LANGUAGE plpgsql; + +SELECT partition_parameter_delete(1, 11); +SELECT partition_parameter_delete(2, 21); +SELECT partition_parameter_delete(3, 31); +SELECT partition_parameter_delete(4, 41); +SELECT partition_parameter_delete(5, 51); +-- This fails with an unexpected error message +SELECT partition_parameter_delete(0, 10); + +CREATE FUNCTION non_partition_parameter_delete(int) RETURNS void as $$ +BEGIN + DELETE FROM plpgsql_table WHERE key = 0 AND value = $1; +END; +$$ LANGUAGE plpgsql; + +-- execute 6 times to trigger prepared statement usage +SELECT non_partition_parameter_delete(12); +SELECT non_partition_parameter_delete(22); +SELECT non_partition_parameter_delete(32); +SELECT non_partition_parameter_delete(42); +SELECT non_partition_parameter_delete(52); +SELECT non_partition_parameter_delete(62); + +-- check table after deletes +SELECT * FROM plpgsql_table ORDER BY key, value; -- clean-up functions -DROP FUNCTION sql_test_no_1(); -DROP FUNCTION sql_test_no_2(); -DROP FUNCTION sql_test_no_3(); -DROP FUNCTION sql_test_no_4(); -DROP FUNCTION sql_test_no_6(int); DROP FUNCTION plpgsql_test_1(); DROP FUNCTION plpgsql_test_2(); DROP FUNCTION plpgsql_test_3(); @@ -372,5 +508,14 @@ DROP FUNCTION plpgsql_test_7(text, text); DROP FUNCTION no_parameter_insert(); DROP FUNCTION single_parameter_insert(int); DROP FUNCTION double_parameter_insert(int, int); -DROP FUNCTION partition_column_select(int); -DROP FUNCTION non_partition_column_select(int); +DROP FUNCTION non_partition_parameter_insert(int); +DROP FUNCTION router_partition_column_select(int); +DROP FUNCTION router_non_partition_column_select(int); +DROP FUNCTION real_time_non_partition_column_select(int); +DROP FUNCTION real_time_partition_column_select(int); +DROP FUNCTION task_tracker_non_partition_column_select(int); +DROP FUNCTION task_tracker_partition_column_select(int); +DROP FUNCTION partition_parameter_update(int, int); +DROP FUNCTION non_partition_parameter_update(int, int); +DROP FUNCTION partition_parameter_delete(int, int); +DROP FUNCTION non_partition_parameter_delete(int); diff --git a/src/test/regress/sql/multi_prepare_sql.sql b/src/test/regress/sql/multi_prepare_sql.sql index 1fd889c89..5c467921c 100644 --- a/src/test/regress/sql/multi_prepare_sql.sql +++ b/src/test/regress/sql/multi_prepare_sql.sql @@ -209,5 +209,252 @@ EXECUTE prepared_partition_column_insert(6); DROP TYPE test_composite_type CASCADE; +-- test router executor with prepare statements +CREATE TABLE prepare_table ( + key int, + value int +); +SELECT master_create_distributed_table('prepare_table','key','hash'); +SELECT master_create_worker_shards('prepare_table',4,1); + +PREPARE prepared_no_parameter_insert AS + INSERT INTO prepare_table (key) VALUES (0); + +-- execute 6 times to trigger prepared statement usage +EXECUTE prepared_no_parameter_insert; +EXECUTE prepared_no_parameter_insert; +EXECUTE prepared_no_parameter_insert; +EXECUTE prepared_no_parameter_insert; +EXECUTE prepared_no_parameter_insert; +EXECUTE prepared_no_parameter_insert; + +PREPARE prepared_single_parameter_insert(int) AS + INSERT INTO prepare_table (key) VALUES ($1); + +-- execute 6 times to trigger prepared statement usage +EXECUTE prepared_single_parameter_insert(1); +EXECUTE prepared_single_parameter_insert(2); +EXECUTE prepared_single_parameter_insert(3); +EXECUTE prepared_single_parameter_insert(4); +EXECUTE prepared_single_parameter_insert(5); +EXECUTE prepared_single_parameter_insert(6); + +PREPARE prepared_double_parameter_insert(int, int) AS + INSERT INTO prepare_table (key, value) VALUES ($1, $2); + +-- execute 6 times to trigger prepared statement usage +EXECUTE prepared_double_parameter_insert(1, 10); +EXECUTE prepared_double_parameter_insert(2, 20); +EXECUTE prepared_double_parameter_insert(3, 30); +EXECUTE prepared_double_parameter_insert(4, 40); +EXECUTE prepared_double_parameter_insert(5, 50); +EXECUTE prepared_double_parameter_insert(6, 60); + +PREPARE prepared_non_partition_parameter_insert(int) AS + INSERT INTO prepare_table (key, value) VALUES (0, $1); + +-- execute 6 times to trigger prepared statement usage +EXECUTE prepared_non_partition_parameter_insert(10); +EXECUTE prepared_non_partition_parameter_insert(20); +EXECUTE prepared_non_partition_parameter_insert(30); +EXECUTE prepared_non_partition_parameter_insert(40); +EXECUTE prepared_non_partition_parameter_insert(50); +EXECUTE prepared_non_partition_parameter_insert(60); + +-- check inserted values +SELECT * FROM prepare_table ORDER BY key, value; + +-- check router executor select +PREPARE prepared_router_partition_column_select(int) AS + SELECT + prepare_table.key, + prepare_table.value + FROM + prepare_table + WHERE + prepare_table.key = $1 + ORDER BY + key, + value; + +EXECUTE prepared_router_partition_column_select(1); +EXECUTE prepared_router_partition_column_select(2); +EXECUTE prepared_router_partition_column_select(3); +EXECUTE prepared_router_partition_column_select(4); +EXECUTE prepared_router_partition_column_select(5); + +-- FIXME: 6th execution is failing. We don't want to run the failing test +-- because of changing output. After implementing this feature, uncomment this. +-- EXECUTE prepared_router_partition_column_select(6); + +PREPARE prepared_router_non_partition_column_select(int) AS + SELECT + prepare_table.key, + prepare_table.value + FROM + prepare_table + WHERE + prepare_table.key = 0 AND + prepare_table.value = $1 + ORDER BY + key, + value; + +EXECUTE prepared_router_non_partition_column_select(10); +EXECUTE prepared_router_non_partition_column_select(20); +EXECUTE prepared_router_non_partition_column_select(30); +EXECUTE prepared_router_non_partition_column_select(40); +EXECUTE prepared_router_non_partition_column_select(50); +EXECUTE prepared_router_non_partition_column_select(60); + +-- check real-time executor +PREPARE prepared_real_time_non_partition_column_select(int) AS + SELECT + prepare_table.key, + prepare_table.value + FROM + prepare_table + WHERE + prepare_table.value = $1 + ORDER BY + key, + value; + +EXECUTE prepared_real_time_non_partition_column_select(10); +EXECUTE prepared_real_time_non_partition_column_select(20); +EXECUTE prepared_real_time_non_partition_column_select(30); +EXECUTE prepared_real_time_non_partition_column_select(40); +EXECUTE prepared_real_time_non_partition_column_select(50); + +-- FIXME: 6th execution is failing. We don't want to run the failing test +-- because of changing output. After implementing this feature, uncomment this. +-- EXECUTE prepared_real_time_non_partition_column_select(60); + +PREPARE prepared_real_time_partition_column_select(int) AS + SELECT + prepare_table.key, + prepare_table.value + FROM + prepare_table + WHERE + prepare_table.key = $1 OR + prepare_table.value = 10 + ORDER BY + key, + value; + +EXECUTE prepared_real_time_partition_column_select(1); +EXECUTE prepared_real_time_partition_column_select(2); +EXECUTE prepared_real_time_partition_column_select(3); +EXECUTE prepared_real_time_partition_column_select(4); +EXECUTE prepared_real_time_partition_column_select(5); + +-- FIXME: 6th execution is failing. We don't want to run the failing test +-- because of changing output. After implementing this feature, uncomment this. +-- EXECUTE prepared_real_time_partition_column_select(6); + +-- check task-tracker executor +SET citus.task_executor_type TO 'task-tracker'; + +PREPARE prepared_task_tracker_non_partition_column_select(int) AS + SELECT + prepare_table.key, + prepare_table.value + FROM + prepare_table + WHERE + prepare_table.value = $1 + ORDER BY + key, + value; + +EXECUTE prepared_task_tracker_non_partition_column_select(10); +EXECUTE prepared_task_tracker_non_partition_column_select(20); +EXECUTE prepared_task_tracker_non_partition_column_select(30); +EXECUTE prepared_task_tracker_non_partition_column_select(40); +EXECUTE prepared_task_tracker_non_partition_column_select(50); + +-- FIXME: 6th execution is failing. We don't want to run the failing test +-- because of changing output. After implementing this feature, uncomment this. +-- EXECUTE prepared_task_tracker_non_partition_column_select(60); + +PREPARE prepared_task_tracker_partition_column_select(int) AS + SELECT + prepare_table.key, + prepare_table.value + FROM + prepare_table + WHERE + prepare_table.key = $1 OR + prepare_table.value = 10 + ORDER BY + key, + value; + +EXECUTE prepared_task_tracker_partition_column_select(1); +EXECUTE prepared_task_tracker_partition_column_select(2); +EXECUTE prepared_task_tracker_partition_column_select(3); +EXECUTE prepared_task_tracker_partition_column_select(4); +EXECUTE prepared_task_tracker_partition_column_select(5); + +-- FIXME: 6th execution is failing. We don't want to run the failing test +-- because of changing output. After implementing this feature, uncomment this. +-- EXECUTE prepared_task_tracker_partition_column_select(6); + +SET citus.task_executor_type TO 'real-time'; + +-- check updates +PREPARE prepared_partition_parameter_update(int, int) AS + UPDATE prepare_table SET value = $2 WHERE key = $1; + +-- execute 6 times to trigger prepared statement usage +EXECUTE prepared_partition_parameter_update(1, 11); +EXECUTE prepared_partition_parameter_update(2, 21); +EXECUTE prepared_partition_parameter_update(3, 31); +EXECUTE prepared_partition_parameter_update(4, 41); +EXECUTE prepared_partition_parameter_update(5, 51); +-- This fails with an unexpected error message +EXECUTE prepared_partition_parameter_update(5, 52); + +PREPARE prepared_non_partition_parameter_update(int, int) AS + UPDATE prepare_table SET value = $2 WHERE key = 0 AND value = $1; + +-- execute 6 times to trigger prepared statement usage +EXECUTE prepared_non_partition_parameter_update(10, 12); +EXECUTE prepared_non_partition_parameter_update(20, 22); +EXECUTE prepared_non_partition_parameter_update(30, 32); +EXECUTE prepared_non_partition_parameter_update(40, 42); +EXECUTE prepared_non_partition_parameter_update(50, 52); +EXECUTE prepared_non_partition_parameter_update(60, 62); + +-- check after updates +SELECT * FROM prepare_table ORDER BY key, value; + +-- check deletes +PREPARE prepared_partition_parameter_delete(int, int) AS + DELETE FROM prepare_table WHERE key = $1 AND value = $2; + +EXECUTE prepared_partition_parameter_delete(1, 11); +EXECUTE prepared_partition_parameter_delete(2, 21); +EXECUTE prepared_partition_parameter_delete(3, 31); +EXECUTE prepared_partition_parameter_delete(4, 41); +EXECUTE prepared_partition_parameter_delete(5, 51); +-- This fails with an unexpected error message +EXECUTE prepared_partition_parameter_delete(0, 10); + +PREPARE prepared_non_partition_parameter_delete(int) AS + DELETE FROM prepare_table WHERE key = 0 AND value = $1; + +-- execute 6 times to trigger prepared statement usage +EXECUTE prepared_non_partition_parameter_delete(12); +EXECUTE prepared_non_partition_parameter_delete(22); +EXECUTE prepared_non_partition_parameter_delete(32); +EXECUTE prepared_non_partition_parameter_delete(42); +EXECUTE prepared_non_partition_parameter_delete(52); +EXECUTE prepared_non_partition_parameter_delete(62); + +-- check after deletes +SELECT * FROM prepare_table ORDER BY key, value; + -- clean-up prepared statements DEALLOCATE ALL; diff --git a/src/test/regress/sql/multi_sql_function.sql b/src/test/regress/sql/multi_sql_function.sql new file mode 100644 index 000000000..a5e2579d3 --- /dev/null +++ b/src/test/regress/sql/multi_sql_function.sql @@ -0,0 +1,154 @@ +-- +-- MULTI_SQL_FUNCTION +-- + +ALTER SEQUENCE pg_catalog.pg_dist_shardid_seq RESTART 1230000; +ALTER SEQUENCE pg_catalog.pg_dist_jobid_seq RESTART 1230000; + + +CREATE FUNCTION sql_test_no_1() RETURNS bigint AS ' + SELECT + count(*) + FROM + orders; +' LANGUAGE SQL; + +CREATE FUNCTION sql_test_no_2() RETURNS bigint AS ' + SELECT + count(*) + FROM + orders, lineitem + WHERE + o_orderkey = l_orderkey; +' LANGUAGE SQL; + +CREATE FUNCTION sql_test_no_3() RETURNS bigint AS ' + SELECT + count(*) + FROM + orders, customer + WHERE + o_custkey = c_custkey; +' LANGUAGE SQL; + +CREATE FUNCTION sql_test_no_4() RETURNS bigint AS ' + SELECT + count(*) + FROM + orders, customer, lineitem + WHERE + o_custkey = c_custkey AND + o_orderkey = l_orderkey; +' LANGUAGE SQL; + +CREATE FUNCTION sql_test_no_6(integer) RETURNS bigint AS $$ + SELECT + count(*) + FROM + orders, lineitem + WHERE + o_orderkey = l_orderkey AND + l_suppkey > $1; +$$ LANGUAGE SQL RETURNS NULL ON NULL INPUT; + +SET citus.task_executor_type TO 'task-tracker'; +SET client_min_messages TO INFO; + +-- now, run plain SQL functions +SELECT sql_test_no_1(); +SELECT sql_test_no_2(); +SELECT sql_test_no_3(); +SELECT sql_test_no_4(); + +-- run the tests which do not require re-partition +-- with real-time executor +SET citus.task_executor_type TO 'real-time'; + +-- now, run plain SQL functions +SELECT sql_test_no_1(); +SELECT sql_test_no_2(); + +-- plain SQL functions with parameters cannot be executed +-- FIXME: temporarily disabled, bad error message - waiting for proper +-- parametrized query support +-- SELECT sql_test_no_6(155); + +-- test router executor parameterized sql functions +CREATE TABLE temp_table ( + key int, + value int +); +SELECT master_create_distributed_table('temp_table','key','hash'); +SELECT master_create_worker_shards('temp_table',4,1); + +CREATE FUNCTION no_parameter_insert_sql() RETURNS void AS $$ + INSERT INTO temp_table (key) VALUES (0); +$$ LANGUAGE SQL; + +-- execute 6 times +SELECT no_parameter_insert_sql(); +SELECT no_parameter_insert_sql(); +SELECT no_parameter_insert_sql(); +SELECT no_parameter_insert_sql(); +SELECT no_parameter_insert_sql(); +SELECT no_parameter_insert_sql(); + +CREATE FUNCTION non_partition_parameter_insert_sql(int) RETURNS void AS $$ + INSERT INTO temp_table (key, value) VALUES (0, $1); +$$ LANGUAGE SQL; + +-- execute 6 times +SELECT non_partition_parameter_insert_sql(10); +SELECT non_partition_parameter_insert_sql(20); +SELECT non_partition_parameter_insert_sql(30); +SELECT non_partition_parameter_insert_sql(40); +SELECT non_partition_parameter_insert_sql(50); +SELECT non_partition_parameter_insert_sql(60); + +-- check inserted values +SELECT * FROM temp_table ORDER BY key, value; + +-- check updates +CREATE FUNCTION non_partition_parameter_update_sql(int, int) RETURNS void AS $$ + UPDATE temp_table SET value = $2 WHERE key = 0 AND value = $1; +$$ LANGUAGE SQL; + +-- execute 6 times +SELECT non_partition_parameter_update_sql(10, 12); +SELECT non_partition_parameter_update_sql(20, 22); +SELECT non_partition_parameter_update_sql(30, 32); +SELECT non_partition_parameter_update_sql(40, 42); +SELECT non_partition_parameter_update_sql(50, 52); +SELECT non_partition_parameter_update_sql(60, 62); + +-- check after updates +SELECT * FROM temp_table ORDER BY key, value; + +-- check deletes +CREATE FUNCTION non_partition_parameter_delete_sql(int) RETURNS void AS $$ + DELETE FROM prepare_table WHERE key = 0 AND value = $1; +$$ LANGUAGE SQL; + +-- execute 6 times to trigger prepared statement usage +SELECT non_partition_parameter_delete_sql(12); +SELECT non_partition_parameter_delete_sql(22); +SELECT non_partition_parameter_delete_sql(32); +SELECT non_partition_parameter_delete_sql(42); +SELECT non_partition_parameter_delete_sql(52); +SELECT non_partition_parameter_delete_sql(62); + +-- check after deletes +SELECT * FROM prepare_table ORDER BY key, value; + +DROP TABLE temp_table; + +-- clean-up functions +DROP FUNCTION sql_test_no_1(); +DROP FUNCTION sql_test_no_2(); +DROP FUNCTION sql_test_no_3(); +DROP FUNCTION sql_test_no_4(); +DROP FUNCTION sql_test_no_6(int); +DROP FUNCTION no_parameter_insert_sql(); +DROP FUNCTION non_partition_parameter_insert_sql(int); +DROP FUNCTION non_partition_parameter_update_sql(int, int); +DROP FUNCTION non_partition_parameter_delete_sql(int);