v41_drowley_fixes.patch
application/octet-stream
Filename: v41_drowley_fixes.patch
Type: application/octet-stream
Part: 0
Patch
Format: unified
Series: patch v41
| File | + | − |
|---|---|---|
| src/backend/catalog/partition.c | 27 | 8 |
| src/backend/nodes/copyfuncs.c | 1 | 0 |
| src/backend/optimizer/plan/planner.c | 3 | 2 |
| src/backend/optimizer/util/partprune.c | 10 | 8 |
| src/include/nodes/primnodes.h | 5 | 5 |
diff --git a/src/backend/catalog/partition.c b/src/backend/catalog/partition.c
index 1b68ab1b82..cf396856a9 100644
--- a/src/backend/catalog/partition.c
+++ b/src/backend/catalog/partition.c
@@ -1790,6 +1790,8 @@ perform_pruning_base_step(PartitionPruneContext *context,
Datum values[PARTITION_MAX_KEYS];
FmgrInfo partsupfunc[PARTITION_MAX_KEYS];
+ Assert(list_length(opstep->exprs) == list_length(opstep->cmpfns));
+
nvalues = 0;
lc1 = list_head(opstep->exprs);
lc2 = list_head(opstep->cmpfns);
@@ -1830,8 +1832,6 @@ perform_pruning_base_step(PartitionPruneContext *context,
* than the one cached in the PartitionKey, we'll need to
* look up the FmgrInfo.
*/
- if (lc2 == NULL)
- elog(ERROR, "incomplete cmpfnids list in pruning step");
cmpfn = lfirst_oid(lc2);
Assert(OidIsValid(cmpfn));
if (cmpfn != context->partsupfunc[keyno].fn_oid)
@@ -1879,6 +1879,8 @@ perform_pruning_base_step(PartitionPruneContext *context,
/*
* perform_pruning_base_step_ne
* Returns indexes of partitions obtained by executing 'nestep'.
+ *
+ * Note this pruning method is only supported by LIST partitioning.
*/
static Bitmapset *
perform_pruning_base_step_ne(PartitionPruneContext *context,
@@ -1893,6 +1895,9 @@ perform_pruning_base_step_ne(PartitionPruneContext *context,
int n_ne_datums = list_length(nestep->exprs),
i;
+ Assert(context->strategy == PARTITION_STRATEGY_LIST);
+ Assert(list_length(nestep->exprs) == list_length(nestep->cmpfns));
+
/*
* Apply not-equal clauses. This only applies in the list
* partitioning case as this is the only partition type where
@@ -1905,8 +1910,7 @@ perform_pruning_base_step_ne(PartitionPruneContext *context,
* Some datums may require different comparison function than
* the default partitioning-specific one.
*/
- partsupfunc = (FmgrInfo **)
- palloc(n_ne_datums * sizeof(FmgrInfo *));
+ partsupfunc = (FmgrInfo **) palloc(n_ne_datums * sizeof(FmgrInfo *));
i = 0;
forboth(lc1, nestep->exprs, lc2, nestep->cmpfns)
@@ -1933,14 +1937,15 @@ perform_pruning_base_step_ne(PartitionPruneContext *context,
}
else
partsupfunc[i] = &context->partsupfunc[0];
- }
- ne_datums[i++] = datum;
+ ne_datums[i++] = datum;
+ }
}
excluded_parts = get_partitions_excluded_by_ne_datums(context, ne_datums, i,
partsupfunc);
pfree(ne_datums);
+ pfree(partsupfunc);
/* All partitions apart from those in excluded_parts match */
result = bms_add_range(NULL, 0, context->nparts - 1);
@@ -2280,7 +2285,7 @@ get_partitions_for_keys_range(PartitionPruneContext *context,
{
if (nvalues == partnatts)
{
- /* There can only be one partition. */
+ /* There can only be zero or one matching partitions. */
if (partindices[off + 1] >= 0)
return bms_make_singleton(partindices[off + 1]);
else if (partition_bound_has_default(boundinfo))
@@ -2535,7 +2540,8 @@ get_partitions_excluded_by_ne_datums(PartitionPruneContext *context,
/*
* We can only do this exclusion for list partitions because that's the
- * only case where we require all values to explicitly specified.
+ * only case where we require all values to explicitly specified in the
+ * partition boundinfo.
*/
Assert(context->strategy == PARTITION_STRATEGY_LIST);
Assert(context->partnatts == 1);
@@ -2569,6 +2575,12 @@ get_partitions_excluded_by_ne_datums(PartitionPruneContext *context,
* counted all this, we can eliminate any partition where the number of
* datums found in the query matches the number of datums allowed in the
* partition.
+ *
+ * It might seem like we can skip attempting pruning any partitions here
+ * if we found no not-equal clauses which match any partitions above, but
+ * because we previously ensured these clauses are strict we may be able
+ * to at least eliminate the NULL partition, providing that partition does
+ * not also allow any non-NULL values.
*/
if (!bms_is_empty(foundoffsets))
{
@@ -2579,6 +2591,13 @@ get_partitions_excluded_by_ne_datums(PartitionPruneContext *context,
datums_in_query[boundinfo->indexes[i]]++;
}
+ /*
+ * We can't prune anything if there's no foundoffsets and no NULL
+ * partition.
+ */
+ else if (!partition_bound_accepts_nulls(boundinfo))
+ return NULL;
+
/*
* Now, in a single pass over all the datums, count the number of datums
* permitted in each partition.
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 6dd525323c..26c5281385 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -2158,6 +2158,7 @@ _copyPartitionPruneStepOpNe(const PartitionPruneStepOpNe *from)
PartitionPruneStepOpNe *newnode = makeNode(PartitionPruneStepOpNe);
COPY_NODE_FIELD(exprs);
+ COPY_NODE_FIELD(cmpfns);
return newnode;
}
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 00d6252552..2cb7f086b7 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -1483,8 +1483,9 @@ inheritance_planner(PlannerInfo *root)
continue;
/* Add the current parent's RT index to the partitioned rels set. */
- partitioned_relids = bms_add_member(partitioned_relids,
- appinfo->parent_relid);
+ if (partitioned_relids)
+ partitioned_relids = bms_add_member(partitioned_relids,
+ appinfo->parent_relid);
/*
* If this is the first non-excluded child, its post-planning rtable
diff --git a/src/backend/optimizer/util/partprune.c b/src/backend/optimizer/util/partprune.c
index 7dfd8fdcaf..e2d8fdb2a2 100644
--- a/src/backend/optimizer/util/partprune.c
+++ b/src/backend/optimizer/util/partprune.c
@@ -758,8 +758,8 @@ generate_pruning_steps_from_opexprs(PartitionScheme part_scheme,
}
/*
- * If we've decided that clauses for subsequent partition keys would't
- * be useful for pruning, don't look.
+ * If we've decided that clauses for subsequent partition keys
+ * wouldn't be useful for pruning, don't look.
*/
if (!consider_next_key)
break;
@@ -895,9 +895,9 @@ generate_pruning_steps_from_opexprs(PartitionScheme part_scheme,
ListCell *lc1;
/*
- * Locate the clause for the greatest column (whic may not
- * be the last partition key column). Actually, the last
- * element of eq_clauses must give us what we need.
+ * Locate the clause for the greatest column (which may
+ * not be the last partition key column). Actually, the
+ * last element of eq_clauses must give us what we need.
*/
pc = llast(eq_clauses);
@@ -994,7 +994,7 @@ generate_pruning_steps_from_opexprs(PartitionScheme part_scheme,
*
* Return value:
*
- * one of PARTCLAUSE_MATCH_* enum values if the clause is successfully
+ * One of PARTCLAUSE_MATCH_* enum values if the clause is successfully
* matched to the partition key. If it is PARTCLAUSE_MATCH_CONTRADICT, then
* this means the clause is self-contradictory (which can happen only if it's
* a BoolExpr whose arguments may be self-contradictory)
@@ -1065,6 +1065,7 @@ match_clause_to_partition_key(RelOptInfo *rel,
Oid commutator = InvalidOid,
negator = InvalidOid;
Oid cmpfn;
+ Oid exprtype;
leftop = (Expr *) get_leftop(clause);
if (IsA(leftop, RelabelType))
@@ -1152,7 +1153,8 @@ match_clause_to_partition_key(RelOptInfo *rel,
}
/* Check if we're going to need a cross-type comparison function. */
- if (exprType((Node *) expr) != part_scheme->partopcintype[partkeyidx])
+ exprtype = exprType((Node *) expr);
+ if (exprtype != part_scheme->partopcintype[partkeyidx])
{
int procnum = (part_scheme->strategy == PARTITION_STRATEGY_HASH)
? HASHEXTENDED_PROC
@@ -1160,7 +1162,7 @@ match_clause_to_partition_key(RelOptInfo *rel,
cmpfn = get_opfamily_proc(part_scheme->partopfamily[partkeyidx],
part_scheme->partopcintype[partkeyidx],
- exprType((Node *) expr), procnum);
+ exprtype, procnum);
/* If we couldn't find one, we cannot use this expression. */
if (!OidIsValid(cmpfn))
return PARTCLAUSE_UNSUPPORTED;
diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h
index 959964ba13..a0345a0abf 100644
--- a/src/include/nodes/primnodes.h
+++ b/src/include/nodes/primnodes.h
@@ -1528,10 +1528,10 @@ typedef struct PartitionPruneStep
* where partnatts is the number of partition key columns. 'opstrategy' is the
* strategy of the operator in the clause matched to the last partition key.
* 'exprs' contains expressions which comprise the look-up key to be passed to
- * the partition bound search function. 'cmpfnids' contains the OIDs of
+ * the partition bound search function. 'cmpfns' contains the OIDs of
* comparison function used to compare aforementioned expressions with
- * partition bounds. Both 'exprs' and 'cmpfns' contain up to partnatts
- * elements.
+ * partition bounds. Both 'exprs' and 'cmpfns' contain the same number of
+ * items up to partnatts items.
*
* Once we find the offset of a partition bound using the look-up key, we
* determine which partitions to include in the result based on the value of
@@ -1563,9 +1563,9 @@ typedef struct PartitionPruneStepOp
* OpExpr clauses each containing a <> operator
*
* This is a special form of PartitionPruneStepOp, where each of the
- * expressions in 'expr' is compared using a <> operator. To prune a given
+ * expressions in 'exprs' is compared using a <> operator. To prune a given
* partition, we must check if each of the values it allows matches the value
- * of one of the expressions in 'expr' using the corresponding comparison
+ * of one of the expressions in 'exprs' using the corresponding comparison
* function in 'cmpfns'.
*
* Note: Since we must consider every possible value of the partition key a