static PruneStepResult *perform_pruning_combine_step(PartitionPruneContext *context,
PartitionPruneStepCombine *cstep,
PruneStepResult **step_results);
-static bool match_boolean_partition_clause(Oid partopfamily, Expr *clause,
- Expr *partkey, Expr **outconst);
+static PartClauseMatchStatus match_boolean_partition_clause(Oid partopfamily,
+ Expr *clause,
+ Expr *partkey,
+ Expr **outconst);
static void partkey_datum_from_expr(PartitionPruneContext *context,
Expr *expr, int stateidx,
Datum *value, bool *isnull);
bool *clause_is_not_null, PartClauseInfo **pc,
List **clause_steps)
{
+ PartClauseMatchStatus boolmatchstatus;
PartitionScheme part_scheme = context->rel->part_scheme;
Oid partopfamily = part_scheme->partopfamily[partkeyidx],
partcoll = part_scheme->partcollation[partkeyidx];
/*
* Recognize specially shaped clauses that match a Boolean partition key.
*/
- if (match_boolean_partition_clause(partopfamily, clause, partkey, &expr))
+ boolmatchstatus = match_boolean_partition_clause(partopfamily, clause,
+ partkey, &expr);
+
+ if (boolmatchstatus == PARTCLAUSE_MATCH_CLAUSE)
{
PartClauseInfo *partclause;
return PARTCLAUSE_MATCH_NULLNESS;
}
- return PARTCLAUSE_UNSUPPORTED;
+ /*
+ * If we get here then the return value depends on the result of the
+ * match_boolean_partition_clause call above. If the call returned
+ * PARTCLAUSE_UNSUPPORTED then we're either not dealing with a bool qual
+ * or the bool qual is not suitable for pruning. Since the qual didn't
+ * match up to any of the other qual types supported here, then trying to
+ * match it against any other partition key is a waste of time, so just
+ * return PARTCLAUSE_UNSUPPORTED. If the qual just couldn't be matched to
+ * this partition key, then it may match another, so return
+ * PARTCLAUSE_NOMATCH. The only other value that
+ * match_boolean_partition_clause can return is PARTCLAUSE_MATCH_CLAUSE,
+ * and since that value was already dealt with above, then we can just
+ * return boolmatchstatus.
+ */
+ return boolmatchstatus;
}
/*
/*
* match_boolean_partition_clause
*
- * Sets *outconst to a Const containing true or false value and returns true if
- * we're able to match the clause to the partition key as specially-shaped
- * Boolean clause. Returns false otherwise with *outconst set to NULL.
+ * If we're able to match the clause to the partition key as specially-shaped
+ * boolean clause, set *outconst to a Const containing a true or false value
+ * and return PARTCLAUSE_MATCH_CLAUSE. Returns PARTCLAUSE_UNSUPPORTED if the
+ * clause is not a boolean clause or if the boolean clause is unsuitable for
+ * partition pruning. Returns PARTCLAUSE_NOMATCH if it's a bool quals but
+ * just does not match this partition key. *outconst is set to NULL in the
+ * latter two cases.
*/
-static bool
+static PartClauseMatchStatus
match_boolean_partition_clause(Oid partopfamily, Expr *clause, Expr *partkey,
Expr **outconst)
{
*outconst = NULL;
if (!IsBooleanOpfamily(partopfamily))
- return false;
+ return PARTCLAUSE_UNSUPPORTED;
if (IsA(clause, BooleanTest))
{
/* Only IS [NOT] TRUE/FALSE are any good to us */
if (btest->booltesttype == IS_UNKNOWN ||
btest->booltesttype == IS_NOT_UNKNOWN)
- return false;
+ return PARTCLAUSE_UNSUPPORTED;
leftop = btest->arg;
if (IsA(leftop, RelabelType))
: (Expr *) makeBoolConst(false, false);
if (*outconst)
- return true;
+ return PARTCLAUSE_MATCH_CLAUSE;
}
else
{
*outconst = (Expr *) makeBoolConst(false, false);
if (*outconst)
- return true;
+ return PARTCLAUSE_MATCH_CLAUSE;
}
- return false;
+ return PARTCLAUSE_NOMATCH;
}
/*
Filter: (a IS NOT UNKNOWN)
(7 rows)
+create table boolrangep (a bool, b bool, c int) partition by range (a,b,c);
+create table boolrangep_tf partition of boolrangep for values from ('true', 'false', 0) to ('true', 'false', 100);
+create table boolrangep_ft partition of boolrangep for values from ('false', 'true', 0) to ('false', 'true', 100);
+create table boolrangep_ff1 partition of boolrangep for values from ('false', 'false', 0) to ('false', 'false', 50);
+create table boolrangep_ff2 partition of boolrangep for values from ('false', 'false', 50) to ('false', 'false', 100);
+-- try a more complex case that's been known to trip up pruning in the past
+explain (costs off) select * from boolrangep where not a and not b and c = 25;
+ QUERY PLAN
+----------------------------------------------
+ Seq Scan on boolrangep_ff1
+ Filter: ((NOT a) AND (NOT b) AND (c = 25))
+(2 rows)
+
-- test scalar-to-array operators
create table coercepart (a varchar) partition by list (a);
create table coercepart_ab partition of coercepart for values in ('ab');
Filter: (a > '100000000000000'::bigint)
(2 rows)
-drop table lp, coll_pruning, rlp, mc3p, mc2p, boolpart, rp, coll_pruning_multi, like_op_noprune, lparted_by_int2, rparted_by_int2;
+drop table lp, coll_pruning, rlp, mc3p, mc2p, boolpart, boolrangep, rp, coll_pruning_multi, like_op_noprune, lparted_by_int2, rparted_by_int2;
--
-- Test Partition pruning for HASH partitioning
--
explain (costs off) select * from boolpart where a is unknown;
explain (costs off) select * from boolpart where a is not unknown;
+create table boolrangep (a bool, b bool, c int) partition by range (a,b,c);
+create table boolrangep_tf partition of boolrangep for values from ('true', 'false', 0) to ('true', 'false', 100);
+create table boolrangep_ft partition of boolrangep for values from ('false', 'true', 0) to ('false', 'true', 100);
+create table boolrangep_ff1 partition of boolrangep for values from ('false', 'false', 0) to ('false', 'false', 50);
+create table boolrangep_ff2 partition of boolrangep for values from ('false', 'false', 50) to ('false', 'false', 100);
+
+-- try a more complex case that's been known to trip up pruning in the past
+explain (costs off) select * from boolrangep where not a and not b and c = 25;
+
-- test scalar-to-array operators
create table coercepart (a varchar) partition by list (a);
create table coercepart_ab partition of coercepart for values in ('ab');
-- all partitions but rparted_by_int2_maxvalue pruned
explain (costs off) select * from rparted_by_int2 where a > 100000000000000;
-drop table lp, coll_pruning, rlp, mc3p, mc2p, boolpart, rp, coll_pruning_multi, like_op_noprune, lparted_by_int2, rparted_by_int2;
+drop table lp, coll_pruning, rlp, mc3p, mc2p, boolpart, boolrangep, rp, coll_pruning_multi, like_op_noprune, lparted_by_int2, rparted_by_int2;
--
-- Test Partition pruning for HASH partitioning