From ae3fd6e10dfe536e186b08e6feb5a584c38ab3fb Mon Sep 17 00:00:00 2001 From: Onder Kalaci Date: Fri, 14 Apr 2017 16:01:08 +0300 Subject: [PATCH] Disallow subqueries without a relation in the range table list for INSERT .. SELECT This commit disallows subqueries without relation in the range table list. This commit is only applied for INSERT.. SELECT queries. The reasoning behind this limitation is that if we allow pushing down such queries, the result would include (shardCount * expectedResults) where in a non distributed world the result would be (expectedResult) only. --- .../planner/multi_router_planner.c | 9 +++++++ ...lti_insert_select_non_pushable_queries.out | 27 +++++++++++++++++++ ...lti_insert_select_non_pushable_queries.sql | 27 +++++++++++++++++++ 3 files changed, 63 insertions(+) diff --git a/src/backend/distributed/planner/multi_router_planner.c b/src/backend/distributed/planner/multi_router_planner.c index 1df52f6e8..753913ca0 100644 --- a/src/backend/distributed/planner/multi_router_planner.c +++ b/src/backend/distributed/planner/multi_router_planner.c @@ -871,6 +871,15 @@ MultiTaskRouterSelectQuerySupported(Query *query) Assert(subquery->commandType == CMD_SELECT); + /* pushing down rtes without relations yields (shardCount * expectedRows) */ + if (subquery->rtable == NIL) + { + return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED, + "Subqueries without relations are not allowed in " + "INSERT ... SELECT queries", + NULL, NULL); + } + /* pushing down limit per shard would yield wrong results */ if (subquery->limitCount != NULL) { diff --git a/src/test/regress/expected/multi_insert_select_non_pushable_queries.out b/src/test/regress/expected/multi_insert_select_non_pushable_queries.out index e3c9c0d6b..ef0ec218b 100644 --- a/src/test/regress/expected/multi_insert_select_non_pushable_queries.out +++ b/src/test/regress/expected/multi_insert_select_non_pushable_queries.out @@ -660,3 +660,30 @@ FROM WHERE users_table.value_1 < 50; ERROR: cannot perform distributed planning for the given modification DETAIL: Select query cannot be pushed down to the worker. +-- not supported since one of the queries doesn't have a relation +INSERT INTO agg_results (user_id, agg_time, value_2_agg) +SELECT + user_id, + user_lastseen, + array_length(event_array, 1) +FROM ( + SELECT + user_id, + max(u.time) as user_lastseen, + array_agg(event_type ORDER BY u.time) AS event_array + FROM ( + SELECT user_id, time, value_3 as val_3 + FROM users_table + WHERE + user_id >= 10 AND user_id <= 70 AND + users_table.value_1 > 10 AND users_table.value_1 < 12 + ) u LEFT JOIN LATERAL ( + SELECT event_type, time + FROM events_table, (SELECT 1 as x) as f + WHERE user_id = u.user_id AND + events_table.event_type > 10 AND events_table.event_type < 12 + ) t ON true + GROUP BY user_id +) AS shard_union +ORDER BY user_lastseen DESC; +ERROR: Subqueries without relations are not allowed in INSERT ... SELECT queries diff --git a/src/test/regress/sql/multi_insert_select_non_pushable_queries.sql b/src/test/regress/sql/multi_insert_select_non_pushable_queries.sql index c7089903b..3982900a8 100644 --- a/src/test/regress/sql/multi_insert_select_non_pushable_queries.sql +++ b/src/test/regress/sql/multi_insert_select_non_pushable_queries.sql @@ -649,3 +649,30 @@ FROM ) temp ON users_table.user_id = temp.user_id WHERE users_table.value_1 < 50; + +-- not supported since one of the queries doesn't have a relation +INSERT INTO agg_results (user_id, agg_time, value_2_agg) +SELECT + user_id, + user_lastseen, + array_length(event_array, 1) +FROM ( + SELECT + user_id, + max(u.time) as user_lastseen, + array_agg(event_type ORDER BY u.time) AS event_array + FROM ( + SELECT user_id, time, value_3 as val_3 + FROM users_table + WHERE + user_id >= 10 AND user_id <= 70 AND + users_table.value_1 > 10 AND users_table.value_1 < 12 + ) u LEFT JOIN LATERAL ( + SELECT event_type, time + FROM events_table, (SELECT 1 as x) as f + WHERE user_id = u.user_id AND + events_table.event_type > 10 AND events_table.event_type < 12 + ) t ON true + GROUP BY user_id +) AS shard_union +ORDER BY user_lastseen DESC;