diff --git a/src/backend/distributed/planner/distributed_planner.c b/src/backend/distributed/planner/distributed_planner.c index e9d17582b..ce006ebcd 100644 --- a/src/backend/distributed/planner/distributed_planner.c +++ b/src/backend/distributed/planner/distributed_planner.c @@ -573,6 +573,7 @@ CreateDistributedPlan(uint64 planId, Query *originalQuery, Query *query, ParamLi DistributedPlan *distributedPlan = NULL; MultiTreeRoot *logicalPlan = NULL; List *subPlanList = NIL; + bool hasCtes = originalQuery->cteList != NIL; if (IsModifyCommand(originalQuery)) { @@ -670,8 +671,13 @@ CreateDistributedPlan(uint64 planId, Query *originalQuery, Query *query, ParamLi * We could simplify this code if the logical planner was capable of dealing * with an original query. In that case, we would only have to filter the * planner restriction context. + * + * Note that we check both for subplans and whether the query had CTEs + * prior to calling GenerateSubplansForSubqueriesAndCTEs. If none of + * the CTEs are referenced then there are no subplans, but we still want + * to retry the router planner. */ - if (list_length(subPlanList) > 0) + if (list_length(subPlanList) > 0 || hasCtes) { Query *newQuery = copyObject(originalQuery); bool setPartitionedTablesInherited = false; diff --git a/src/test/regress/expected/dml_recursive.out b/src/test/regress/expected/dml_recursive.out index e79e5a1c3..ca02f9ef5 100644 --- a/src/test/regress/expected/dml_recursive.out +++ b/src/test/regress/expected/dml_recursive.out @@ -1,5 +1,6 @@ CREATE SCHEMA recursive_dml_queries; SET search_path TO recursive_dml_queries, public; +SET citus.next_shard_id TO 2370000; CREATE TABLE recursive_dml_queries.distributed_table (tenant_id text, dept int, info jsonb); SELECT create_distributed_table('distributed_table', 'tenant_id'); create_distributed_table @@ -274,8 +275,7 @@ DEBUG: subqueries are not supported within INSERT queries HINT: Try rewriting your queries with 'INSERT INTO ... SELECT' syntax. ERROR: subqueries are not supported within INSERT queries HINT: Try rewriting your queries with 'INSERT INTO ... SELECT' syntax. --- we error out of the CTE is not referenced --- by any part of the query (e.g., cte2 is not referenced) +-- DML with an unreferenced SELECT CTE WITH cte_1 AS ( WITH cte_2 AS ( SELECT tenant_id as cte2_id @@ -294,7 +294,49 @@ WHERE distributed_table.tenant_id < cte_1.tenant_id; DEBUG: common table expressions are not supported in distributed modifications DEBUG: generating subplan 20_1 for CTE cte_1: WITH cte_2 AS (SELECT second_distributed_table.tenant_id AS cte2_id FROM recursive_dml_queries.second_distributed_table WHERE (second_distributed_table.dept >= 2)) UPDATE recursive_dml_queries.distributed_table SET dept = 10 RETURNING tenant_id, dept, info DEBUG: common table expressions are not supported in distributed modifications -ERROR: common table expressions are not supported in distributed modifications +DEBUG: Plan 20 query after replacing subqueries and CTEs: UPDATE recursive_dml_queries.distributed_table SET dept = 5 FROM (SELECT intermediate_result.tenant_id, intermediate_result.dept, intermediate_result.info FROM read_intermediate_result('20_1'::text, 'binary'::citus_copy_format) intermediate_result(tenant_id text, dept integer, info jsonb)) cte_1 WHERE (distributed_table.tenant_id < cte_1.tenant_id) +EXPLAIN (COSTS FALSE) WITH cte_1 AS ( + WITH cte_2 AS ( + SELECT tenant_id as cte2_id + FROM second_distributed_table + WHERE dept >= 2 + ) + + UPDATE distributed_table + SET dept = 10 + RETURNING * +) +UPDATE distributed_table +SET dept = 5 +FROM cte_1 +WHERE distributed_table.tenant_id < cte_1.tenant_id; +DEBUG: common table expressions are not supported in distributed modifications +DEBUG: generating subplan 22_1 for CTE cte_1: WITH cte_2 AS (SELECT second_distributed_table.tenant_id AS cte2_id FROM recursive_dml_queries.second_distributed_table WHERE (second_distributed_table.dept >= 2)) UPDATE recursive_dml_queries.distributed_table SET dept = 10 RETURNING tenant_id, dept, info +DEBUG: common table expressions are not supported in distributed modifications +DEBUG: Plan 22 query after replacing subqueries and CTEs: UPDATE recursive_dml_queries.distributed_table SET dept = 5 FROM (SELECT intermediate_result.tenant_id, intermediate_result.dept, intermediate_result.info FROM read_intermediate_result('22_1'::text, 'binary'::citus_copy_format) intermediate_result(tenant_id text, dept integer, info jsonb)) cte_1 WHERE (distributed_table.tenant_id < cte_1.tenant_id) + QUERY PLAN +------------------------------------------------------------------------------------------------ + Custom Scan (Citus Router) + -> Distributed Subplan 22_1 + -> Custom Scan (Citus Router) + Task Count: 4 + Tasks Shown: One of 4 + -> Task + Node: host=localhost port=57638 dbname=regression + -> Update on distributed_table_2370000 distributed_table + -> Seq Scan on distributed_table_2370000 distributed_table + Task Count: 4 + Tasks Shown: One of 4 + -> Task + Node: host=localhost port=57638 dbname=regression + -> Update on distributed_table_2370000 distributed_table + -> Nested Loop + Join Filter: (distributed_table.tenant_id < intermediate_result.tenant_id) + -> Function Scan on read_intermediate_result intermediate_result + -> Materialize + -> Seq Scan on distributed_table_2370000 distributed_table +(19 rows) + -- we don't support updating local table with a join with -- distributed tables UPDATE diff --git a/src/test/regress/sql/dml_recursive.sql b/src/test/regress/sql/dml_recursive.sql index e04b1ef6b..f44195a84 100644 --- a/src/test/regress/sql/dml_recursive.sql +++ b/src/test/regress/sql/dml_recursive.sql @@ -1,5 +1,6 @@ CREATE SCHEMA recursive_dml_queries; SET search_path TO recursive_dml_queries, public; +SET citus.next_shard_id TO 2370000; CREATE TABLE recursive_dml_queries.distributed_table (tenant_id text, dept int, info jsonb); SELECT create_distributed_table('distributed_table', 'tenant_id'); @@ -216,8 +217,7 @@ INSERT INTO second_distributed_table (tenant_id, dept) VALUES ('3', (SELECT 3)); --- we error out of the CTE is not referenced --- by any part of the query (e.g., cte2 is not referenced) +-- DML with an unreferenced SELECT CTE WITH cte_1 AS ( WITH cte_2 AS ( SELECT tenant_id as cte2_id @@ -234,6 +234,22 @@ SET dept = 5 FROM cte_1 WHERE distributed_table.tenant_id < cte_1.tenant_id; +EXPLAIN (COSTS FALSE) WITH cte_1 AS ( + WITH cte_2 AS ( + SELECT tenant_id as cte2_id + FROM second_distributed_table + WHERE dept >= 2 + ) + + UPDATE distributed_table + SET dept = 10 + RETURNING * +) +UPDATE distributed_table +SET dept = 5 +FROM cte_1 +WHERE distributed_table.tenant_id < cte_1.tenant_id; + -- we don't support updating local table with a join with -- distributed tables UPDATE