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 1370 of file execPartition.c.

1372{
1373 int i;
1374
1375 /*
1376 * Remember, proute->partition_dispatch_info[0] corresponds to the root
1377 * partitioned table, which we must not try to close, because it is the
1378 * main target table of the query that will be closed by callers such as
1379 * ExecEndPlan() or DoCopy(). Also, tupslot is NULL for the root
1380 * partitioned table.
1381 */
1382 for (i = 1; i < proute->num_dispatch; i++)
1383 {
1385
1387
1388 if (pd->tupslot)
1390 }
1391
1392 for (i = 0; i < proute->num_partitions; i++)
1393 {
1394 ResultRelInfo *resultRelInfo = proute->partitions[i];
1395
1396 /* Allow any FDWs to shut down */
1397 if (resultRelInfo->ri_FdwRoutine != NULL &&
1398 resultRelInfo->ri_FdwRoutine->EndForeignInsert != NULL)
1399 resultRelInfo->ri_FdwRoutine->EndForeignInsert(mtstate->ps.state,
1400 resultRelInfo);
1401
1402 /*
1403 * Close it if it's not one of the result relations borrowed from the
1404 * owning ModifyTableState; those will be closed by ExecEndPlan().
1405 */
1406 if (proute->is_borrowed_rel[i])
1407 continue;
1408
1409 ExecCloseIndices(resultRelInfo);
1410 table_close(resultRelInfo->ri_RelationDesc, NoLock);
1411 }
1412}
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 1953 of file execPartition.c.

1954{
1955 ListCell *lc;
1956
1957 foreach(lc, estate->es_part_prune_infos)
1958 {
1960 PartitionPruneState *prunestate;
1961 Bitmapset *validsubplans = NULL;
1962 Bitmapset *all_leafpart_rtis = NULL;
1963 Bitmapset *validsubplan_rtis = NULL;
1964
1965 /* Create and save the PartitionPruneState. */
1966 prunestate = CreatePartitionPruneState(estate, pruneinfo,
1967 &all_leafpart_rtis);
1969 prunestate);
1970
1971 /*
1972 * Perform initial pruning steps, if any, and save the result
1973 * bitmapset or NULL as described in the header comment.
1974 */
1975 if (prunestate->do_initial_prune)
1976 validsubplans = ExecFindMatchingSubPlans(prunestate, true,
1977 &validsubplan_rtis);
1978 else
1979 validsubplan_rtis = all_leafpart_rtis;
1980
1982 validsubplan_rtis);
1984 validsubplans);
1985 }
1986}
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 2625 of file execPartition.c.

2628{
2629 Bitmapset *result = NULL;
2630 MemoryContext oldcontext;
2631 int i;
2632
2633 /*
2634 * Either we're here on the initial prune done during pruning
2635 * initialization, or we're at a point where PARAM_EXEC Params can be
2636 * evaluated *and* there are steps in which to do so.
2637 */
2638 Assert(initial_prune || prunestate->do_exec_prune);
2639 Assert(validsubplan_rtis != NULL || !initial_prune);
2640
2641 /*
2642 * Switch to a temp context to avoid leaking memory in the executor's
2643 * query-lifespan memory context.
2644 */
2645 oldcontext = MemoryContextSwitchTo(prunestate->prune_context);
2646
2647 /*
2648 * For each hierarchy, do the pruning tests, and add nondeletable
2649 * subplans' indexes to "result".
2650 */
2651 for (i = 0; i < prunestate->num_partprunedata; i++)
2652 {
2653 PartitionPruningData *prunedata = prunestate->partprunedata[i];
2655
2656 /*
2657 * We pass the zeroth item, belonging to the root table of the
2658 * hierarchy, and find_matching_subplans_recurse() takes care of
2659 * recursing to other (lower-level) parents as needed.
2660 */
2661 pprune = &prunedata->partrelprunedata[0];
2662 find_matching_subplans_recurse(prunedata, pprune, initial_prune,
2663 &result, validsubplan_rtis);
2664
2665 /*
2666 * Expression eval may have used space in ExprContext too. Avoid
2667 * accessing exec_context during initial pruning, as it is not valid
2668 * at that stage.
2669 */
2670 if (!initial_prune && pprune->exec_pruning_steps)
2672 }
2673
2674 /* Add in any subplans that partition pruning didn't account for */
2675 result = bms_add_members(result, prunestate->other_subplans);
2676
2677 MemoryContextSwitchTo(oldcontext);
2678
2679 /* Copy result out of the temp context before we reset it */
2680 result = bms_copy(result);
2681 if (validsubplan_rtis)
2682 *validsubplan_rtis = bms_copy(*validsubplan_rtis);
2683
2684 MemoryContextReset(prunestate->prune_context);
2685
2686 return result;
2687}
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:417
#define OidIsValid(objectId)
Definition: c.h:788
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 2009 of file execPartition.c.

2014{
2015 PartitionPruneState *prunestate;
2016 EState *estate = planstate->state;
2017 PartitionPruneInfo *pruneinfo;
2018
2019 /* Obtain the pruneinfo we need. */
2021 part_prune_index);
2022
2023 /* Its relids better match the plan node's or the planner messed up. */
2024 if (!bms_equal(relids, pruneinfo->relids))
2025 elog(ERROR, "wrong pruneinfo with relids=%s found at part_prune_index=%d contained in plan node with relids=%s",
2026 bmsToString(pruneinfo->relids), part_prune_index,
2027 bmsToString(relids));
2028
2029 /*
2030 * The PartitionPruneState would have been created by
2031 * ExecDoInitialPruning() and stored as the part_prune_index'th element of
2032 * EState.es_part_prune_states.
2033 */
2034 prunestate = list_nth(estate->es_part_prune_states, part_prune_index);
2035 Assert(prunestate != NULL);
2036
2037 /* Use the result of initial pruning done by ExecDoInitialPruning(). */
2038 if (prunestate->do_initial_prune)
2039 *initially_valid_subplans = list_nth_node(Bitmapset,
2040 estate->es_part_prune_results,
2041 part_prune_index);
2042 else
2043 {
2044 /* No pruning, so we'll need to initialize all subplans */
2045 Assert(n_total_subplans > 0);
2046 *initially_valid_subplans = bms_add_range(NULL, 0,
2047 n_total_subplans - 1);
2048 }
2049
2050 /*
2051 * The exec pruning state must also be initialized, if needed, before it
2052 * can be used for pruning during execution.
2053 *
2054 * This also re-sequences subplan indexes contained in prunestate to
2055 * account for any that were removed due to initial pruning; refer to the
2056 * condition in InitExecPartitionPruneContexts() that is used to determine
2057 * whether to do this. If no exec pruning needs to be done, we would thus
2058 * leave the maps to be in an invalid state, but that's ok since that data
2059 * won't be consulted again (cf initial Assert in
2060 * ExecFindMatchingSubPlans).
2061 */
2062 if (prunestate->do_exec_prune)
2063 InitExecPartitionPruneContexts(prunestate, planstate,
2064 *initially_valid_subplans,
2065 n_total_subplans);
2066
2067 return prunestate;
2068}
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}
#define palloc0_object(type)
Definition: fe_memutils.h:75
MemoryContext CurrentMemoryContext
Definition: mcxt.c:160
MemoryContext memcxt

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

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