generate_PartitionClauseInfos_for_or_clauses.patch
application/octet-stream
Filename: generate_PartitionClauseInfos_for_or_clauses.patch
Type: application/octet-stream
Part: 0
Patch
Format: unified
| File | + | − |
|---|---|---|
| src/backend/executor/nodeAppend.c | 5 | 3 |
| src/backend/optimizer/util/partprune.c | 101 | 73 |
| src/include/optimizer/partprune.h | 8 | 3 |
diff --git a/src/backend/executor/nodeAppend.c b/src/backend/executor/nodeAppend.c
index 7171682..7658906 100644
--- a/src/backend/executor/nodeAppend.c
+++ b/src/backend/executor/nodeAppend.c
@@ -83,6 +83,7 @@ struct ParallelAppendState
struct PartitionPruneContextCache
{
PartitionPruneContext *context;
+ PartitionClauseInfo *partclauseinfo;
PartitionPruneContextCache *subcache;
};
@@ -714,7 +715,7 @@ set_valid_runtime_subplans_recurse(AppendState *node,
context->econtext = node->ps.ps_ExprContext;
context->paramids = NULL;
- generate_partition_clauses(context, pinfo->prunequal);
+ ctxcache->partclauseinfo = generate_partition_clauses(context, pinfo->prunequal);
node->part_prune_params = bms_add_members(node->part_prune_params,
context->paramids);
@@ -730,7 +731,7 @@ set_valid_runtime_subplans_recurse(AppendState *node,
* Detect if any impossibilities were discovered during
* generate_partition_clauses
*/
- if (context->clauseinfo->constfalse)
+ if (ctxcache->partclauseinfo->constfalse)
{
bms_free(*validsubplans);
*validsubplans = NULL;
@@ -747,7 +748,8 @@ set_valid_runtime_subplans_recurse(AppendState *node,
* params.
*/
if (!bms_is_empty(context->paramids))
- partset = get_partitions_from_clauses(context);
+ partset = get_partitions_from_clauses(context,
+ ctxcache->partclauseinfo);
else
partset = pinfo->allsubnodes;
diff --git a/src/backend/optimizer/util/partprune.c b/src/backend/optimizer/util/partprune.c
index 81f66bf..010333e 100644
--- a/src/backend/optimizer/util/partprune.c
+++ b/src/backend/optimizer/util/partprune.c
@@ -24,21 +24,19 @@
* pruning from a list of clauses containing clauses that reference a given
* partitioned table. For example, prune_append_rel_partitions() calls this
* function, because a partitioned table's rel->baserestrictinfo may contain
- * clauses that might be useful for partitioning. Caller must have set up a
- * valid partition pruning context in the form of struct PartitionPruneContext,
- * that is, each of its fields other other than clauseinfo must be valid before
- * calling here. After extracting relevant clauses, clauseinfo is filled with
- * information that will be used for actual pruning.
+ * clauses that might be useful for partitioning. The list of clauses is
+ * processed and a PartitionClauseInfo is returned which contains details of
+ * any clauses which could be matched to the partition keys of the relation
+ * defined in the context.
*
* get_partitions_from_clauses()
*
- * This is to be called to prune partitions based on relevant partitioning
- * clauses. Caller must have called generate_partition_clauses() at least
- * once and hence a valid partition pruning context must have already been
- * created. Especially, PartitionPruneContext.clauseinfo must contain valid
- * information. Partition pruning proceeds by extracting constant values
- * from the clauses and comparing it with the partition bounds while also
- * taking into account strategies of the operators in the matched clauses.
+ * This is to be called to prune partitions based on 'partclauseinfo'. Caller
+ * must have called generate_partition_clauses() in order to have generated
+ * a valid PartitionClauseInfo. Partition pruning proceeds by extracting
+ * constant values from the clauses and comparing it with the partition bounds
+ * while also taking into account strategies of the operators in the matched
+ * clauses.
*
* make_partition_pruneinfo()
*
@@ -104,18 +102,22 @@ typedef enum PartOpStrategy
PART_OP_GREATER
} PartOpStrategy;
-static void extract_partition_clauses(PartitionPruneContext *context,
- List *clauses);
+static PartitionClauseInfo *extract_partition_clauses(
+ PartitionPruneContext *context,
+ List *clauses);
static bool match_boolean_partition_clause(Expr *clause, Expr *partkey,
Expr **rightop);
static Bitmapset *get_partitions_from_or_args(PartitionPruneContext *context,
- List *or_args);
+ List *or_args,
+ List *or_partclauselist);
static void remove_redundant_clauses(PartitionPruneContext *context,
+ PartitionClauseInfo *partclauseinfo,
List **minimalclauses);
static bool partition_cmp_args(PartitionPruneContext *context, Oid parttypid,
Oid partopfamily, PartClause *pc, PartClause *leftarg,
PartClause *rightarg, bool *result);
static bool extract_bounding_datums(PartitionPruneContext *context,
+ PartitionClauseInfo *clauseinfo,
List **minimalclauses, PartScanKeyInfo *keys);
static PartOpStrategy partition_op_strategy(char part_strategy,
PartClause *pc, bool *incl);
@@ -144,6 +146,7 @@ prune_append_rel_partitions(PlannerInfo *root, RelOptInfo *rel)
else
{
PartitionPruneContext context;
+ PartitionClauseInfo *partclauseinfo;
int partnatts = rel->part_scheme->partnatts,
i;
@@ -168,13 +171,16 @@ prune_append_rel_partitions(PlannerInfo *root, RelOptInfo *rel)
context.econtext = NULL;
context.paramids = NULL;
- /* process clauses; context.clauseinfo will be set */
- generate_partition_clauses(&context, clauses);
+ /* process clauses */
+ partclauseinfo = generate_partition_clauses(&context, clauses);
- if (!context.clauseinfo->constfalse)
+ if (!partclauseinfo->constfalse)
{
/* Actual pruning happens here. */
- Bitmapset *partindexes = get_partitions_from_clauses(&context);
+ Bitmapset *partindexes;
+
+ partindexes = get_partitions_from_clauses(&context,
+ partclauseinfo);
/* Add selected partitions' RT indexes to result. */
i = -1;
@@ -188,13 +194,10 @@ prune_append_rel_partitions(PlannerInfo *root, RelOptInfo *rel)
/*
* generate_partition_clauses
- * Analyzes clauses to find those that match the partition key and sets
- * context->clauseinfo
- *
- * Ideally, this should be called only once for a given query and a given
- * partitioned table.
+ * Processes 'clauses' and returns a PartitionClauseInfo which contains
+ * the details of any clauses which were matched to partition keys.
*/
-void
+PartitionClauseInfo *
generate_partition_clauses(PartitionPruneContext *context, List *clauses)
{
/* The clauses list may be modified below, so better make a copy. */
@@ -227,25 +230,26 @@ generate_partition_clauses(PartitionPruneContext *context, List *clauses)
clauses = list_concat(clauses, partqual);
}
- /* And away we go to do the real work; context->clauseinfo will be set */
- extract_partition_clauses(context, clauses);
+ /* pre-process the clauses and generate the PartitionClauseInfo */
+ return extract_partition_clauses(context, clauses);
}
/*
* get_partitions_from_clauses
* Determine partitions that could possible contain a record that
- * satisfies clauses as described in context->clauseinfo
+ * satisfies clauses as described in partclauseinfo
*
* Returns a Bitmapset of the matching partition indexes, or NULL if none can
* match.
*/
Bitmapset *
-get_partitions_from_clauses(PartitionPruneContext *context)
+get_partitions_from_clauses(PartitionPruneContext *context,
+ PartitionClauseInfo *partclauseinfo)
{
- PartitionClauseInfo *partclauseinfo = context->clauseinfo;
PartScanKeyInfo keys;
Bitmapset *result;
- ListCell *lc;
+ ListCell *lc;
+ ListCell *lc2;
Assert(partclauseinfo != NULL);
Assert(!partclauseinfo->constfalse);
@@ -260,17 +264,18 @@ get_partitions_from_clauses(PartitionPruneContext *context)
List *minimalclauses[PARTITION_MAX_KEYS];
/*
- * For each partition key column, populate its slot in minimalclauses
- * with the most restrictive of the clauses from the corresponding
- * list in context->clauseinfo.
+ * For each partition key column, populate its element in
+ * minimalclauses with the most restrictive set of the clauses from
+ * the corresponding partition key in partclauseinfo.
*/
- remove_redundant_clauses(context, minimalclauses);
+ remove_redundant_clauses(context, partclauseinfo, minimalclauses);
/* Did remove_redundant_clauses find any contradicting clauses? */
if (partclauseinfo->constfalse)
return NULL;
- if (extract_bounding_datums(context, minimalclauses, &keys))
+ if (extract_bounding_datums(context, partclauseinfo, minimalclauses,
+ &keys))
{
result = get_partitions_for_keys(context, &keys);
@@ -292,12 +297,14 @@ get_partitions_from_clauses(PartitionPruneContext *context)
}
/* Now apply the OR clauses. */
- foreach(lc, partclauseinfo->or_clauses)
+ forboth(lc, partclauseinfo->or_clauses, lc2,
+ partclauseinfo->or_partclauseinfos)
{
List *or_args = (List *) lfirst(lc);
+ List *or_partclauselist = lfirst(lc2);
Bitmapset *or_parts;
- or_parts = get_partitions_from_or_args(context, or_args);
+ or_parts = get_partitions_from_or_args(context, or_args, or_partclauselist);
/*
* Clauses in or_clauses are mutually conjunctive and also in
@@ -327,26 +334,27 @@ get_partitions_from_clauses(PartitionPruneContext *context)
/*
* extract_partition_clauses
* Processes 'clauses' to extract clause matching the partition key.
- * This adds matched clauses to the list corresponding to particular key
- * in context->clauseinfo. Also collects other useful clauses to assist
- * in partition elimination, such as OR clauses, clauses containing <>
- * operator, and IS [NOT] NULL clauses
+ * Returns a PartitionClauseInfo which stores the clauses which were
+ * matched to the partition key. The PartitionClauseInfo also collects
+ * other useful clauses to assist in partition elimination, such as OR
+ * clauses, clauses containing <> operator, and IS [NOT] NULL clauses
*
* We may also discover some contradiction in the clauses which means that no
- * partition can possibly match. In this case, the function sets
- * context->clauseinfo's 'constfalse' to true and exits immediately without
- * processing any further clauses. In this case, the caller must be careful
- * not to assume the context->clauseinfo is fully populated with all clauses.
+ * partition can possibly match. In this case, the function sets the
+ * returned PartitionClauseInfo's 'constfalse' to true and exits immediately
+ * without processing any further clauses. In this case, the caller must be
+ * careful not to assume the return value is fully populated with all clauses.
*/
-static void
+static PartitionClauseInfo *
extract_partition_clauses(PartitionPruneContext *context, List *clauses)
{
PartitionClauseInfo *partclauseinfo;
ListCell *lc;
- context->clauseinfo = partclauseinfo = palloc(sizeof(PartitionClauseInfo));
+ partclauseinfo = palloc(sizeof(PartitionClauseInfo));
memset(partclauseinfo->keyclauses, 0, sizeof(partclauseinfo->keyclauses));
partclauseinfo->or_clauses = NIL;
+ partclauseinfo->or_partclauseinfos = NIL;
partclauseinfo->ne_clauses = NIL;
partclauseinfo->keyisnull = NULL;
partclauseinfo->keyisnotnull = NULL;
@@ -367,7 +375,7 @@ extract_partition_clauses(PartitionPruneContext *context, List *clauses)
!DatumGetBool(((Const *) clause)->constvalue))
{
partclauseinfo->constfalse = true;
- return;
+ return partclauseinfo;
}
}
@@ -558,7 +566,7 @@ extract_partition_clauses(PartitionPruneContext *context, List *clauses)
if (bms_is_member(i, partclauseinfo->keyisnull))
{
partclauseinfo->constfalse = true;
- return;
+ return partclauseinfo;
}
/* Record that a strict clause has been seen for this key */
partclauseinfo->keyisnotnull =
@@ -734,7 +742,7 @@ extract_partition_clauses(PartitionPruneContext *context, List *clauses)
if (bms_is_member(i, partclauseinfo->keyisnotnull))
{
partclauseinfo->constfalse = true;
- return;
+ return partclauseinfo;
}
partclauseinfo->keyisnull =
bms_add_member(partclauseinfo->keyisnull,
@@ -746,7 +754,7 @@ extract_partition_clauses(PartitionPruneContext *context, List *clauses)
if (bms_is_member(i, partclauseinfo->keyisnull))
{
partclauseinfo->constfalse = true;
- return;
+ return partclauseinfo;
}
partclauseinfo->keyisnotnull =
@@ -760,6 +768,31 @@ extract_partition_clauses(PartitionPruneContext *context, List *clauses)
partclauseinfo->foundkeyclauses = true;
}
}
+
+ /*
+ * Now pre-process any OR clauses found above and generate
+ * PartitionClauseInfos for them.
+ */
+ foreach(lc, partclauseinfo->or_clauses)
+ {
+ List *or_args = lfirst(lc);
+ List *pclauselist = NIL;
+ ListCell *lc2;
+
+ foreach (lc2, or_args)
+ {
+ List *clauses = list_make1(lfirst(lc2));
+ PartitionClauseInfo *orpartclauseinfo;
+
+ orpartclauseinfo = extract_partition_clauses(context, clauses);
+ pclauselist = lappend(pclauselist, orpartclauseinfo);
+ }
+
+ partclauseinfo->or_partclauseinfos =
+ lappend(partclauseinfo->or_partclauseinfos, pclauselist);
+ }
+
+ return partclauseinfo;
}
/*
@@ -829,10 +862,11 @@ match_boolean_partition_clause(Expr *clause, Expr *partkey,
* clause in or_args.
*/
static Bitmapset *
-get_partitions_from_or_args(PartitionPruneContext *context, List *or_args)
+get_partitions_from_or_args(PartitionPruneContext *context, List *or_args,
+ List *or_partclauselist)
{
Bitmapset *result = NULL;
- ListCell *lc;
+ ListCell *lc, *lc2;
/*
* When matching an OR expression, it is only checked if at least one of
@@ -843,20 +877,13 @@ get_partitions_from_or_args(PartitionPruneContext *context, List *or_args)
* clause refutes its partition constraint, that is, we can eliminate all
* of its partitions.
*/
- foreach(lc, or_args)
+ forboth(lc, or_args, lc2, or_partclauselist)
{
List *clauses = list_make1(lfirst(lc));
- PartitionPruneContext subcontext;
+ PartitionClauseInfo *or_pclause = lfirst(lc2);
Bitmapset *arg_partset;
- /*
- * All fields except clauseinfo are same as in the parent context,
- * which will be set by calling extract_partition_clauses().
- */
- memcpy(&subcontext, context, sizeof(PartitionPruneContext));
- extract_partition_clauses(&subcontext, clauses);
-
- if (!subcontext.clauseinfo->foundkeyclauses)
+ if (!or_pclause->foundkeyclauses)
{
List *partconstr = context->partition_qual;
@@ -873,8 +900,8 @@ get_partitions_from_or_args(PartitionPruneContext *context, List *or_args)
return bms_add_range(NULL, 0, context->nparts - 1);
}
- if (!subcontext.clauseinfo->constfalse)
- arg_partset = get_partitions_from_clauses(&subcontext);
+ if (!or_pclause->constfalse)
+ arg_partset = get_partitions_from_clauses(context, or_pclause);
else
arg_partset = NULL;
@@ -887,8 +914,8 @@ get_partitions_from_or_args(PartitionPruneContext *context, List *or_args)
/*
* remove_redundant_clauses
- * Processes the clauses contained in context->clauseinfo to remove the
- * ones that are superseeded by other clauses which are more restrictive.
+ * Process 'partpruneinfo' to remove the clauses that are superseeded
+ * by other clauses which are more restrictive.
*
* Finished lists of clauses are returned in *minimalclauses which is an array
* with one slot for each of the partition keys.
@@ -900,16 +927,16 @@ get_partitions_from_or_args(PartitionPruneContext *context, List *or_args)
* that the clauses cannot possibly match any partition. Impossible clauses
* include things like: x = 1 AND x = 2, x > 0 and x < 10. The function
* returns right after finding such a clause and before returning, sets
- * constfalse in context->clauseinfo to inform the caller that we found such
+ * constfalse in 'partclauseinfo' to inform the caller that we found such
* clause.
*/
static void
remove_redundant_clauses(PartitionPruneContext *context,
+ PartitionClauseInfo *partclauseinfo,
List **minimalclauses)
{
PartClause *hash_clause,
*btree_clauses[BTMaxStrategyNumber];
- PartitionClauseInfo *partclauseinfo = context->clauseinfo;
ListCell *lc;
int s;
int i;
@@ -1220,8 +1247,9 @@ partition_cmp_args(PartitionPruneContext *context, Oid parttypid,
/*
* extract_bounding_datums
- * Process clauses in context->clauseinfo and populate 'keys' with all
- * min/max/equal/not-equal values that we're able to determine.
+ * Process 'clauseinfo' and populate 'keys' with all
+ * min/max/equal/not-equal values that we're able to
+ * determine.
*
* *minimalclauses is an array with partnatts members, each of which is a list
* of the most restrictive clauses of each operator strategy for the given
@@ -1237,9 +1265,9 @@ partition_cmp_args(PartitionPruneContext *context, Oid parttypid,
*/
static bool
extract_bounding_datums(PartitionPruneContext *context,
+ PartitionClauseInfo *clauseinfo,
List **minimalclauses, PartScanKeyInfo *keys)
{
- PartitionClauseInfo *clauseinfo = context->clauseinfo;
bool need_next_eq,
need_next_min,
need_next_max;
diff --git a/src/include/optimizer/partprune.h b/src/include/optimizer/partprune.h
index a761e65..ff68d4a 100644
--- a/src/include/optimizer/partprune.h
+++ b/src/include/optimizer/partprune.h
@@ -39,6 +39,9 @@ typedef struct PartitionClauseInfo
/* Each members is a List itself of a given OR clauses's arguments. */
List *or_clauses;
+ /* each OR clause processed into a PartitionClauseInfo */
+ List *or_partclauseinfos;
+
/* List of clauses containing <> operator. */
List *ne_clauses;
@@ -55,9 +58,11 @@ typedef struct PartitionClauseInfo
extern Relids prune_append_rel_partitions(PlannerInfo *root,
RelOptInfo *rel);
-extern void generate_partition_clauses(PartitionPruneContext *context,
- List *clauses);
-extern Bitmapset *get_partitions_from_clauses(PartitionPruneContext *context);
+extern PartitionClauseInfo *generate_partition_clauses(
+ PartitionPruneContext *context,
+ List *clauses);
+extern Bitmapset *get_partitions_from_clauses(PartitionPruneContext *context,
+ PartitionClauseInfo *partclauseinfo);
extern PartitionPruneInfo *make_partition_pruneinfo(PlannerInfo *root,
RelOptInfo *rel,