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

int make_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 70 of file partprune.h.

Typedef Documentation

◆ PartitionPruneContext

Function Documentation

◆ get_matching_partitions()

Bitmapset* get_matching_partitions ( PartitionPruneContext context,
List pruning_steps 
)

Definition at line 826 of file partprune.c.

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

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, and PartitionPruneContext::strategy.

Referenced by find_matching_subplans_recurse(), and prune_append_rel_partitions().

◆ make_partition_pruneinfo()

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

Definition at line 226 of file partprune.c.

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

References add_part_relids(), 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(), AppendRelInfo::parent_relid, PlannerInfo::partPruneInfos, pfree(), PartitionPruneInfo::prune_infos, RelOptInfo::relid, RelOptInfo::relids, RELOPT_OTHER_MEMBER_REL, RelOptInfo::reloptkind, PartitionPruneInfo::root_parent_relids, and PlannerInfo::simple_rel_array_size.

Referenced by create_append_plan(), and create_merge_append_plan().

◆ prune_append_rel_partitions()

Bitmapset* prune_append_rel_partitions ( struct RelOptInfo rel)

Definition at line 759 of file partprune.c.

760 {
761  List *clauses = rel->baserestrictinfo;
762  List *pruning_steps;
764  PartitionPruneContext context;
765 
766  Assert(rel->part_scheme != NULL);
767 
768  /* If there are no partitions, return the empty set */
769  if (rel->nparts == 0)
770  return NULL;
771 
772  /*
773  * If pruning is disabled or if there are no clauses to prune with, return
774  * all partitions.
775  */
776  if (!enable_partition_pruning || clauses == NIL)
777  return bms_add_range(NULL, 0, rel->nparts - 1);
778 
779  /*
780  * Process clauses to extract pruning steps that are usable at plan time.
781  * If the clauses are found to be contradictory, we can return the empty
782  * set.
783  */
785  &gcontext);
786  if (gcontext.contradictory)
787  return NULL;
788  pruning_steps = gcontext.steps;
789 
790  /* If there's nothing usable, return all partitions */
791  if (pruning_steps == NIL)
792  return bms_add_range(NULL, 0, rel->nparts - 1);
793 
794  /* Set up PartitionPruneContext */
795  context.strategy = rel->part_scheme->strategy;
796  context.partnatts = rel->part_scheme->partnatts;
797  context.nparts = rel->nparts;
798  context.boundinfo = rel->boundinfo;
799  context.partcollation = rel->part_scheme->partcollation;
800  context.partsupfunc = rel->part_scheme->partsupfunc;
801  context.stepcmpfuncs = (FmgrInfo *) palloc0(sizeof(FmgrInfo) *
802  context.partnatts *
803  list_length(pruning_steps));
805 
806  /* These are not valid when being called from the planner */
807  context.planstate = NULL;
808  context.exprcontext = NULL;
809  context.exprstates = NULL;
810 
811  /* Actual pruning happens here. */
812  return get_matching_partitions(&context, pruning_steps);
813 }
bool enable_partition_pruning
Definition: costsize.c:153
MemoryContext CurrentMemoryContext
Definition: mcxt.c:135
Bitmapset * get_matching_partitions(PartitionPruneContext *context, List *pruning_steps)
Definition: partprune.c:826
@ PARTTARGET_PLANNER
Definition: partprune.c:94
static void gen_partprune_steps(RelOptInfo *rel, List *clauses, PartClauseTarget target, GeneratePruningStepsContext *context)
Definition: partprune.c:723
Definition: fmgr.h:57
FmgrInfo * partsupfunc
Definition: partprune.h:56
ExprContext * exprcontext
Definition: partprune.h:60
MemoryContext ppccontext
Definition: partprune.h:58
PlanState * planstate
Definition: partprune.h:59
FmgrInfo * stepcmpfuncs
Definition: partprune.h:57
ExprState ** exprstates
Definition: partprune.h:61
List * baserestrictinfo
Definition: pathnodes.h:974

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

Referenced by expand_partitioned_rtentry().