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; Var *selectColumn = NULL;
int selectColumnTableId = 0; 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); selectColumn = (Var *) linitial(selectColumnList);
selectColumnTableId = (int) selectColumn->varno; selectColumnTableId = (int) selectColumn->varno;
@ -944,16 +949,24 @@ TableIdListSelectClauses(List *tableIdList, List *selectClauseList)
foreach(selectClauseCell, selectClauseList) foreach(selectClauseCell, selectClauseList)
{ {
Node *selectClause = (Node *) lfirst(selectClauseCell); Node *selectClause = (Node *) lfirst(selectClauseCell);
List *selectColumnList = pull_var_clause_default(selectClause); List *selectColumnList = pull_var_clause_default(selectClause);
if (list_length(selectColumnList) == 0)
Var *selectColumn = (Var *) linitial(selectColumnList);
int selectClauseTableId = (int) selectColumn->varno;
bool tableIdListMember = list_member_int(tableIdList, selectClauseTableId);
if (tableIdListMember)
{ {
/* filter is a constant, e.g. false or 1=0, always include it */
tableSelectClauseList = lappend(tableSelectClauseList, selectClause); tableSelectClauseList = lappend(tableSelectClauseList, selectClause);
} }
else
{
Var *selectColumn = (Var *) linitial(selectColumnList);
int selectClauseTableId = (int) selectColumn->varno;
bool tableIdListMember = list_member_int(tableIdList, selectClauseTableId);
if (tableIdListMember)
{
tableSelectClauseList = lappend(tableSelectClauseList, selectClause);
}
}
} }
return tableSelectClauseList; return tableSelectClauseList;

View File

@ -2515,6 +2515,12 @@ PruneShardList(Oid relationId, Index tableId, List *whereClauseList,
Var *partitionColumn = PartitionColumn(relationId, tableId); Var *partitionColumn = PartitionColumn(relationId, tableId);
char partitionMethod = PartitionMethod(relationId); 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 */ /* build the filter clause list for the partition method */
if (partitionMethod == DISTRIBUTE_BY_HASH) 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 * BuildBaseConstraint builds and returns a base constraint. This constraint
* implements an expression in the form of (column <= max && column >= min), * 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 */ /* Function declarations for shard pruning */
extern List * PruneShardList(Oid relationId, Index tableId, List *whereClauseList, extern List * PruneShardList(Oid relationId, Index tableId, List *whereClauseList,
List *shardList); List *shardList);
extern bool ContainsFalseClause(List *whereClauseList);
extern OpExpr * MakeOpExpression(Var *variable, int16 strategyNumber); extern OpExpr * MakeOpExpression(Var *variable, int16 strategyNumber);
/* /*

View File

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

View File

@ -75,6 +75,22 @@ DEBUG: join prunable for intervals [13473,14947] and [1,5986]
| |
(1 row) (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 -- These tests check that we can do join pruning for tables partitioned over
-- different type of columns including varchar, array types, composite types -- 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 -- 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 explain statements for distributed queries are not enabled
(1 row) (1 row)
SET client_min_messages TO NOTICE;

View File

@ -130,5 +130,42 @@ DEBUG: predicate pruning for shardId 290007
(1 row) (1 row)
-- Reset client logging level to its previous value -- Test cases with false in the WHERE clause
SET client_min_messages TO NOTICE; 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 SELECT sum(l_linenumber), avg(l_linenumber) FROM lineitem, orders
WHERE l_orderkey = o_orderkey AND l_orderkey > 6000 AND o_orderkey < 6000; 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 -- These tests check that we can do join pruning for tables partitioned over
-- different type of columns including varchar, array types, composite types -- 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 -- 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(*) EXPLAIN SELECT count(*)
FROM varchar_partitioned_table table1, varchar_partitioned_table table2 FROM varchar_partitioned_table table1, varchar_partitioned_table table2
WHERE table1.varchar_column = table2.varchar_column; 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_partkey = c_nationkey AND
l_orderkey < 0; 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;