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

Go to the source code of this file.

Data Structures

struct  PartitionedRelPruningData
 
struct  PartitionPruningData
 
struct  PartitionPruneState
 

Typedefs

typedef struct PartitionDispatchDataPartitionDispatch
 
typedef struct PartitionTupleRouting PartitionTupleRouting
 
typedef struct PartitionedRelPruningData PartitionedRelPruningData
 
typedef struct PartitionPruningData PartitionPruningData
 
typedef struct PartitionPruneState PartitionPruneState
 

Functions

PartitionTupleRoutingExecSetupPartitionTupleRouting (EState *estate, Relation rel)
 
ResultRelInfoExecFindPartition (ModifyTableState *mtstate, ResultRelInfo *rootResultRelInfo, PartitionTupleRouting *proute, TupleTableSlot *slot, EState *estate)
 
void ExecCleanupTupleRouting (ModifyTableState *mtstate, PartitionTupleRouting *proute)
 
void ExecDoInitialPruning (EState *estate)
 
PartitionPruneStateExecInitPartitionExecPruning (PlanState *planstate, int n_total_subplans, int part_prune_index, Bitmapset *relids, Bitmapset **initially_valid_subplans)
 
BitmapsetExecFindMatchingSubPlans (PartitionPruneState *prunestate, bool initial_prune, Bitmapset **validsubplan_rtis)
 

Typedef Documentation

◆ PartitionDispatch

Definition at line 22 of file execPartition.h.

◆ PartitionedRelPruningData

◆ PartitionPruneState

◆ PartitionPruningData

◆ PartitionTupleRouting

Definition at line 23 of file execPartition.h.

Function Documentation

◆ ExecCleanupTupleRouting()

void ExecCleanupTupleRouting ( ModifyTableState mtstate,
PartitionTupleRouting proute 
)

Definition at line 1374 of file execPartition.c.

1376{
1377 int i;
1378
1379 /*
1380 * Remember, proute->partition_dispatch_info[0] corresponds to the root
1381 * partitioned table, which we must not try to close, because it is the
1382 * main target table of the query that will be closed by callers such as
1383 * ExecEndPlan() or DoCopy(). Also, tupslot is NULL for the root
1384 * partitioned table.
1385 */
1386 for (i = 1; i < proute->num_dispatch; i++)
1387 {
1389
1391
1392 if (pd->tupslot)
1394 }
1395
1396 for (i = 0; i < proute->num_partitions; i++)
1397 {
1398 ResultRelInfo *resultRelInfo = proute->partitions[i];
1399
1400 /* Allow any FDWs to shut down */
1401 if (resultRelInfo->ri_FdwRoutine != NULL &&
1402 resultRelInfo->ri_FdwRoutine->EndForeignInsert != NULL)
1403 resultRelInfo->ri_FdwRoutine->EndForeignInsert(mtstate->ps.state,
1404 resultRelInfo);
1405
1406 /*
1407 * Close it if it's not one of the result relations borrowed from the
1408 * owning ModifyTableState; those will be closed by ExecEndPlan().
1409 */
1410 if (proute->is_borrowed_rel[i])
1411 continue;
1412
1413 ExecCloseIndices(resultRelInfo);
1414 table_close(resultRelInfo->ri_RelationDesc, NoLock);
1415 }
1416}
void ExecCloseIndices(ResultRelInfo *resultRelInfo)
Definition: execIndexing.c:239
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
Definition: execTuples.c:1443
int i
Definition: isn.c:77
#define NoLock
Definition: lockdefs.h:34
EndForeignInsert_function EndForeignInsert
Definition: fdwapi.h:239
PlanState ps
Definition: execnodes.h:1403
TupleTableSlot * tupslot
PartitionDispatch * partition_dispatch_info
Definition: execPartition.c:95
ResultRelInfo ** partitions
Definition: execPartition.c:99
EState * state
Definition: execnodes.h:1167
Relation ri_RelationDesc
Definition: execnodes.h:480
struct FdwRoutine * ri_FdwRoutine
Definition: execnodes.h:533
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126

References FdwRoutine::EndForeignInsert, ExecCloseIndices(), ExecDropSingleTupleTableSlot(), i, PartitionTupleRouting::is_borrowed_rel, NoLock, PartitionTupleRouting::num_dispatch, PartitionTupleRouting::num_partitions, PartitionTupleRouting::partition_dispatch_info, PartitionTupleRouting::partitions, ModifyTableState::ps, PartitionDispatchData::reldesc, ResultRelInfo::ri_FdwRoutine, ResultRelInfo::ri_RelationDesc, PlanState::state, table_close(), and PartitionDispatchData::tupslot.

Referenced by CopyFrom(), ExecEndModifyTable(), and finish_edata().

◆ ExecDoInitialPruning()

void ExecDoInitialPruning ( EState estate)

Definition at line 1957 of file execPartition.c.

1958{
1959 ListCell *lc;
1960
1961 foreach(lc, estate->es_part_prune_infos)
1962 {
1964 PartitionPruneState *prunestate;
1965 Bitmapset *validsubplans = NULL;
1966 Bitmapset *all_leafpart_rtis = NULL;
1967 Bitmapset *validsubplan_rtis = NULL;
1968
1969 /* Create and save the PartitionPruneState. */
1970 prunestate = CreatePartitionPruneState(estate, pruneinfo,
1971 &all_leafpart_rtis);
1973 prunestate);
1974
1975 /*
1976 * Perform initial pruning steps, if any, and save the result
1977 * bitmapset or NULL as described in the header comment.
1978 */
1979 if (prunestate->do_initial_prune)
1980 validsubplans = ExecFindMatchingSubPlans(prunestate, true,
1981 &validsubplan_rtis);
1982 else
1983 validsubplan_rtis = all_leafpart_rtis;
1984
1986 validsubplan_rtis);
1988 validsubplans);
1989 }
1990}
Bitmapset * bms_add_members(Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:916
Bitmapset * ExecFindMatchingSubPlans(PartitionPruneState *prunestate, bool initial_prune, Bitmapset **validsubplan_rtis)
static PartitionPruneState * CreatePartitionPruneState(EState *estate, PartitionPruneInfo *pruneinfo, Bitmapset **all_leafpart_rtis)
List * lappend(List *list, void *datum)
Definition: list.c:339
#define lfirst_node(type, lc)
Definition: pg_list.h:176
List * es_part_prune_infos
Definition: execnodes.h:670
Bitmapset * es_unpruned_relids
Definition: execnodes.h:673
List * es_part_prune_states
Definition: execnodes.h:671
List * es_part_prune_results
Definition: execnodes.h:672

References bms_add_members(), CreatePartitionPruneState(), PartitionPruneState::do_initial_prune, EState::es_part_prune_infos, EState::es_part_prune_results, EState::es_part_prune_states, EState::es_unpruned_relids, ExecFindMatchingSubPlans(), lappend(), and lfirst_node.

Referenced by InitPlan().

◆ ExecFindMatchingSubPlans()

Bitmapset * ExecFindMatchingSubPlans ( PartitionPruneState prunestate,
bool  initial_prune,
Bitmapset **  validsubplan_rtis 
)

Definition at line 2631 of file execPartition.c.

2634{
2635 Bitmapset *result = NULL;
2636 MemoryContext oldcontext;
2637 int i;
2638
2639 /*
2640 * Either we're here on the initial prune done during pruning
2641 * initialization, or we're at a point where PARAM_EXEC Params can be
2642 * evaluated *and* there are steps in which to do so.
2643 */
2644 Assert(initial_prune || prunestate->do_exec_prune);
2645 Assert(validsubplan_rtis != NULL || !initial_prune);
2646
2647 /*
2648 * Switch to a temp context to avoid leaking memory in the executor's
2649 * query-lifespan memory context.
2650 */
2651 oldcontext = MemoryContextSwitchTo(prunestate->prune_context);
2652
2653 /*
2654 * For each hierarchy, do the pruning tests, and add nondeletable
2655 * subplans' indexes to "result".
2656 */
2657 for (i = 0; i < prunestate->num_partprunedata; i++)
2658 {
2659 PartitionPruningData *prunedata = prunestate->partprunedata[i];
2661
2662 /*
2663 * We pass the zeroth item, belonging to the root table of the
2664 * hierarchy, and find_matching_subplans_recurse() takes care of
2665 * recursing to other (lower-level) parents as needed.
2666 */
2667 pprune = &prunedata->partrelprunedata[0];
2668 find_matching_subplans_recurse(prunedata, pprune, initial_prune,
2669 &result, validsubplan_rtis);
2670
2671 /*
2672 * Expression eval may have used space in ExprContext too. Avoid
2673 * accessing exec_context during initial pruning, as it is not valid
2674 * at that stage.
2675 */
2676 if (!initial_prune && pprune->exec_pruning_steps)
2678 }
2679
2680 /* Add in any subplans that partition pruning didn't account for */
2681 result = bms_add_members(result, prunestate->other_subplans);
2682
2683 MemoryContextSwitchTo(oldcontext);
2684
2685 /* Copy result out of the temp context before we reset it */
2686 result = bms_copy(result);
2687 if (validsubplan_rtis)
2688 *validsubplan_rtis = bms_copy(*validsubplan_rtis);
2689
2690 MemoryContextReset(prunestate->prune_context);
2691
2692 return result;
2693}
Bitmapset * bms_copy(const Bitmapset *a)
Definition: bitmapset.c:122
static void find_matching_subplans_recurse(PartitionPruningData *prunedata, PartitionedRelPruningData *pprune, bool initial_prune, Bitmapset **validsubplans, Bitmapset **validsubplan_rtis)
#define ResetExprContext(econtext)
Definition: executor.h:650
Assert(PointerIsAligned(start, uint64))
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:400
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
ExprContext * exprcontext
Definition: partprune.h:60
PartitionPruningData * partprunedata[FLEXIBLE_ARRAY_MEMBER]
Bitmapset * other_subplans
MemoryContext prune_context
PartitionedRelPruningData partrelprunedata[FLEXIBLE_ARRAY_MEMBER]
Definition: execPartition.h:87
PartitionPruneContext exec_context
Definition: execPartition.h:74

References Assert(), bms_add_members(), bms_copy(), PartitionPruneState::do_exec_prune, PartitionedRelPruningData::exec_context, PartitionedRelPruningData::exec_pruning_steps, PartitionPruneContext::exprcontext, find_matching_subplans_recurse(), i, MemoryContextReset(), MemoryContextSwitchTo(), PartitionPruneState::num_partprunedata, PartitionPruneState::other_subplans, PartitionPruneState::partprunedata, PartitionPruningData::partrelprunedata, PartitionPruneState::prune_context, and ResetExprContext.

Referenced by choose_next_subplan_for_leader(), choose_next_subplan_for_worker(), choose_next_subplan_locally(), ExecAppendAsyncBegin(), ExecDoInitialPruning(), and ExecMergeAppend().

◆ ExecFindPartition()

ResultRelInfo * ExecFindPartition ( ModifyTableState mtstate,
ResultRelInfo rootResultRelInfo,
PartitionTupleRouting proute,
TupleTableSlot slot,
EState estate 
)

Definition at line 266 of file execPartition.c.

270{
273 bool isnull[PARTITION_MAX_KEYS];
274 Relation rel;
275 PartitionDispatch dispatch;
276 PartitionDesc partdesc;
277 ExprContext *ecxt = GetPerTupleExprContext(estate);
278 TupleTableSlot *ecxt_scantuple_saved = ecxt->ecxt_scantuple;
279 TupleTableSlot *rootslot = slot;
280 TupleTableSlot *myslot = NULL;
281 MemoryContext oldcxt;
282 ResultRelInfo *rri = NULL;
283
284 /* use per-tuple context here to avoid leaking memory */
286
287 /*
288 * First check the root table's partition constraint, if any. No point in
289 * routing the tuple if it doesn't belong in the root table itself.
290 */
291 if (rootResultRelInfo->ri_RelationDesc->rd_rel->relispartition)
292 ExecPartitionCheck(rootResultRelInfo, slot, estate, true);
293
294 /* start with the root partitioned table */
295 dispatch = pd[0];
296 while (dispatch != NULL)
297 {
298 int partidx = -1;
299 bool is_leaf;
300
302
303 rel = dispatch->reldesc;
304 partdesc = dispatch->partdesc;
305
306 /*
307 * Extract partition key from tuple. Expression evaluation machinery
308 * that FormPartitionKeyDatum() invokes expects ecxt_scantuple to
309 * point to the correct tuple slot. The slot might have changed from
310 * what was used for the parent table if the table of the current
311 * partitioning level has different tuple descriptor from the parent.
312 * So update ecxt_scantuple accordingly.
313 */
314 ecxt->ecxt_scantuple = slot;
315 FormPartitionKeyDatum(dispatch, slot, estate, values, isnull);
316
317 /*
318 * If this partitioned table has no partitions or no partition for
319 * these values, error out.
320 */
321 if (partdesc->nparts == 0 ||
322 (partidx = get_partition_for_tuple(dispatch, values, isnull)) < 0)
323 {
324 char *val_desc;
325
327 values, isnull, 64);
330 (errcode(ERRCODE_CHECK_VIOLATION),
331 errmsg("no partition of relation \"%s\" found for row",
333 val_desc ?
334 errdetail("Partition key of the failing row contains %s.",
335 val_desc) : 0,
336 errtable(rel)));
337 }
338
339 is_leaf = partdesc->is_leaf[partidx];
340 if (is_leaf)
341 {
342 /*
343 * We've reached the leaf -- hurray, we're done. Look to see if
344 * we've already got a ResultRelInfo for this partition.
345 */
346 if (likely(dispatch->indexes[partidx] >= 0))
347 {
348 /* ResultRelInfo already built */
349 Assert(dispatch->indexes[partidx] < proute->num_partitions);
350 rri = proute->partitions[dispatch->indexes[partidx]];
351 }
352 else
353 {
354 /*
355 * If the partition is known in the owning ModifyTableState
356 * node, we can re-use that ResultRelInfo instead of creating
357 * a new one with ExecInitPartitionInfo().
358 */
359 rri = ExecLookupResultRelByOid(mtstate,
360 partdesc->oids[partidx],
361 true, false);
362 if (rri)
363 {
364 ModifyTable *node = (ModifyTable *) mtstate->ps.plan;
365
366 /* Verify this ResultRelInfo allows INSERTs */
368 node ? node->onConflictAction : ONCONFLICT_NONE,
369 NIL);
370
371 /*
372 * Initialize information needed to insert this and
373 * subsequent tuples routed to this partition.
374 */
375 ExecInitRoutingInfo(mtstate, estate, proute, dispatch,
376 rri, partidx, true);
377 }
378 else
379 {
380 /* We need to create a new one. */
381 rri = ExecInitPartitionInfo(mtstate, estate, proute,
382 dispatch,
383 rootResultRelInfo, partidx);
384 }
385 }
386 Assert(rri != NULL);
387
388 /* Signal to terminate the loop */
389 dispatch = NULL;
390 }
391 else
392 {
393 /*
394 * Partition is a sub-partitioned table; get the PartitionDispatch
395 */
396 if (likely(dispatch->indexes[partidx] >= 0))
397 {
398 /* Already built. */
399 Assert(dispatch->indexes[partidx] < proute->num_dispatch);
400
401 rri = proute->nonleaf_partitions[dispatch->indexes[partidx]];
402
403 /*
404 * Move down to the next partition level and search again
405 * until we find a leaf partition that matches this tuple
406 */
407 dispatch = pd[dispatch->indexes[partidx]];
408 }
409 else
410 {
411 /* Not yet built. Do that now. */
412 PartitionDispatch subdispatch;
413
414 /*
415 * Create the new PartitionDispatch. We pass the current one
416 * in as the parent PartitionDispatch
417 */
418 subdispatch = ExecInitPartitionDispatchInfo(estate,
419 proute,
420 partdesc->oids[partidx],
421 dispatch, partidx,
422 mtstate->rootResultRelInfo);
423 Assert(dispatch->indexes[partidx] >= 0 &&
424 dispatch->indexes[partidx] < proute->num_dispatch);
425
426 rri = proute->nonleaf_partitions[dispatch->indexes[partidx]];
427 dispatch = subdispatch;
428 }
429
430 /*
431 * Convert the tuple to the new parent's layout, if different from
432 * the previous parent.
433 */
434 if (dispatch->tupslot)
435 {
436 AttrMap *map = dispatch->tupmap;
437 TupleTableSlot *tempslot = myslot;
438
439 myslot = dispatch->tupslot;
440 slot = execute_attr_map_slot(map, slot, myslot);
441
442 if (tempslot != NULL)
443 ExecClearTuple(tempslot);
444 }
445 }
446
447 /*
448 * If this partition is the default one, we must check its partition
449 * constraint now, which may have changed concurrently due to
450 * partitions being added to the parent.
451 *
452 * (We do this here, and do not rely on ExecInsert doing it, because
453 * we don't want to miss doing it for non-leaf partitions.)
454 */
455 if (partidx == partdesc->boundinfo->default_index)
456 {
457 /*
458 * The tuple must match the partition's layout for the constraint
459 * expression to be evaluated successfully. If the partition is
460 * sub-partitioned, that would already be the case due to the code
461 * above, but for a leaf partition the tuple still matches the
462 * parent's layout.
463 *
464 * Note that we have a map to convert from root to current
465 * partition, but not from immediate parent to current partition.
466 * So if we have to convert, do it from the root slot; if not, use
467 * the root slot as-is.
468 */
469 if (is_leaf)
470 {
471 TupleConversionMap *map = ExecGetRootToChildMap(rri, estate);
472
473 if (map)
474 slot = execute_attr_map_slot(map->attrMap, rootslot,
476 else
477 slot = rootslot;
478 }
479
480 ExecPartitionCheck(rri, slot, estate, true);
481 }
482 }
483
484 /* Release the tuple in the lowest parent's dedicated slot. */
485 if (myslot != NULL)
486 ExecClearTuple(myslot);
487 /* and restore ecxt's scantuple */
488 ecxt->ecxt_scantuple = ecxt_scantuple_saved;
489 MemoryContextSwitchTo(oldcxt);
490
491 return rri;
492}
static Datum values[MAXATTR]
Definition: bootstrap.c:153
#define likely(x)
Definition: c.h:406
#define OidIsValid(objectId)
Definition: c.h:777
int errdetail(const char *fmt,...)
Definition: elog.c:1216
int errcode(int sqlerrcode)
Definition: elog.c:863
int errmsg(const char *fmt,...)
Definition: elog.c:1080
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:150
void CheckValidResultRel(ResultRelInfo *resultRelInfo, CmdType operation, OnConflictAction onConflictAction, List *mergeActions)
Definition: execMain.c:1050
bool ExecPartitionCheck(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate, bool emitError)
Definition: execMain.c:1856
static PartitionDispatch ExecInitPartitionDispatchInfo(EState *estate, PartitionTupleRouting *proute, Oid partoid, PartitionDispatch parent_pd, int partidx, ResultRelInfo *rootResultRelInfo)
static ResultRelInfo * ExecInitPartitionInfo(ModifyTableState *mtstate, EState *estate, PartitionTupleRouting *proute, PartitionDispatch dispatch, ResultRelInfo *rootResultRelInfo, int partidx)
static void ExecInitRoutingInfo(ModifyTableState *mtstate, EState *estate, PartitionTupleRouting *proute, PartitionDispatch dispatch, ResultRelInfo *partRelInfo, int partidx, bool is_borrowed_rel)
static char * ExecBuildSlotPartitionKeyDescription(Relation rel, const Datum *values, const bool *isnull, int maxfieldlen)
static void FormPartitionKeyDatum(PartitionDispatch pd, TupleTableSlot *slot, EState *estate, Datum *values, bool *isnull)
static int get_partition_for_tuple(PartitionDispatch pd, const Datum *values, const bool *isnull)
TupleConversionMap * ExecGetRootToChildMap(ResultRelInfo *resultRelInfo, EState *estate)
Definition: execUtils.c:1326
#define GetPerTupleExprContext(estate)
Definition: executor.h:656
#define GetPerTupleMemoryContext(estate)
Definition: executor.h:661
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:123
ResultRelInfo * ExecLookupResultRelByOid(ModifyTableState *node, Oid resultoid, bool missing_ok, bool update_cache)
@ ONCONFLICT_NONE
Definition: nodes.h:428
@ CMD_INSERT
Definition: nodes.h:277
#define PARTITION_MAX_KEYS
#define NIL
Definition: pg_list.h:68
uint64_t Datum
Definition: postgres.h:70
#define RelationGetRelid(relation)
Definition: rel.h:515
#define RelationGetRelationName(relation)
Definition: rel.h:549
int errtable(Relation rel)
Definition: relcache.c:6049
Definition: attmap.h:35
TupleTableSlot * ecxt_scantuple
Definition: execnodes.h:273
ResultRelInfo * rootResultRelInfo
Definition: execnodes.h:1416
OnConflictAction onConflictAction
Definition: plannodes.h:362
PartitionBoundInfo boundinfo
Definition: partdesc.h:38
bool * is_leaf
Definition: partdesc.h:35
PartitionDesc partdesc
int indexes[FLEXIBLE_ARRAY_MEMBER]
ResultRelInfo ** nonleaf_partitions
Definition: execPartition.c:96
Plan * plan
Definition: execnodes.h:1165
Form_pg_class rd_rel
Definition: rel.h:111
TupleTableSlot * ri_PartitionTupleSlot
Definition: execnodes.h:619
AttrMap * attrMap
Definition: tupconvert.h:28
TupleTableSlot * execute_attr_map_slot(AttrMap *attrMap, TupleTableSlot *in_slot, TupleTableSlot *out_slot)
Definition: tupconvert.c:193
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:457

References Assert(), TupleConversionMap::attrMap, PartitionDescData::boundinfo, CHECK_FOR_INTERRUPTS, CheckValidResultRel(), CMD_INSERT, PartitionBoundInfoData::default_index, ExprContext::ecxt_scantuple, ereport, errcode(), errdetail(), errmsg(), ERROR, errtable(), ExecBuildSlotPartitionKeyDescription(), ExecClearTuple(), ExecGetRootToChildMap(), ExecInitPartitionDispatchInfo(), ExecInitPartitionInfo(), ExecInitRoutingInfo(), ExecLookupResultRelByOid(), ExecPartitionCheck(), execute_attr_map_slot(), FormPartitionKeyDatum(), get_partition_for_tuple(), GetPerTupleExprContext, GetPerTupleMemoryContext, PartitionDispatchData::indexes, PartitionDescData::is_leaf, likely, MemoryContextSwitchTo(), NIL, PartitionTupleRouting::nonleaf_partitions, PartitionDescData::nparts, PartitionTupleRouting::num_dispatch, PartitionTupleRouting::num_partitions, OidIsValid, PartitionDescData::oids, ONCONFLICT_NONE, ModifyTable::onConflictAction, PartitionDispatchData::partdesc, PartitionTupleRouting::partition_dispatch_info, PARTITION_MAX_KEYS, PartitionTupleRouting::partitions, PlanState::plan, ModifyTableState::ps, RelationData::rd_rel, RelationGetRelationName, RelationGetRelid, PartitionDispatchData::reldesc, ResultRelInfo::ri_PartitionTupleSlot, ResultRelInfo::ri_RelationDesc, ModifyTableState::rootResultRelInfo, PartitionDispatchData::tupmap, PartitionDispatchData::tupslot, and values.

Referenced by apply_handle_tuple_routing(), CopyFrom(), and ExecPrepareTupleRouting().

◆ ExecInitPartitionExecPruning()

PartitionPruneState * ExecInitPartitionExecPruning ( PlanState planstate,
int  n_total_subplans,
int  part_prune_index,
Bitmapset relids,
Bitmapset **  initially_valid_subplans 
)

Definition at line 2013 of file execPartition.c.

2018{
2019 PartitionPruneState *prunestate;
2020 EState *estate = planstate->state;
2021 PartitionPruneInfo *pruneinfo;
2022
2023 /* Obtain the pruneinfo we need. */
2025 part_prune_index);
2026
2027 /* Its relids better match the plan node's or the planner messed up. */
2028 if (!bms_equal(relids, pruneinfo->relids))
2029 elog(ERROR, "wrong pruneinfo with relids=%s found at part_prune_index=%d contained in plan node with relids=%s",
2030 bmsToString(pruneinfo->relids), part_prune_index,
2031 bmsToString(relids));
2032
2033 /*
2034 * The PartitionPruneState would have been created by
2035 * ExecDoInitialPruning() and stored as the part_prune_index'th element of
2036 * EState.es_part_prune_states.
2037 */
2038 prunestate = list_nth(estate->es_part_prune_states, part_prune_index);
2039 Assert(prunestate != NULL);
2040
2041 /* Use the result of initial pruning done by ExecDoInitialPruning(). */
2042 if (prunestate->do_initial_prune)
2043 *initially_valid_subplans = list_nth_node(Bitmapset,
2044 estate->es_part_prune_results,
2045 part_prune_index);
2046 else
2047 {
2048 /* No pruning, so we'll need to initialize all subplans */
2049 Assert(n_total_subplans > 0);
2050 *initially_valid_subplans = bms_add_range(NULL, 0,
2051 n_total_subplans - 1);
2052 }
2053
2054 /*
2055 * The exec pruning state must also be initialized, if needed, before it
2056 * can be used for pruning during execution.
2057 *
2058 * This also re-sequences subplan indexes contained in prunestate to
2059 * account for any that were removed due to initial pruning; refer to the
2060 * condition in InitExecPartitionPruneContexts() that is used to determine
2061 * whether to do this. If no exec pruning needs to be done, we would thus
2062 * leave the maps to be in an invalid state, but that's ok since that data
2063 * won't be consulted again (cf initial Assert in
2064 * ExecFindMatchingSubPlans).
2065 */
2066 if (prunestate->do_exec_prune)
2067 InitExecPartitionPruneContexts(prunestate, planstate,
2068 *initially_valid_subplans,
2069 n_total_subplans);
2070
2071 return prunestate;
2072}
bool bms_equal(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:142
Bitmapset * bms_add_range(Bitmapset *a, int lower, int upper)
Definition: bitmapset.c:1018
#define elog(elevel,...)
Definition: elog.h:226
static void InitExecPartitionPruneContexts(PartitionPruneState *prunestate, PlanState *parent_plan, Bitmapset *initially_valid_subplans, int n_total_subplans)
char * bmsToString(const Bitmapset *bms)
Definition: outfuncs.c:819
static void * list_nth(const List *list, int n)
Definition: pg_list.h:299
#define list_nth_node(type, list, n)
Definition: pg_list.h:327
Bitmapset * relids
Definition: plannodes.h:1647

References Assert(), bms_add_range(), bms_equal(), bmsToString(), PartitionPruneState::do_exec_prune, PartitionPruneState::do_initial_prune, elog, ERROR, EState::es_part_prune_infos, EState::es_part_prune_results, EState::es_part_prune_states, InitExecPartitionPruneContexts(), list_nth(), list_nth_node, PartitionPruneInfo::relids, and PlanState::state.

Referenced by ExecInitAppend(), and ExecInitMergeAppend().

◆ ExecSetupPartitionTupleRouting()

PartitionTupleRouting * ExecSetupPartitionTupleRouting ( EState estate,
Relation  rel 
)

Definition at line 219 of file execPartition.c.

220{
221 PartitionTupleRouting *proute;
222
223 /*
224 * Here we attempt to expend as little effort as possible in setting up
225 * the PartitionTupleRouting. Each partition's ResultRelInfo is built on
226 * demand, only when we actually need to route a tuple to that partition.
227 * The reason for this is that a common case is for INSERT to insert a
228 * single tuple into a partitioned table and this must be fast.
229 */
231 proute->partition_root = rel;
233 /* Rest of members initialized by zeroing */
234
235 /*
236 * Initialize this table's PartitionDispatch object. Here we pass in the
237 * parent as NULL as we don't need to care about any parent of the target
238 * partitioned table.
239 */
241 NULL, 0, NULL);
242
243 return proute;
244}
void * palloc0(Size size)
Definition: mcxt.c:1395
MemoryContext CurrentMemoryContext
Definition: mcxt.c:160
MemoryContext memcxt

References CurrentMemoryContext, ExecInitPartitionDispatchInfo(), PartitionTupleRouting::memcxt, palloc0(), PartitionTupleRouting::partition_root, and RelationGetRelid.

Referenced by apply_handle_tuple_routing(), CopyFrom(), ExecCrossPartitionUpdate(), ExecInitMerge(), and ExecInitModifyTable().