From 12ca9513ebf1d99becd2791a3648031bc171170f Mon Sep 17 00:00:00 2001 From: Onder Kalaci Date: Mon, 24 Apr 2017 14:45:57 +0300 Subject: [PATCH] Extend checks for unresolved paramaters to include SubLinks With the presence of subqueries in where clause (i.e., SubPlans on the query) the existing way for checking unresolved parameters fail. The reason is that the parameters for SubPlans are kept on the parent plan not on the query itself (see primnodes.h for the details). With this commit, instead of checking SubPlans on the modified plans we start to use originalQuery, where SubLinks represent the subqueries in where clause. The unresolved parameters can be found on the SubLinks. --- src/backend/distributed/planner/multi_planner.c | 2 +- src/test/regress/expected/multi_sql_function.out | 14 +++++++++++++- src/test/regress/sql/multi_sql_function.sql | 12 +++++++++++- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/backend/distributed/planner/multi_planner.c b/src/backend/distributed/planner/multi_planner.c index 3cebc1e53..f60e803c1 100644 --- a/src/backend/distributed/planner/multi_planner.c +++ b/src/backend/distributed/planner/multi_planner.c @@ -266,7 +266,7 @@ CreateDistributedPlan(PlannedStmt *localPlan, Query *originalQuery, Query *query PlannedStmt *resultPlan = NULL; bool hasUnresolvedParams = false; - if (HasUnresolvedExternParamsWalker((Node *) query, boundParams)) + if (HasUnresolvedExternParamsWalker((Node *) originalQuery, boundParams)) { hasUnresolvedParams = true; } diff --git a/src/test/regress/expected/multi_sql_function.out b/src/test/regress/expected/multi_sql_function.out index 860fe9a75..0c4458677 100644 --- a/src/test/regress/expected/multi_sql_function.out +++ b/src/test/regress/expected/multi_sql_function.out @@ -316,8 +316,14 @@ 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); --- both of them should fail +-- 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. @@ -326,6 +332,11 @@ 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 @@ -338,3 +349,4 @@ 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); diff --git a/src/test/regress/sql/multi_sql_function.sql b/src/test/regress/sql/multi_sql_function.sql index 22ba0a380..b93313e08 100644 --- a/src/test/regress/sql/multi_sql_function.sql +++ b/src/test/regress/sql/multi_sql_function.sql @@ -134,11 +134,20 @@ 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); --- both of them should fail +-- all of them should fail SELECT * FROM test_parameterized_sql_function(1); SELECT test_parameterized_sql_function(1); +SELECT test_parameterized_sql_function_in_subquery_where(1); DROP TABLE temp_table; DROP TABLE test_parameterized_sql; @@ -153,3 +162,4 @@ 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);