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

1243{
1244 int i;
1245
1246 /*
1247 * Remember, proute->partition_dispatch_info[0] corresponds to the root
1248 * partitioned table, which we must not try to close, because it is the
1249 * main target table of the query that will be closed by callers such as
1250 * ExecEndPlan() or DoCopy(). Also, tupslot is NULL for the root
1251 * partitioned table.
1252 */
1253 for (i = 1; i < proute->num_dispatch; i++)
1254 {
1256
1258
1259 if (pd->tupslot)
1261 }
1262
1263 for (i = 0; i < proute->num_partitions; i++)
1264 {
1265 ResultRelInfo *resultRelInfo = proute->partitions[i];
1266
1267 /* Allow any FDWs to shut down */
1268 if (resultRelInfo->ri_FdwRoutine != NULL &&
1269 resultRelInfo->ri_FdwRoutine->EndForeignInsert != NULL)
1270 resultRelInfo->ri_FdwRoutine->EndForeignInsert(mtstate->ps.state,
1271 resultRelInfo);
1272
1273 /*
1274 * Close it if it's not one of the result relations borrowed from the
1275 * owning ModifyTableState; those will be closed by ExecEndPlan().
1276 */
1277 if (proute->is_borrowed_rel[i])
1278 continue;
1279
1280 ExecCloseIndices(resultRelInfo);
1281 table_close(resultRelInfo->ri_RelationDesc, NoLock);
1282 }
1283}
void ExecCloseIndices(ResultRelInfo *resultRelInfo)
Definition: execIndexing.c:238
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:94
ResultRelInfo ** partitions
Definition: execPartition.c:98
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 1824 of file execPartition.c.

1825{
1826 ListCell *lc;
1827
1828 foreach(lc, estate->es_part_prune_infos)
1829 {
1831 PartitionPruneState *prunestate;
1832 Bitmapset *validsubplans = NULL;
1833 Bitmapset *all_leafpart_rtis = NULL;
1834 Bitmapset *validsubplan_rtis = NULL;
1835
1836 /* Create and save the PartitionPruneState. */
1837 prunestate = CreatePartitionPruneState(estate, pruneinfo,
1838 &all_leafpart_rtis);
1840 prunestate);
1841
1842 /*
1843 * Perform initial pruning steps, if any, and save the result
1844 * bitmapset or NULL as described in the header comment.
1845 */
1846 if (prunestate->do_initial_prune)
1847 validsubplans = ExecFindMatchingSubPlans(prunestate, true,
1848 &validsubplan_rtis);
1849 else
1850 validsubplan_rtis = all_leafpart_rtis;
1851
1853 validsubplan_rtis);
1855 validsubplans);
1856 }
1857}
Bitmapset * bms_add_members(Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:917
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 2498 of file execPartition.c.

2501{
2502 Bitmapset *result = NULL;
2503 MemoryContext oldcontext;
2504 int i;
2505
2506 /*
2507 * Either we're here on the initial prune done during pruning
2508 * initialization, or we're at a point where PARAM_EXEC Params can be
2509 * evaluated *and* there are steps in which to do so.
2510 */
2511 Assert(initial_prune || prunestate->do_exec_prune);
2512 Assert(validsubplan_rtis != NULL || !initial_prune);
2513
2514 /*
2515 * Switch to a temp context to avoid leaking memory in the executor's
2516 * query-lifespan memory context.
2517 */
2518 oldcontext = MemoryContextSwitchTo(prunestate->prune_context);
2519
2520 /*
2521 * For each hierarchy, do the pruning tests, and add nondeletable
2522 * subplans' indexes to "result".
2523 */
2524 for (i = 0; i < prunestate->num_partprunedata; i++)
2525 {
2526 PartitionPruningData *prunedata = prunestate->partprunedata[i];
2528
2529 /*
2530 * We pass the zeroth item, belonging to the root table of the
2531 * hierarchy, and find_matching_subplans_recurse() takes care of
2532 * recursing to other (lower-level) parents as needed.
2533 */
2534 pprune = &prunedata->partrelprunedata[0];
2535 find_matching_subplans_recurse(prunedata, pprune, initial_prune,
2536 &result, validsubplan_rtis);
2537
2538 /*
2539 * Expression eval may have used space in ExprContext too. Avoid
2540 * accessing exec_context during initial pruning, as it is not valid
2541 * at that stage.
2542 */
2543 if (!initial_prune && pprune->exec_pruning_steps)
2545 }
2546
2547 /* Add in any subplans that partition pruning didn't account for */
2548 result = bms_add_members(result, prunestate->other_subplans);
2549
2550 MemoryContextSwitchTo(oldcontext);
2551
2552 /* Copy result out of the temp context before we reset it */
2553 result = bms_copy(result);
2554 if (validsubplan_rtis)
2555 *validsubplan_rtis = bms_copy(*validsubplan_rtis);
2556
2557 MemoryContextReset(prunestate->prune_context);
2558
2559 return result;
2560}
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 265 of file execPartition.c.

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

1885{
1886 PartitionPruneState *prunestate;
1887 EState *estate = planstate->state;
1888 PartitionPruneInfo *pruneinfo;
1889
1890 /* Obtain the pruneinfo we need. */
1892 part_prune_index);
1893
1894 /* Its relids better match the plan node's or the planner messed up. */
1895 if (!bms_equal(relids, pruneinfo->relids))
1896 elog(ERROR, "wrong pruneinfo with relids=%s found at part_prune_index=%d contained in plan node with relids=%s",
1897 bmsToString(pruneinfo->relids), part_prune_index,
1898 bmsToString(relids));
1899
1900 /*
1901 * The PartitionPruneState would have been created by
1902 * ExecDoInitialPruning() and stored as the part_prune_index'th element of
1903 * EState.es_part_prune_states.
1904 */
1905 prunestate = list_nth(estate->es_part_prune_states, part_prune_index);
1906 Assert(prunestate != NULL);
1907
1908 /* Use the result of initial pruning done by ExecDoInitialPruning(). */
1909 if (prunestate->do_initial_prune)
1910 *initially_valid_subplans = list_nth_node(Bitmapset,
1911 estate->es_part_prune_results,
1912 part_prune_index);
1913 else
1914 {
1915 /* No pruning, so we'll need to initialize all subplans */
1916 Assert(n_total_subplans > 0);
1917 *initially_valid_subplans = bms_add_range(NULL, 0,
1918 n_total_subplans - 1);
1919 }
1920
1921 /*
1922 * The exec pruning state must also be initialized, if needed, before it
1923 * can be used for pruning during execution.
1924 *
1925 * This also re-sequences subplan indexes contained in prunestate to
1926 * account for any that were removed due to initial pruning; refer to the
1927 * condition in InitExecPartitionPruneContexts() that is used to determine
1928 * whether to do this. If no exec pruning needs to be done, we would thus
1929 * leave the maps to be in an invalid state, but that's ok since that data
1930 * won't be consulted again (cf initial Assert in
1931 * ExecFindMatchingSubPlans).
1932 */
1933 if (prunestate->do_exec_prune)
1934 InitExecPartitionPruneContexts(prunestate, planstate,
1935 *initially_valid_subplans,
1936 n_total_subplans);
1937
1938 return prunestate;
1939}
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:1019
#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:822
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 218 of file execPartition.c.

219{
220 PartitionTupleRouting *proute;
221
222 /*
223 * Here we attempt to expend as little effort as possible in setting up
224 * the PartitionTupleRouting. Each partition's ResultRelInfo is built on
225 * demand, only when we actually need to route a tuple to that partition.
226 * The reason for this is that a common case is for INSERT to insert a
227 * single tuple into a partitioned table and this must be fast.
228 */
230 proute->partition_root = rel;
232 /* Rest of members initialized by zeroing */
233
234 /*
235 * Initialize this table's PartitionDispatch object. Here we pass in the
236 * parent as NULL as we don't need to care about any parent of the target
237 * partitioned table.
238 */
240 NULL, 0, NULL);
241
242 return proute;
243}
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().