From 388be994e768dc3c53d7c5a38794187496f79194 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 0b5d03d3c..9b8527dd6 100644 --- a/src/backend/distributed/planner/multi_planner.c +++ b/src/backend/distributed/planner/multi_planner.c @@ -265,7 +265,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);