PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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 846 of file partprune.c.

847{
848 Bitmapset *result;
849 int num_steps = list_length(pruning_steps),
850 i;
851 PruneStepResult **results,
852 *final_result;
853 ListCell *lc;
854 bool scan_default;
855
856 /* If there are no pruning steps then all partitions match. */
857 if (num_steps == 0)
858 {
859 Assert(context->nparts > 0);
860 return bms_add_range(NULL, 0, context->nparts - 1);
861 }
862
863 /*
864 * Allocate space for individual pruning steps to store its result. Each
865 * slot will hold a PruneStepResult after performing a given pruning step.
866 * Later steps may use the result of one or more earlier steps. The
867 * result of applying all pruning steps is the value contained in the slot
868 * of the last pruning step.
869 */
870 results = (PruneStepResult **)
871 palloc0(num_steps * sizeof(PruneStepResult *));
872 foreach(lc, pruning_steps)
873 {
874 PartitionPruneStep *step = lfirst(lc);
875
876 switch (nodeTag(step))
877 {
878 case T_PartitionPruneStepOp:
879 results[step->step_id] =
881 (PartitionPruneStepOp *) step);
882 break;
883
884 case T_PartitionPruneStepCombine:
885 results[step->step_id] =
888 results);
889 break;
890
891 default:
892 elog(ERROR, "invalid pruning step type: %d",
893 (int) nodeTag(step));
894 }
895 }
896
897 /*
898 * At this point we know the offsets of all the datums whose corresponding
899 * partitions need to be in the result, including special null-accepting
900 * and default partitions. Collect the actual partition indexes now.
901 */
902 final_result = results[num_steps - 1];
903 Assert(final_result != NULL);
904 i = -1;
905 result = NULL;
906 scan_default = final_result->scan_default;
907 while ((i = bms_next_member(final_result->bound_offsets, i)) >= 0)
908 {
909 int partindex;
910
911 Assert(i < context->boundinfo->nindexes);
912 partindex = context->boundinfo->indexes[i];
913
914 if (partindex < 0)
915 {
916 /*
917 * In range partitioning cases, if a partition index is -1 it
918 * means that the bound at the offset is the upper bound for a
919 * range not covered by any partition (other than a possible
920 * default partition). In hash partitioning, the same means no
921 * partition has been defined for the corresponding remainder
922 * value.
923 *
924 * In either case, the value is still part of the queried range of
925 * values, so mark to scan the default partition if one exists.
926 */
927 scan_default |= partition_bound_has_default(context->boundinfo);
928 continue;
929 }
930
931 result = bms_add_member(result, partindex);
932 }
933
934 /* Add the null and/or default partition if needed and present. */
935 if (final_result->scan_null)
936 {
939 result = bms_add_member(result, context->boundinfo->null_index);
940 }
941 if (scan_default)
942 {
946 result = bms_add_member(result, context->boundinfo->default_index);
947 }
948
949 return result;
950}
int bms_next_member(const Bitmapset *a, int prevbit)
Definition: bitmapset.c:1306
Bitmapset * bms_add_range(Bitmapset *a, int lower, int upper)
Definition: bitmapset.c:1019
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:815
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:226
Assert(PointerIsAligned(start, uint64))
int i
Definition: isn.c:77
void * palloc0(Size size)
Definition: mcxt.c:1969
#define nodeTag(nodeptr)
Definition: nodes.h:139
@ PARTITION_STRATEGY_LIST
Definition: parsenodes.h:883
@ PARTITION_STRATEGY_RANGE
Definition: parsenodes.h:884
#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:3444
static PruneStepResult * perform_pruning_combine_step(PartitionPruneContext *context, PartitionPruneStepCombine *cstep, PruneStepResult **step_results)
Definition: partprune.c:3592
#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:133

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 224 of file partprune.c.

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

References add_part_relids(), Assert(), bms_add_member(), bms_add_range(), bms_copy(), 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, pfree(), PartitionPruneInfo::prune_infos, RelOptInfo::relid, RelOptInfo::relids, PartitionPruneInfo::relids, RELOPT_OTHER_MEMBER_REL, RelOptInfo::reloptkind, and root.

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 779 of file partprune.c.

780{
781 List *clauses = rel->baserestrictinfo;
782 List *pruning_steps;
784 PartitionPruneContext context;
785
786 Assert(rel->part_scheme != NULL);
787
788 /* If there are no partitions, return the empty set */
789 if (rel->nparts == 0)
790 return NULL;
791
792 /*
793 * If pruning is disabled or if there are no clauses to prune with, return
794 * all partitions.
795 */
796 if (!enable_partition_pruning || clauses == NIL)
797 return bms_add_range(NULL, 0, rel->nparts - 1);
798
799 /*
800 * Process clauses to extract pruning steps that are usable at plan time.
801 * If the clauses are found to be contradictory, we can return the empty
802 * set.
803 */
805 &gcontext);
806 if (gcontext.contradictory)
807 return NULL;
808 pruning_steps = gcontext.steps;
809
810 /* If there's nothing usable, return all partitions */
811 if (pruning_steps == NIL)
812 return bms_add_range(NULL, 0, rel->nparts - 1);
813
814 /* Set up PartitionPruneContext */
815 context.strategy = rel->part_scheme->strategy;
816 context.partnatts = rel->part_scheme->partnatts;
817 context.nparts = rel->nparts;
818 context.boundinfo = rel->boundinfo;
819 context.partcollation = rel->part_scheme->partcollation;
820 context.partsupfunc = rel->part_scheme->partsupfunc;
821 context.stepcmpfuncs = (FmgrInfo *) palloc0(sizeof(FmgrInfo) *
822 context.partnatts *
823 list_length(pruning_steps));
825
826 /* These are not valid when being called from the planner */
827 context.planstate = NULL;
828 context.exprcontext = NULL;
829 context.exprstates = NULL;
830
831 /* Actual pruning happens here. */
832 return get_matching_partitions(&context, pruning_steps);
833}
bool enable_partition_pruning
Definition: costsize.c:163
MemoryContext CurrentMemoryContext
Definition: mcxt.c:159
Bitmapset * get_matching_partitions(PartitionPruneContext *context, List *pruning_steps)
Definition: partprune.c:846
@ PARTTARGET_PLANNER
Definition: partprune.c:93
static void gen_partprune_steps(RelOptInfo *rel, List *clauses, PartClauseTarget target, GeneratePruningStepsContext *context)
Definition: partprune.c:743
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:1012

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().