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

1237{
1238 int i;
1239
1240 /*
1241 * Remember, proute->partition_dispatch_info[0] corresponds to the root
1242 * partitioned table, which we must not try to close, because it is the
1243 * main target table of the query that will be closed by callers such as
1244 * ExecEndPlan() or DoCopy(). Also, tupslot is NULL for the root
1245 * partitioned table.
1246 */
1247 for (i = 1; i < proute->num_dispatch; i++)
1248 {
1250
1252
1253 if (pd->tupslot)
1255 }
1256
1257 for (i = 0; i < proute->num_partitions; i++)
1258 {
1259 ResultRelInfo *resultRelInfo = proute->partitions[i];
1260
1261 /* Allow any FDWs to shut down */
1262 if (resultRelInfo->ri_FdwRoutine != NULL &&
1263 resultRelInfo->ri_FdwRoutine->EndForeignInsert != NULL)
1264 resultRelInfo->ri_FdwRoutine->EndForeignInsert(mtstate->ps.state,
1265 resultRelInfo);
1266
1267 /*
1268 * Close it if it's not one of the result relations borrowed from the
1269 * owning ModifyTableState; those will be closed by ExecEndPlan().
1270 */
1271 if (proute->is_borrowed_rel[i])
1272 continue;
1273
1274 ExecCloseIndices(resultRelInfo);
1275 table_close(resultRelInfo->ri_RelationDesc, NoLock);
1276 }
1277}
void ExecCloseIndices(ResultRelInfo *resultRelInfo)
Definition: execIndexing.c:239
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
Definition: execTuples.c:1441
int i
Definition: isn.c:74
#define NoLock
Definition: lockdefs.h:34
EndForeignInsert_function EndForeignInsert
Definition: fdwapi.h:239
PlanState ps
Definition: execnodes.h:1391
TupleTableSlot * tupslot
PartitionDispatch * partition_dispatch_info
Definition: execPartition.c:95
ResultRelInfo ** partitions
Definition: execPartition.c:99
EState * state
Definition: execnodes.h:1155
Relation ri_RelationDesc
Definition: execnodes.h:475
struct FdwRoutine * ri_FdwRoutine
Definition: execnodes.h:528
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 1820 of file execPartition.c.

1821{
1822 PlannedStmt *stmt = estate->es_plannedstmt;
1823 ListCell *lc;
1824 List *locked_relids = NIL;
1825
1826 foreach(lc, estate->es_part_prune_infos)
1827 {
1829 PartitionPruneState *prunestate;
1830 Bitmapset *validsubplans = NULL;
1831 Bitmapset *all_leafpart_rtis = NULL;
1832 Bitmapset *validsubplan_rtis = NULL;
1833
1834 /* Create and save the PartitionPruneState. */
1835 prunestate = CreatePartitionPruneState(estate, pruneinfo,
1836 &all_leafpart_rtis);
1838 prunestate);
1839
1840 /*
1841 * Perform initial pruning steps, if any, and save the result
1842 * bitmapset or NULL as described in the header comment.
1843 */
1844 if (prunestate->do_initial_prune)
1845 validsubplans = ExecFindMatchingSubPlans(prunestate, true,
1846 &validsubplan_rtis);
1847 else
1848 validsubplan_rtis = all_leafpart_rtis;
1849
1850 if (ExecShouldLockRelations(estate))
1851 {
1852 int rtindex = -1;
1853
1854 while ((rtindex = bms_next_member(validsubplan_rtis,
1855 rtindex)) >= 0)
1856 {
1857 RangeTblEntry *rte = exec_rt_fetch(rtindex, estate);
1858
1859 Assert(rte->rtekind == RTE_RELATION &&
1860 rte->rellockmode != NoLock);
1861 LockRelationOid(rte->relid, rte->rellockmode);
1862 locked_relids = lappend_int(locked_relids, rtindex);
1863 }
1864 }
1866 validsubplan_rtis);
1868 validsubplans);
1869 }
1870
1871 /*
1872 * Lock the first result relation of each ModifyTable node, even if it was
1873 * pruned. This is required for ExecInitModifyTable(), which keeps its
1874 * first result relation if all other result relations have been pruned,
1875 * because some executor paths (e.g., in nodeModifyTable.c and
1876 * execPartition.c) rely on there being at least one result relation.
1877 *
1878 * There's room for improvement here --- we actually only need to do this
1879 * if all other result relations of the ModifyTable node were pruned, but
1880 * we don't have an easy way to tell that here.
1881 */
1882 if (stmt->resultRelations && ExecShouldLockRelations(estate))
1883 {
1884 foreach(lc, stmt->firstResultRels)
1885 {
1886 Index firstResultRel = lfirst_int(lc);
1887
1888 if (!bms_is_member(firstResultRel, estate->es_unpruned_relids))
1889 {
1890 RangeTblEntry *rte = exec_rt_fetch(firstResultRel, estate);
1891
1892 Assert(rte->rtekind == RTE_RELATION && rte->rellockmode != NoLock);
1893 LockRelationOid(rte->relid, rte->rellockmode);
1894 locked_relids = lappend_int(locked_relids, firstResultRel);
1895 }
1896 }
1897 }
1898
1899 /*
1900 * Release the useless locks if the plan won't be executed. This is the
1901 * same as what CheckCachedPlan() in plancache.c does.
1902 */
1903 if (!ExecPlanStillValid(estate))
1904 {
1905 foreach(lc, locked_relids)
1906 {
1907 RangeTblEntry *rte = exec_rt_fetch(lfirst_int(lc), estate);
1908
1909 UnlockRelationOid(rte->relid, rte->rellockmode);
1910 }
1911 }
1912}
int bms_next_member(const Bitmapset *a, int prevbit)
Definition: bitmapset.c:1306
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:510
Bitmapset * bms_add_members(Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:917
unsigned int Index
Definition: c.h:585
Bitmapset * ExecFindMatchingSubPlans(PartitionPruneState *prunestate, bool initial_prune, Bitmapset **validsubplan_rtis)
static PartitionPruneState * CreatePartitionPruneState(EState *estate, PartitionPruneInfo *pruneinfo, Bitmapset **all_leafpart_rtis)
static bool ExecShouldLockRelations(EState *estate)
Definition: executor.h:281
static RangeTblEntry * exec_rt_fetch(Index rti, EState *estate)
Definition: executor.h:678
static bool ExecPlanStillValid(EState *estate)
Definition: executor.h:270
Assert(PointerIsAligned(start, uint64))
#define stmt
Definition: indent_codes.h:59
List * lappend(List *list, void *datum)
Definition: list.c:339
List * lappend_int(List *list, int datum)
Definition: list.c:357
void UnlockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:229
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:107
@ RTE_RELATION
Definition: parsenodes.h:1026
#define lfirst_node(type, lc)
Definition: pg_list.h:176
#define NIL
Definition: pg_list.h:68
#define lfirst_int(lc)
Definition: pg_list.h:173
List * es_part_prune_infos
Definition: execnodes.h:662
PlannedStmt * es_plannedstmt
Definition: execnodes.h:660
Bitmapset * es_unpruned_relids
Definition: execnodes.h:665
List * es_part_prune_states
Definition: execnodes.h:663
List * es_part_prune_results
Definition: execnodes.h:664
Definition: pg_list.h:54
RTEKind rtekind
Definition: parsenodes.h:1056

References Assert(), bms_add_members(), bms_is_member(), bms_next_member(), CreatePartitionPruneState(), PartitionPruneState::do_initial_prune, EState::es_part_prune_infos, EState::es_part_prune_results, EState::es_part_prune_states, EState::es_plannedstmt, EState::es_unpruned_relids, exec_rt_fetch(), ExecFindMatchingSubPlans(), ExecPlanStillValid(), ExecShouldLockRelations(), lappend(), lappend_int(), lfirst_int, lfirst_node, LockRelationOid(), NIL, NoLock, RangeTblEntry::relid, RTE_RELATION, RangeTblEntry::rtekind, stmt, and UnlockRelationOid().

Referenced by InitPlan().

◆ ExecFindMatchingSubPlans()

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

Definition at line 2553 of file execPartition.c.

2556{
2557 Bitmapset *result = NULL;
2558 MemoryContext oldcontext;
2559 int i;
2560
2561 /*
2562 * Either we're here on the initial prune done during pruning
2563 * initialization, or we're at a point where PARAM_EXEC Params can be
2564 * evaluated *and* there are steps in which to do so.
2565 */
2566 Assert(initial_prune || prunestate->do_exec_prune);
2567 Assert(validsubplan_rtis != NULL || !initial_prune);
2568
2569 /*
2570 * Switch to a temp context to avoid leaking memory in the executor's
2571 * query-lifespan memory context.
2572 */
2573 oldcontext = MemoryContextSwitchTo(prunestate->prune_context);
2574
2575 /*
2576 * For each hierarchy, do the pruning tests, and add nondeletable
2577 * subplans' indexes to "result".
2578 */
2579 for (i = 0; i < prunestate->num_partprunedata; i++)
2580 {
2581 PartitionPruningData *prunedata = prunestate->partprunedata[i];
2583
2584 /*
2585 * We pass the zeroth item, belonging to the root table of the
2586 * hierarchy, and find_matching_subplans_recurse() takes care of
2587 * recursing to other (lower-level) parents as needed.
2588 */
2589 pprune = &prunedata->partrelprunedata[0];
2590 find_matching_subplans_recurse(prunedata, pprune, initial_prune,
2591 &result, validsubplan_rtis);
2592
2593 /*
2594 * Expression eval may have used space in ExprContext too. Avoid
2595 * accessing exec_context during initial pruning, as it is not valid
2596 * at that stage.
2597 */
2598 if (!initial_prune && pprune->exec_pruning_steps)
2600 }
2601
2602 /* Add in any subplans that partition pruning didn't account for */
2603 result = bms_add_members(result, prunestate->other_subplans);
2604
2605 MemoryContextSwitchTo(oldcontext);
2606
2607 /* Copy result out of the temp context before we reset it */
2608 result = bms_copy(result);
2609 if (validsubplan_rtis)
2610 *validsubplan_rtis = bms_copy(*validsubplan_rtis);
2611
2612 MemoryContextReset(prunestate->prune_context);
2613
2614 return result;
2615}
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:631
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:383
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 /* Verify this ResultRelInfo allows INSERTs */
366
367 /*
368 * Initialize information needed to insert this and
369 * subsequent tuples routed to this partition.
370 */
371 ExecInitRoutingInfo(mtstate, estate, proute, dispatch,
372 rri, partidx, true);
373 }
374 else
375 {
376 /* We need to create a new one. */
377 rri = ExecInitPartitionInfo(mtstate, estate, proute,
378 dispatch,
379 rootResultRelInfo, partidx);
380 }
381 }
382 Assert(rri != NULL);
383
384 /* Signal to terminate the loop */
385 dispatch = NULL;
386 }
387 else
388 {
389 /*
390 * Partition is a sub-partitioned table; get the PartitionDispatch
391 */
392 if (likely(dispatch->indexes[partidx] >= 0))
393 {
394 /* Already built. */
395 Assert(dispatch->indexes[partidx] < proute->num_dispatch);
396
397 rri = proute->nonleaf_partitions[dispatch->indexes[partidx]];
398
399 /*
400 * Move down to the next partition level and search again
401 * until we find a leaf partition that matches this tuple
402 */
403 dispatch = pd[dispatch->indexes[partidx]];
404 }
405 else
406 {
407 /* Not yet built. Do that now. */
408 PartitionDispatch subdispatch;
409
410 /*
411 * Create the new PartitionDispatch. We pass the current one
412 * in as the parent PartitionDispatch
413 */
414 subdispatch = ExecInitPartitionDispatchInfo(estate,
415 proute,
416 partdesc->oids[partidx],
417 dispatch, partidx,
418 mtstate->rootResultRelInfo);
419 Assert(dispatch->indexes[partidx] >= 0 &&
420 dispatch->indexes[partidx] < proute->num_dispatch);
421
422 rri = proute->nonleaf_partitions[dispatch->indexes[partidx]];
423 dispatch = subdispatch;
424 }
425
426 /*
427 * Convert the tuple to the new parent's layout, if different from
428 * the previous parent.
429 */
430 if (dispatch->tupslot)
431 {
432 AttrMap *map = dispatch->tupmap;
433 TupleTableSlot *tempslot = myslot;
434
435 myslot = dispatch->tupslot;
436 slot = execute_attr_map_slot(map, slot, myslot);
437
438 if (tempslot != NULL)
439 ExecClearTuple(tempslot);
440 }
441 }
442
443 /*
444 * If this partition is the default one, we must check its partition
445 * constraint now, which may have changed concurrently due to
446 * partitions being added to the parent.
447 *
448 * (We do this here, and do not rely on ExecInsert doing it, because
449 * we don't want to miss doing it for non-leaf partitions.)
450 */
451 if (partidx == partdesc->boundinfo->default_index)
452 {
453 /*
454 * The tuple must match the partition's layout for the constraint
455 * expression to be evaluated successfully. If the partition is
456 * sub-partitioned, that would already be the case due to the code
457 * above, but for a leaf partition the tuple still matches the
458 * parent's layout.
459 *
460 * Note that we have a map to convert from root to current
461 * partition, but not from immediate parent to current partition.
462 * So if we have to convert, do it from the root slot; if not, use
463 * the root slot as-is.
464 */
465 if (is_leaf)
466 {
467 TupleConversionMap *map = ExecGetRootToChildMap(rri, estate);
468
469 if (map)
470 slot = execute_attr_map_slot(map->attrMap, rootslot,
472 else
473 slot = rootslot;
474 }
475
476 ExecPartitionCheck(rri, slot, estate, true);
477 }
478 }
479
480 /* Release the tuple in the lowest parent's dedicated slot. */
481 if (myslot != NULL)
482 ExecClearTuple(myslot);
483 /* and restore ecxt's scantuple */
484 ecxt->ecxt_scantuple = ecxt_scantuple_saved;
485 MemoryContextSwitchTo(oldcxt);
486
487 return rri;
488}
static Datum values[MAXATTR]
Definition: bootstrap.c:151
#define likely(x)
Definition: c.h:346
#define OidIsValid(objectId)
Definition: c.h:746
int errdetail(const char *fmt,...)
Definition: elog.c:1203
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
void CheckValidResultRel(ResultRelInfo *resultRelInfo, CmdType operation, List *mergeActions)
Definition: execMain.c:1149
bool ExecPartitionCheck(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate, bool emitError)
Definition: execMain.c:1930
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, Datum *values, 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, Datum *values, bool *isnull)
TupleConversionMap * ExecGetRootToChildMap(ResultRelInfo *resultRelInfo, EState *estate)
Definition: execUtils.c:1328
#define GetPerTupleExprContext(estate)
Definition: executor.h:637
#define GetPerTupleMemoryContext(estate)
Definition: executor.h:642
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:122
ResultRelInfo * ExecLookupResultRelByOid(ModifyTableState *node, Oid resultoid, bool missing_ok, bool update_cache)
@ CMD_INSERT
Definition: nodes.h:269
#define PARTITION_MAX_KEYS
uintptr_t Datum
Definition: postgres.h:69
#define RelationGetRelid(relation)
Definition: rel.h:513
#define RelationGetRelationName(relation)
Definition: rel.h:547
int errtable(Relation rel)
Definition: relcache.c:5977
Definition: attmap.h:35
TupleTableSlot * ecxt_scantuple
Definition: execnodes.h:268
ResultRelInfo * rootResultRelInfo
Definition: execnodes.h:1404
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
Form_pg_class rd_rel
Definition: rel.h:111
TupleTableSlot * ri_PartitionTupleSlot
Definition: execnodes.h:610
AttrMap * attrMap
Definition: tupconvert.h:28
TupleTableSlot * execute_attr_map_slot(AttrMap *attrMap, TupleTableSlot *in_slot, TupleTableSlot *out_slot)
Definition: tupconvert.c:192
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:454

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, PartitionDispatchData::partdesc, PartitionTupleRouting::partition_dispatch_info, PARTITION_MAX_KEYS, PartitionTupleRouting::partitions, 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 1935 of file execPartition.c.

1940{
1941 PartitionPruneState *prunestate;
1942 EState *estate = planstate->state;
1943 PartitionPruneInfo *pruneinfo;
1944
1945 /* Obtain the pruneinfo we need. */
1947 part_prune_index);
1948
1949 /* Its relids better match the plan node's or the planner messed up. */
1950 if (!bms_equal(relids, pruneinfo->relids))
1951 elog(ERROR, "wrong pruneinfo with relids=%s found at part_prune_index=%d contained in plan node with relids=%s",
1952 bmsToString(pruneinfo->relids), part_prune_index,
1953 bmsToString(relids));
1954
1955 /*
1956 * The PartitionPruneState would have been created by
1957 * ExecDoInitialPruning() and stored as the part_prune_index'th element of
1958 * EState.es_part_prune_states.
1959 */
1960 prunestate = list_nth(estate->es_part_prune_states, part_prune_index);
1961 Assert(prunestate != NULL);
1962
1963 /* Use the result of initial pruning done by ExecDoInitialPruning(). */
1964 if (prunestate->do_initial_prune)
1965 *initially_valid_subplans = list_nth_node(Bitmapset,
1966 estate->es_part_prune_results,
1967 part_prune_index);
1968 else
1969 {
1970 /* No pruning, so we'll need to initialize all subplans */
1971 Assert(n_total_subplans > 0);
1972 *initially_valid_subplans = bms_add_range(NULL, 0,
1973 n_total_subplans - 1);
1974 }
1975
1976 /*
1977 * The exec pruning state must also be initialized, if needed, before it
1978 * can be used for pruning during execution.
1979 *
1980 * This also re-sequences subplan indexes contained in prunestate to
1981 * account for any that were removed due to initial pruning; refer to the
1982 * condition in InitExecPartitionPruneContexts() that is used to determine
1983 * whether to do this. If no exec pruning needs to be done, we would thus
1984 * leave the maps to be in an invalid invalid state, but that's ok since
1985 * that data won't be consulted again (cf initial Assert in
1986 * ExecFindMatchingSubPlans).
1987 */
1988 if (prunestate->do_exec_prune)
1989 InitExecPartitionPruneContexts(prunestate, planstate,
1990 *initially_valid_subplans,
1991 n_total_subplans);
1992
1993 return prunestate;
1994}
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:225
static void InitExecPartitionPruneContexts(PartitionPruneState *prunstate, PlanState *parent_plan, Bitmapset *initially_valid_subplans, int n_total_subplans)
char * bmsToString(const Bitmapset *bms)
Definition: outfuncs.c:811
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:1597

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:1347
MemoryContext CurrentMemoryContext
Definition: mcxt.c:143
MemoryContext memcxt

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

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