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.
 */
pull/4744/head
Önder Kalacı 2021-02-26 11:04:21 +01:00 committed by GitHub
parent 5e6030b87f
commit 0fe26a216c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 76 additions and 1 deletions

View File

@ -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;

View File

@ -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

View File

@ -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);