Fix segmentation fault in case of joins with WHERE 1=0

pull/804/head
Marco Slot 2016-09-25 00:42:16 +02:00
parent 70fd42c41c
commit 3318288d75
8 changed files with 145 additions and 15 deletions

View File

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

View File

@ -2515,6 +2515,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)
{
@ -2569,6 +2575,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),

View File

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

View File

@ -224,7 +224,7 @@ SELECT count(*) FROM lineitem
WHERE 0 != 0;
count
-------
0
(1 row)
-- distinct expressions can be pushed down

View File

@ -75,6 +75,22 @@ DEBUG: join prunable for intervals [13473,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
@ -110,4 +126,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;

View File

@ -130,5 +130,42 @@ DEBUG: predicate pruning for shardId 290007
(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)

View File

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

View File

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