mirror of https://github.com/citusdata/citus.git
Fix segmentation fault in case of joins with WHERE 1=0
parent
5494f21541
commit
4c72a88bfe
|
@ -814,7 +814,12 @@ SelectClauseTableIdList(List *selectClauseList)
|
|||
Var *selectColumn = NULL;
|
||||
int selectColumnTableId = 0;
|
||||
|
||||
Assert(list_length(selectColumnList) > 0);
|
||||
if (list_length(selectColumnList) == 0)
|
||||
{
|
||||
/* filter is a constant, e.g. false or 1=0 */
|
||||
continue;
|
||||
}
|
||||
|
||||
selectColumn = (Var *) linitial(selectColumnList);
|
||||
selectColumnTableId = (int) selectColumn->varno;
|
||||
|
||||
|
@ -944,8 +949,15 @@ TableIdListSelectClauses(List *tableIdList, List *selectClauseList)
|
|||
foreach(selectClauseCell, selectClauseList)
|
||||
{
|
||||
Node *selectClause = (Node *) lfirst(selectClauseCell);
|
||||
List *selectColumnList = pull_var_clause_default(selectClause);
|
||||
|
||||
List *selectColumnList = pull_var_clause_default(selectClause);
|
||||
if (list_length(selectColumnList) == 0)
|
||||
{
|
||||
/* filter is a constant, e.g. false or 1=0, always include it */
|
||||
tableSelectClauseList = lappend(tableSelectClauseList, selectClause);
|
||||
}
|
||||
else
|
||||
{
|
||||
Var *selectColumn = (Var *) linitial(selectColumnList);
|
||||
int selectClauseTableId = (int) selectColumn->varno;
|
||||
|
||||
|
@ -955,6 +967,7 @@ TableIdListSelectClauses(List *tableIdList, List *selectClauseList)
|
|||
tableSelectClauseList = lappend(tableSelectClauseList, selectClause);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tableSelectClauseList;
|
||||
}
|
||||
|
|
|
@ -2516,6 +2516,12 @@ PruneShardList(Oid relationId, Index tableId, List *whereClauseList,
|
|||
Var *partitionColumn = PartitionColumn(relationId, tableId);
|
||||
char partitionMethod = PartitionMethod(relationId);
|
||||
|
||||
if (ContainsFalseClause(whereClauseList))
|
||||
{
|
||||
/* always return empty result if WHERE clause is of the form: false (AND ..) */
|
||||
return NIL;
|
||||
}
|
||||
|
||||
/* build the filter clause list for the partition method */
|
||||
if (partitionMethod == DISTRIBUTE_BY_HASH)
|
||||
{
|
||||
|
@ -2570,6 +2576,35 @@ PruneShardList(Oid relationId, Index tableId, List *whereClauseList,
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* ContainsFalseClause returns whether the flattened where clause list
|
||||
* contains false as a clause.
|
||||
*/
|
||||
bool
|
||||
ContainsFalseClause(List *whereClauseList)
|
||||
{
|
||||
bool containsFalseClause = false;
|
||||
ListCell *clauseCell = NULL;
|
||||
|
||||
foreach(clauseCell, whereClauseList)
|
||||
{
|
||||
Node *clause = (Node *) lfirst(clauseCell);
|
||||
|
||||
if (IsA(clause, Const))
|
||||
{
|
||||
Const *constant = (Const *) clause;
|
||||
if (constant->consttype == BOOLOID && !DatumGetBool(constant->constvalue))
|
||||
{
|
||||
containsFalseClause = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return containsFalseClause;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* BuildBaseConstraint builds and returns a base constraint. This constraint
|
||||
* implements an expression in the form of (column <= max && column >= min),
|
||||
|
|
|
@ -231,6 +231,7 @@ extern StringInfo ShardFetchQueryString(uint64 shardId);
|
|||
/* Function declarations for shard pruning */
|
||||
extern List * PruneShardList(Oid relationId, Index tableId, List *whereClauseList,
|
||||
List *shardList);
|
||||
extern bool ContainsFalseClause(List *whereClauseList);
|
||||
extern OpExpr * MakeOpExpression(Var *variable, int16 strategyNumber);
|
||||
|
||||
/*
|
||||
|
|
|
@ -224,7 +224,7 @@ SELECT count(*) FROM lineitem
|
|||
WHERE 0 != 0;
|
||||
count
|
||||
-------
|
||||
0
|
||||
|
||||
(1 row)
|
||||
|
||||
-- distinct expressions can be pushed down
|
||||
|
|
|
@ -67,6 +67,22 @@ DEBUG: join prunable for intervals [13921,14947] and [1,5986]
|
|||
|
|
||||
(1 row)
|
||||
|
||||
-- Make sure that we can handle filters without a column
|
||||
SELECT sum(l_linenumber), avg(l_linenumber) FROM lineitem, orders
|
||||
WHERE l_orderkey = o_orderkey AND false;
|
||||
sum | avg
|
||||
-----+-----
|
||||
|
|
||||
(1 row)
|
||||
|
||||
SELECT sum(l_linenumber), avg(l_linenumber)
|
||||
FROM lineitem INNER JOIN orders ON (l_orderkey = o_orderkey)
|
||||
WHERE false;
|
||||
sum | avg
|
||||
-----+-----
|
||||
|
|
||||
(1 row)
|
||||
|
||||
-- These tests check that we can do join pruning for tables partitioned over
|
||||
-- different type of columns including varchar, array types, composite types
|
||||
-- etc. This is in response to a bug we had where we were not able to resolve
|
||||
|
@ -102,4 +118,3 @@ DEBUG: join prunable for intervals [BA1000U2AMO4ZGX,BZZXSP27F21T6] and [AA1000U
|
|||
explain statements for distributed queries are not enabled
|
||||
(1 row)
|
||||
|
||||
SET client_min_messages TO NOTICE;
|
||||
|
|
|
@ -128,5 +128,42 @@ DEBUG: predicate pruning for shardId 290005
|
|||
|
||||
(1 row)
|
||||
|
||||
-- Reset client logging level to its previous value
|
||||
SET client_min_messages TO NOTICE;
|
||||
-- Test cases with false in the WHERE clause
|
||||
SELECT
|
||||
o_orderkey
|
||||
FROM
|
||||
orders INNER JOIN customer ON (o_custkey = c_custkey)
|
||||
WHERE
|
||||
false;
|
||||
o_orderkey
|
||||
------------
|
||||
(0 rows)
|
||||
|
||||
SELECT
|
||||
o_orderkey
|
||||
FROM
|
||||
orders INNER JOIN customer ON (o_custkey = c_custkey)
|
||||
WHERE
|
||||
1=0 AND c_custkey < 0;
|
||||
o_orderkey
|
||||
------------
|
||||
(0 rows)
|
||||
|
||||
SELECT
|
||||
o_orderkey
|
||||
FROM
|
||||
orders INNER JOIN customer ON (o_custkey = c_custkey AND false);
|
||||
o_orderkey
|
||||
------------
|
||||
(0 rows)
|
||||
|
||||
SELECT
|
||||
o_orderkey
|
||||
FROM
|
||||
orders, customer
|
||||
WHERE
|
||||
o_custkey = c_custkey AND false;
|
||||
o_orderkey
|
||||
------------
|
||||
(0 rows)
|
||||
|
||||
|
|
|
@ -36,6 +36,14 @@ SELECT sum(l_linenumber), avg(l_linenumber) FROM lineitem, orders
|
|||
SELECT sum(l_linenumber), avg(l_linenumber) FROM lineitem, orders
|
||||
WHERE l_orderkey = o_orderkey AND l_orderkey > 6000 AND o_orderkey < 6000;
|
||||
|
||||
-- Make sure that we can handle filters without a column
|
||||
SELECT sum(l_linenumber), avg(l_linenumber) FROM lineitem, orders
|
||||
WHERE l_orderkey = o_orderkey AND false;
|
||||
|
||||
SELECT sum(l_linenumber), avg(l_linenumber)
|
||||
FROM lineitem INNER JOIN orders ON (l_orderkey = o_orderkey)
|
||||
WHERE false;
|
||||
|
||||
-- These tests check that we can do join pruning for tables partitioned over
|
||||
-- different type of columns including varchar, array types, composite types
|
||||
-- etc. This is in response to a bug we had where we were not able to resolve
|
||||
|
@ -54,5 +62,3 @@ EXPLAIN SELECT count(*)
|
|||
EXPLAIN SELECT count(*)
|
||||
FROM varchar_partitioned_table table1, varchar_partitioned_table table2
|
||||
WHERE table1.varchar_column = table2.varchar_column;
|
||||
|
||||
SET client_min_messages TO NOTICE;
|
||||
|
|
|
@ -67,6 +67,29 @@ WHERE
|
|||
l_partkey = c_nationkey AND
|
||||
l_orderkey < 0;
|
||||
|
||||
-- Reset client logging level to its previous value
|
||||
-- Test cases with false in the WHERE clause
|
||||
SELECT
|
||||
o_orderkey
|
||||
FROM
|
||||
orders INNER JOIN customer ON (o_custkey = c_custkey)
|
||||
WHERE
|
||||
false;
|
||||
|
||||
SET client_min_messages TO NOTICE;
|
||||
SELECT
|
||||
o_orderkey
|
||||
FROM
|
||||
orders INNER JOIN customer ON (o_custkey = c_custkey)
|
||||
WHERE
|
||||
1=0 AND c_custkey < 0;
|
||||
|
||||
SELECT
|
||||
o_orderkey
|
||||
FROM
|
||||
orders INNER JOIN customer ON (o_custkey = c_custkey AND false);
|
||||
|
||||
SELECT
|
||||
o_orderkey
|
||||
FROM
|
||||
orders, customer
|
||||
WHERE
|
||||
o_custkey = c_custkey AND false;
|
||||
|
|
Loading…
Reference in New Issue