From fdcb6ead43c440b7da9cdc86588d9459fd7a13e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96nder=20Kalac=C4=B1?= Date: Fri, 26 Feb 2021 11:04:21 +0100 Subject: [PATCH] Prevent cross join without any target list entries (#4750) /* * The physical planner assumes that all worker queries would have * target list entries based on the fact that at least the column * on the JOINs have to be on the target list. However, there is * an exception to that if there is a cartesian product join and * there is no additional target list entries belong to one side * of the JOIN. Once we support cartesian product join, we should * remove this error. */ (cherry picked from commit 0fe26a216c7a5f95585590abee33db90f15797dd) --- .../planner/multi_physical_planner.c | 16 ++++++- src/test/regress/expected/cross_join.out | 45 +++++++++++++++++++ src/test/regress/sql/cross_join.sql | 16 +++++++ 3 files changed, 76 insertions(+), 1 deletion(-) diff --git a/src/backend/distributed/planner/multi_physical_planner.c b/src/backend/distributed/planner/multi_physical_planner.c index 0f699f24e..5093a9d2d 100644 --- a/src/backend/distributed/planner/multi_physical_planner.c +++ b/src/backend/distributed/planner/multi_physical_planner.c @@ -824,7 +824,21 @@ static List * QueryTargetList(MultiNode *multiNode) { List *projectNodeList = FindNodesOfType(multiNode, T_MultiProject); - Assert(list_length(projectNodeList) > 0); + if (list_length(projectNodeList) == 0) + { + /* + * The physical planner assumes that all worker queries would have + * target list entries based on the fact that at least the column + * on the JOINs have to be on the target list. However, there is + * an exception to that if there is a cartesian product join and + * there is no additional target list entries belong to one side + * of the JOIN. Once we support cartesian product join, we should + * remove this error. + */ + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot perform distributed planning on this query"), + errdetail("Cartesian products are currently unsupported"))); + } MultiProject *topProjectNode = (MultiProject *) linitial(projectNodeList); List *columnList = topProjectNode->columnList; diff --git a/src/test/regress/expected/cross_join.out b/src/test/regress/expected/cross_join.out index 8ced8541d..279c4ab2f 100644 --- a/src/test/regress/expected/cross_join.out +++ b/src/test/regress/expected/cross_join.out @@ -251,3 +251,48 @@ ORDER BY 1,2,3,4 LIMIT 5; 1 | Wed Nov 22 22:51:43.132261 2017 | 4 | 0 | 3 | (5 rows) +-- we don't support cross JOINs between distributed tables +-- and without target list entries +CREATE TABLE dist1(c0 int); +CREATE TABLE dist2(c0 int); +CREATE TABLE dist3(c0 int , c1 int); +CREATE TABLE dist4(c0 int , c1 int); +SELECT create_distributed_table('dist1', 'c0'); + create_distributed_table +--------------------------------------------------------------------- + +(1 row) + +SELECT create_distributed_table('dist2', 'c0'); + create_distributed_table +--------------------------------------------------------------------- + +(1 row) + +SELECT create_distributed_table('dist3', 'c1'); + create_distributed_table +--------------------------------------------------------------------- + +(1 row) + +SELECT create_distributed_table('dist4', 'c1'); + create_distributed_table +--------------------------------------------------------------------- + +(1 row) + +SELECT dist2.c0 FROM dist1, dist3, dist4, dist2 WHERE (dist3.c0) IN (dist4.c0); +ERROR: cannot perform distributed planning on this query +DETAIL: Cartesian products are currently unsupported +SELECT 1 FROM dist3, dist4, dist2 WHERE (dist3.c0) IN (dist4.c0); +ERROR: cannot perform distributed planning on this query +DETAIL: Cartesian products are currently unsupported +SELECT FROM dist3, dist4, dist2 WHERE (dist3.c0) IN (dist4.c0); +ERROR: cannot perform distributed planning on this query +DETAIL: Cartesian products are currently unsupported +SELECT dist2.c0 FROM dist3, dist4, dist2 WHERE (dist3.c0) IN (dist4.c0); +ERROR: cannot perform distributed planning on this query +DETAIL: Cartesian products are currently unsupported +SELECT dist2.* FROM dist3, dist4, dist2 WHERE (dist3.c0) IN (dist4.c0); +ERROR: cannot perform distributed planning on this query +DETAIL: Cartesian products are currently unsupported diff --git a/src/test/regress/sql/cross_join.sql b/src/test/regress/sql/cross_join.sql index c301e753b..3e776368b 100644 --- a/src/test/regress/sql/cross_join.sql +++ b/src/test/regress/sql/cross_join.sql @@ -128,4 +128,20 @@ FROM LEFT JOIN users_table USING (user_id) ORDER BY 1,2,3,4 LIMIT 5; +-- we don't support cross JOINs between distributed tables +-- and without target list entries +CREATE TABLE dist1(c0 int); +CREATE TABLE dist2(c0 int); +CREATE TABLE dist3(c0 int , c1 int); +CREATE TABLE dist4(c0 int , c1 int); +SELECT create_distributed_table('dist1', 'c0'); +SELECT create_distributed_table('dist2', 'c0'); +SELECT create_distributed_table('dist3', 'c1'); +SELECT create_distributed_table('dist4', 'c1'); + +SELECT dist2.c0 FROM dist1, dist3, dist4, dist2 WHERE (dist3.c0) IN (dist4.c0); +SELECT 1 FROM dist3, dist4, dist2 WHERE (dist3.c0) IN (dist4.c0); +SELECT FROM dist3, dist4, dist2 WHERE (dist3.c0) IN (dist4.c0); +SELECT dist2.c0 FROM dist3, dist4, dist2 WHERE (dist3.c0) IN (dist4.c0); +SELECT dist2.* FROM dist3, dist4, dist2 WHERE (dist3.c0) IN (dist4.c0);