PostgreSQL Source Code  git master
partprune.h File Reference
Include dependency graph for partprune.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  PartitionPruneContext
 

Macros

#define PruneCxtStateIdx(partnatts, step_id, keyno)   ((partnatts) * (step_id) + (keyno))
 

Typedefs

typedef struct PartitionPruneContext PartitionPruneContext
 

Functions

PartitionPruneInfomake_partition_pruneinfo (struct PlannerInfo *root, struct RelOptInfo *parentrel, List *subpaths, List *prunequal)
 
Bitmapsetprune_append_rel_partitions (struct RelOptInfo *rel)
 
Bitmapsetget_matching_partitions (PartitionPruneContext *context, List *pruning_steps)
 

Macro Definition Documentation

◆ PruneCxtStateIdx

#define PruneCxtStateIdx (   partnatts,
  step_id,
  keyno 
)    ((partnatts) * (step_id) + (keyno))

Definition at line 68 of file partprune.h.

Referenced by ExecInitPruningContext(), and perform_pruning_base_step().

Typedef Documentation

◆ PartitionPruneContext

Function Documentation

◆ get_matching_partitions()

Bitmapset* get_matching_partitions ( PartitionPruneContext context,
List pruning_steps 
)

Definition at line 819 of file partprune.c.

References Assert, bms_add_member(), bms_add_range(), bms_next_member(), PruneStepResult::bound_offsets, PartitionPruneContext::boundinfo, PartitionBoundInfoData::default_index, elog, ERROR, i, PartitionBoundInfoData::indexes, lfirst, list_length(), nodeTag, PartitionPruneContext::nparts, PartitionBoundInfoData::null_index, palloc0(), partition_bound_accepts_nulls, partition_bound_has_default, PARTITION_STRATEGY_LIST, PARTITION_STRATEGY_RANGE, perform_pruning_base_step(), perform_pruning_combine_step(), PruneStepResult::scan_default, PruneStepResult::scan_null, PartitionPruneStep::step_id, PartitionPruneContext::strategy, T_PartitionPruneStepCombine, and T_PartitionPruneStepOp.

Referenced by find_matching_subplans_recurse(), and prune_append_rel_partitions().

820 {
821  Bitmapset *result;
822  int num_steps = list_length(pruning_steps),
823  i;
824  PruneStepResult **results,
825  *final_result;
826  ListCell *lc;
827  bool scan_default;
828 
829  /* If there are no pruning steps then all partitions match. */
830  if (num_steps == 0)
831  {
832  Assert(context->nparts > 0);
833  return bms_add_range(NULL, 0, context->nparts - 1);
834  }
835 
836  /*
837  * Allocate space for individual pruning steps to store its result. Each
838  * slot will hold a PruneStepResult after performing a given pruning step.
839  * Later steps may use the result of one or more earlier steps. The
840  * result of applying all pruning steps is the value contained in the slot
841  * of the last pruning step.
842  */
843  results = (PruneStepResult **)
844  palloc0(num_steps * sizeof(PruneStepResult *));
845  foreach(lc, pruning_steps)
846  {
847  PartitionPruneStep *step = lfirst(lc);
848 
849  switch (nodeTag(step))
850  {
852  results[step->step_id] =
854  (PartitionPruneStepOp *) step);
855  break;
856 
858  results[step->step_id] =
860  (PartitionPruneStepCombine *) step,
861  results);
862  break;
863 
864  default:
865  elog(ERROR, "invalid pruning step type: %d",
866  (int) nodeTag(step));
867  }
868  }
869 
870  /*
871  * At this point we know the offsets of all the datums whose corresponding
872  * partitions need to be in the result, including special null-accepting
873  * and default partitions. Collect the actual partition indexes now.
874  */
875  final_result = results[num_steps - 1];
876  Assert(final_result != NULL);
877  i = -1;
878  result = NULL;
879  scan_default = final_result->scan_default;
880  while ((i = bms_next_member(final_result->bound_offsets, i)) >= 0)
881  {
882  int partindex;
883 
884  Assert(i < context->boundinfo->nindexes);
885  partindex = context->boundinfo->indexes[i];
886 
887  if (partindex < 0)
888  {
889  /*
890  * In range partitioning cases, if a partition index is -1 it
891  * means that the bound at the offset is the upper bound for a
892  * range not covered by any partition (other than a possible
893  * default partition). In hash partitioning, the same means no
894  * partition has been defined for the corresponding remainder
895  * value.
896  *
897  * In either case, the value is still part of the queried range of
898  * values, so mark to scan the default partition if one exists.
899  */
900  scan_default |= partition_bound_has_default(context->boundinfo);
901  continue;
902  }
903 
904  result = bms_add_member(result, partindex);
905  }
906 
907  /* Add the null and/or default partition if needed and present. */
908  if (final_result->scan_null)
909  {
912  result = bms_add_member(result, context->boundinfo->null_index);
913  }
914  if (scan_default)
915  {
917  context->strategy == PARTITION_STRATEGY_RANGE);
919  result = bms_add_member(result, context->boundinfo->default_index);
920  }
921 
922  return result;
923 }
int bms_next_member(const Bitmapset *a, int prevbit)
Definition: bitmapset.c:1043
Bitmapset * bound_offsets
Definition: partprune.c:134
static PruneStepResult * perform_pruning_combine_step(PartitionPruneContext *context, PartitionPruneStepCombine *cstep, PruneStepResult **step_results)
Definition: partprune.c:3485
Bitmapset * bms_add_range(Bitmapset *a, int lower, int upper)
Definition: bitmapset.c:834
#define ERROR
Definition: elog.h:46
static PruneStepResult * perform_pruning_base_step(PartitionPruneContext *context, PartitionPruneStepOp *opstep)
Definition: partprune.c:3337
#define partition_bound_has_default(bi)
Definition: partbounds.h:82
void * palloc0(Size size)
Definition: mcxt.c:1093
#define partition_bound_accepts_nulls(bi)
Definition: partbounds.h:81
#define Assert(condition)
Definition: c.h:804
#define lfirst(lc)
Definition: pg_list.h:169
static int list_length(const List *l)
Definition: pg_list.h:149
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:736
#define PARTITION_STRATEGY_LIST
Definition: parsenodes.h:815
#define nodeTag(nodeptr)
Definition: nodes.h:544
#define PARTITION_STRATEGY_RANGE
Definition: parsenodes.h:816
PartitionBoundInfo boundinfo
Definition: partprune.h:53
#define elog(elevel,...)
Definition: elog.h:232
int i

◆ make_partition_pruneinfo()

PartitionPruneInfo* make_partition_pruneinfo ( struct PlannerInfo root,
struct RelOptInfo parentrel,
List subpaths,
List prunequal 
)

Definition at line 222 of file partprune.c.

References add_part_relids(), PlannerInfo::append_rel_array, Assert, bms_add_member(), bms_add_range(), bms_del_members(), bms_join(), bms_num_members(), find_base_rel(), i, IS_PARTITIONED_REL, lappend(), lfirst, list_length(), make_partitionedrel_pruneinfo(), makeNode, NIL, PartitionPruneInfo::other_subplans, palloc0(), Path::parent, AppendRelInfo::parent_relid, pfree(), PartitionPruneInfo::prune_infos, RelOptInfo::relid, RELOPT_OTHER_MEMBER_REL, RelOptInfo::reloptkind, and PlannerInfo::simple_rel_array_size.

Referenced by create_append_plan(), and create_merge_append_plan().

225 {
226  PartitionPruneInfo *pruneinfo;
227  Bitmapset *allmatchedsubplans = NULL;
228  List *allpartrelids;
229  List *prunerelinfos;
230  int *relid_subplan_map;
231  ListCell *lc;
232  int i;
233 
234  /*
235  * Scan the subpaths to see which ones are scans of partition child
236  * relations, and identify their parent partitioned rels. (Note: we must
237  * restrict the parent partitioned rels to be parentrel or children of
238  * parentrel, otherwise we couldn't translate prunequal to match.)
239  *
240  * Also construct a temporary array to map from partition-child-relation
241  * relid to the index in 'subpaths' of the scan plan for that partition.
242  * (Use of "subplan" rather than "subpath" is a bit of a misnomer, but
243  * we'll let it stand.) For convenience, we use 1-based indexes here, so
244  * that zero can represent an un-filled array entry.
245  */
246  allpartrelids = NIL;
247  relid_subplan_map = palloc0(sizeof(int) * root->simple_rel_array_size);
248 
249  i = 1;
250  foreach(lc, subpaths)
251  {
252  Path *path = (Path *) lfirst(lc);
253  RelOptInfo *pathrel = path->parent;
254 
255  /* We don't consider partitioned joins here */
256  if (pathrel->reloptkind == RELOPT_OTHER_MEMBER_REL)
257  {
258  RelOptInfo *prel = pathrel;
259  Bitmapset *partrelids = NULL;
260 
261  /*
262  * Traverse up to the pathrel's topmost partitioned parent,
263  * collecting parent relids as we go; but stop if we reach
264  * parentrel. (Normally, a pathrel's topmost partitioned parent
265  * is either parentrel or a UNION ALL appendrel child of
266  * parentrel. But when handling partitionwise joins of
267  * multi-level partitioning trees, we can see an append path whose
268  * parentrel is an intermediate partitioned table.)
269  */
270  do
271  {
272  AppendRelInfo *appinfo;
273 
274  Assert(prel->relid < root->simple_rel_array_size);
275  appinfo = root->append_rel_array[prel->relid];
276  prel = find_base_rel(root, appinfo->parent_relid);
277  if (!IS_PARTITIONED_REL(prel))
278  break; /* reached a non-partitioned parent */
279  /* accept this level as an interesting parent */
280  partrelids = bms_add_member(partrelids, prel->relid);
281  if (prel == parentrel)
282  break; /* don't traverse above parentrel */
283  } while (prel->reloptkind == RELOPT_OTHER_MEMBER_REL);
284 
285  if (partrelids)
286  {
287  /*
288  * Found some relevant parent partitions, which may or may not
289  * overlap with partition trees we already found. Add new
290  * information to the allpartrelids list.
291  */
292  allpartrelids = add_part_relids(allpartrelids, partrelids);
293  /* Also record the subplan in relid_subplan_map[] */
294  /* No duplicates please */
295  Assert(relid_subplan_map[pathrel->relid] == 0);
296  relid_subplan_map[pathrel->relid] = i;
297  }
298  }
299  i++;
300  }
301 
302  /*
303  * We now build a PartitionedRelPruneInfo for each topmost partitioned rel
304  * (omitting any that turn out not to have useful pruning quals).
305  */
306  prunerelinfos = NIL;
307  foreach(lc, allpartrelids)
308  {
309  Bitmapset *partrelids = (Bitmapset *) lfirst(lc);
310  List *pinfolist;
311  Bitmapset *matchedsubplans = NULL;
312 
313  pinfolist = make_partitionedrel_pruneinfo(root, parentrel,
314  prunequal,
315  partrelids,
316  relid_subplan_map,
317  &matchedsubplans);
318 
319  /* When pruning is possible, record the matched subplans */
320  if (pinfolist != NIL)
321  {
322  prunerelinfos = lappend(prunerelinfos, pinfolist);
323  allmatchedsubplans = bms_join(matchedsubplans,
324  allmatchedsubplans);
325  }
326  }
327 
328  pfree(relid_subplan_map);
329 
330  /*
331  * If none of the partition hierarchies had any useful run-time pruning
332  * quals, then we can just not bother with run-time pruning.
333  */
334  if (prunerelinfos == NIL)
335  return NULL;
336 
337  /* Else build the result data structure */
338  pruneinfo = makeNode(PartitionPruneInfo);
339  pruneinfo->prune_infos = prunerelinfos;
340 
341  /*
342  * Some subplans may not belong to any of the identified partitioned rels.
343  * This can happen for UNION ALL queries which include a non-partitioned
344  * table, or when some of the hierarchies aren't run-time prunable. Build
345  * a bitmapset of the indexes of all such subplans, so that the executor
346  * can identify which subplans should never be pruned.
347  */
348  if (bms_num_members(allmatchedsubplans) < list_length(subpaths))
349  {
350  Bitmapset *other_subplans;
351 
352  /* Create the complement of allmatchedsubplans */
353  other_subplans = bms_add_range(NULL, 0, list_length(subpaths) - 1);
354  other_subplans = bms_del_members(other_subplans, allmatchedsubplans);
355 
356  pruneinfo->other_subplans = other_subplans;
357  }
358  else
359  pruneinfo->other_subplans = NULL;
360 
361  return pruneinfo;
362 }
#define NIL
Definition: pg_list.h:65
RelOptKind reloptkind
Definition: pathnodes.h:673
static List * make_partitionedrel_pruneinfo(PlannerInfo *root, RelOptInfo *parentrel, List *prunequal, Bitmapset *partrelids, int *relid_subplan_map, Bitmapset **matchedsubplans)
Definition: partprune.c:440
void pfree(void *pointer)
Definition: mcxt.c:1169
Bitmapset * bms_add_range(Bitmapset *a, int lower, int upper)
Definition: bitmapset.c:834
Bitmapset * bms_join(Bitmapset *a, Bitmapset *b)
Definition: bitmapset.c:949
RelOptInfo * parent
Definition: pathnodes.h:1174
int bms_num_members(const Bitmapset *a)
Definition: bitmapset.c:646
int simple_rel_array_size
Definition: pathnodes.h:186
Index relid
Definition: pathnodes.h:704
List * lappend(List *list, void *datum)
Definition: list.c:336
void * palloc0(Size size)
Definition: mcxt.c:1093
struct AppendRelInfo ** append_rel_array
Definition: pathnodes.h:201
#define makeNode(_type_)
Definition: nodes.h:587
Bitmapset * other_subplans
Definition: plannodes.h:1163
#define Assert(condition)
Definition: c.h:804
#define lfirst(lc)
Definition: pg_list.h:169
static int list_length(const List *l)
Definition: pg_list.h:149
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:736
Bitmapset * bms_del_members(Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:928
#define IS_PARTITIONED_REL(rel)
Definition: pathnodes.h:778
int i
RelOptInfo * find_base_rel(PlannerInfo *root, int relid)
Definition: relnode.c:374
Index parent_relid
Definition: pathnodes.h:2295
static List * add_part_relids(List *allpartrelids, Bitmapset *partrelids)
Definition: partprune.c:394
Definition: pg_list.h:50

◆ prune_append_rel_partitions()

Bitmapset* prune_append_rel_partitions ( struct RelOptInfo rel)

Definition at line 753 of file partprune.c.

References Assert, RelOptInfo::baserestrictinfo, bms_add_range(), PartitionPruneContext::boundinfo, RelOptInfo::boundinfo, GeneratePruningStepsContext::contradictory, CurrentMemoryContext, enable_partition_pruning, PartitionPruneContext::exprstates, gen_partprune_steps(), get_matching_partitions(), list_length(), NIL, PartitionPruneContext::nparts, RelOptInfo::nparts, palloc0(), RelOptInfo::part_scheme, PartitionPruneContext::partcollation, PartitionSchemeData::partcollation, PartitionPruneContext::partnatts, PartitionSchemeData::partnatts, PartitionPruneContext::partsupfunc, PartitionSchemeData::partsupfunc, PARTTARGET_PLANNER, PartitionPruneContext::planstate, PartitionPruneContext::ppccontext, PartitionPruneContext::stepcmpfuncs, GeneratePruningStepsContext::steps, PartitionPruneContext::strategy, and PartitionSchemeData::strategy.

Referenced by expand_partitioned_rtentry().

754 {
755  List *clauses = rel->baserestrictinfo;
756  List *pruning_steps;
758  PartitionPruneContext context;
759 
760  Assert(rel->part_scheme != NULL);
761 
762  /* If there are no partitions, return the empty set */
763  if (rel->nparts == 0)
764  return NULL;
765 
766  /*
767  * If pruning is disabled or if there are no clauses to prune with, return
768  * all partitions.
769  */
770  if (!enable_partition_pruning || clauses == NIL)
771  return bms_add_range(NULL, 0, rel->nparts - 1);
772 
773  /*
774  * Process clauses to extract pruning steps that are usable at plan time.
775  * If the clauses are found to be contradictory, we can return the empty
776  * set.
777  */
779  &gcontext);
780  if (gcontext.contradictory)
781  return NULL;
782  pruning_steps = gcontext.steps;
783 
784  /* If there's nothing usable, return all partitions */
785  if (pruning_steps == NIL)
786  return bms_add_range(NULL, 0, rel->nparts - 1);
787 
788  /* Set up PartitionPruneContext */
789  context.strategy = rel->part_scheme->strategy;
790  context.partnatts = rel->part_scheme->partnatts;
791  context.nparts = rel->nparts;
792  context.boundinfo = rel->boundinfo;
793  context.partcollation = rel->part_scheme->partcollation;
794  context.partsupfunc = rel->part_scheme->partsupfunc;
795  context.stepcmpfuncs = (FmgrInfo *) palloc0(sizeof(FmgrInfo) *
796  context.partnatts *
797  list_length(pruning_steps));
799 
800  /* These are not valid when being called from the planner */
801  context.planstate = NULL;
802  context.exprstates = NULL;
803 
804  /* Actual pruning happens here. */
805  return get_matching_partitions(&context, pruning_steps);
806 }
static void gen_partprune_steps(RelOptInfo *rel, List *clauses, PartClauseTarget target, GeneratePruningStepsContext *context)
Definition: partprune.c:717
#define NIL
Definition: pg_list.h:65
Definition: fmgr.h:56
FmgrInfo * partsupfunc
Definition: partprune.h:55
FmgrInfo * stepcmpfuncs
Definition: partprune.h:56
MemoryContext ppccontext
Definition: partprune.h:57
List * baserestrictinfo
Definition: pathnodes.h:740
Bitmapset * bms_add_range(Bitmapset *a, int lower, int upper)
Definition: bitmapset.c:834
ExprState ** exprstates
Definition: partprune.h:59
int nparts
Definition: pathnodes.h:756
MemoryContext CurrentMemoryContext
Definition: mcxt.c:42
void * palloc0(Size size)
Definition: mcxt.c:1093
struct PartitionBoundInfoData * boundinfo
Definition: pathnodes.h:759
bool enable_partition_pruning
Definition: costsize.c:151
#define Assert(condition)
Definition: c.h:804
struct FmgrInfo * partsupfunc
Definition: pathnodes.h:414
static int list_length(const List *l)
Definition: pg_list.h:149
PartitionBoundInfo boundinfo
Definition: partprune.h:53
Bitmapset * get_matching_partitions(PartitionPruneContext *context, List *pruning_steps)
Definition: partprune.c:819
PartitionScheme part_scheme
Definition: pathnodes.h:755
Definition: pg_list.h:50
PlanState * planstate
Definition: partprune.h:58