-- -- MULTI_SQL_FUNCTION -- SET citus.next_shard_id TO 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; 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 --------------- 2985 (1 row) SELECT sql_test_no_2(); sql_test_no_2 --------------- 12000 (1 row) SELECT sql_test_no_3(); sql_test_no_3 --------------- 1956 (1 row) SELECT sql_test_no_4(); sql_test_no_4 --------------- 7806 (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 --------------- 2985 (1 row) SELECT sql_test_no_2(); sql_test_no_2 --------------- 12000 (1 row) -- test router executor parameterized sql functions CREATE TABLE temp_table ( key int, value int ); SET citus.shard_replication_factor TO 1; SELECT create_distributed_table('temp_table','key','hash'); create_distributed_table -------------------------- (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 temp_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 temp_table ORDER BY key, value; key | value -----+------- 0 | 0 | 0 | 0 | 0 | 0 | (6 rows) -- test running parameterized SQL function CREATE TABLE test_parameterized_sql(id integer, org_id integer); select create_distributed_table('test_parameterized_sql','org_id'); create_distributed_table -------------------------- (1 row) CREATE OR REPLACE FUNCTION test_parameterized_sql_function(org_id_val integer) RETURNS TABLE (a bigint) AS $$ SELECT count(*) AS count_val from test_parameterized_sql where org_id = org_id_val; $$ LANGUAGE SQL STABLE; CREATE OR REPLACE FUNCTION test_parameterized_sql_function_in_subquery_where(org_id_val integer) RETURNS TABLE (a bigint) AS $$ SELECT count(*) AS count_val from test_parameterized_sql as t1 where org_id IN (SELECT org_id FROM test_parameterized_sql as t2 WHERE t2.org_id = t1.org_id AND org_id = org_id_val); $$ LANGUAGE SQL STABLE; INSERT INTO test_parameterized_sql VALUES(1, 1); -- all of them should fail SELECT * FROM test_parameterized_sql_function(1); ERROR: cannot perform distributed planning on this query because parameterized queries for SQL functions referencing distributed tables are not supported HINT: Consider using PL/pgSQL functions instead. SELECT test_parameterized_sql_function(1); ERROR: could not create distributed plan DETAIL: Possibly this is caused by the use of parameters in SQL functions, which is not supported in Citus. HINT: Consider using PL/pgSQL functions instead. CONTEXT: SQL function "test_parameterized_sql_function" statement 1 SELECT test_parameterized_sql_function_in_subquery_where(1); ERROR: could not create distributed plan DETAIL: Possibly this is caused by the use of parameters in SQL functions, which is not supported in Citus. HINT: Consider using PL/pgSQL functions instead. CONTEXT: SQL function "test_parameterized_sql_function_in_subquery_where" statement 1 DROP TABLE temp_table; DROP TABLE test_parameterized_sql; -- 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 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); DROP FUNCTION test_parameterized_sql_function(int); DROP FUNCTION test_parameterized_sql_function_in_subquery_where(int);