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

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

1823{
1824 PlannedStmt *stmt = estate->es_plannedstmt;
1825 ListCell *lc;
1826 List *locked_relids = NIL;
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
1852 if (ExecShouldLockRelations(estate))
1853 {
1854 int rtindex = -1;
1855
1856 while ((rtindex = bms_next_member(validsubplan_rtis,
1857 rtindex)) >= 0)
1858 {
1859 RangeTblEntry *rte = exec_rt_fetch(rtindex, estate);
1860
1861 Assert(rte->rtekind == RTE_RELATION &&
1862 rte->rellockmode != NoLock);
1863 LockRelationOid(rte->relid, rte->rellockmode);
1864 locked_relids = lappend_int(locked_relids, rtindex);
1865 }
1866 }
1868 validsubplan_rtis);
1870 validsubplans);
1871 }
1872
1873 /*
1874 * Lock the first result relation of each ModifyTable node, even if it was
1875 * pruned. This is required for ExecInitModifyTable(), which keeps its
1876 * first result relation if all other result relations have been pruned,
1877 * because some executor paths (e.g., in nodeModifyTable.c and
1878 * execPartition.c) rely on there being at least one result relation.
1879 *
1880 * There's room for improvement here --- we actually only need to do this
1881 * if all other result relations of the ModifyTable node were pruned, but
1882 * we don't have an easy way to tell that here.
1883 */
1884 if (stmt->resultRelations && ExecShouldLockRelations(estate))
1885 {
1886 foreach(lc, stmt->firstResultRels)
1887 {
1888 Index firstResultRel = lfirst_int(lc);
1889
1890 if (!bms_is_member(firstResultRel, estate->es_unpruned_relids))
1891 {
1892 RangeTblEntry *rte = exec_rt_fetch(firstResultRel, estate);
1893
1894 Assert(rte->rtekind == RTE_RELATION && rte->rellockmode != NoLock);
1895 LockRelationOid(rte->relid, rte->rellockmode);
1896 locked_relids = lappend_int(locked_relids, firstResultRel);
1897 }
1898 }
1899 }
1900
1901 /*
1902 * Release the useless locks if the plan won't be executed. This is the
1903 * same as what CheckCachedPlan() in plancache.c does.
1904 */
1905 if (!ExecPlanStillValid(estate))
1906 {
1907 foreach(lc, locked_relids)
1908 {
1909 RangeTblEntry *rte = exec_rt_fetch(lfirst_int(lc), estate);
1910
1911 UnlockRelationOid(rte->relid, rte->rellockmode);
1912 }
1913 }
1914}
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:322
static RangeTblEntry * exec_rt_fetch(Index rti, EState *estate)
Definition: executor.h:719
static bool ExecPlanStillValid(EState *estate)
Definition: executor.h:311
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:668
PlannedStmt * es_plannedstmt
Definition: execnodes.h:666
Bitmapset * es_unpruned_relids
Definition: execnodes.h:671
List * es_part_prune_states
Definition: execnodes.h:669
List * es_part_prune_results
Definition: execnodes.h:670
Definition: pg_list.h:54
RTEKind rtekind
Definition: parsenodes.h:1061

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, RTE_RELATION, RangeTblEntry::rtekind, stmt, and UnlockRelationOid().

Referenced by InitPlan().

◆ ExecFindMatchingSubPlans()

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

Definition at line 2555 of file execPartition.c.

2558{
2559 Bitmapset *result = NULL;
2560 MemoryContext oldcontext;
2561 int i;
2562
2563 /*
2564 * Either we're here on the initial prune done during pruning
2565 * initialization, or we're at a point where PARAM_EXEC Params can be
2566 * evaluated *and* there are steps in which to do so.
2567 */
2568 Assert(initial_prune || prunestate->do_exec_prune);
2569 Assert(validsubplan_rtis != NULL || !initial_prune);
2570
2571 /*
2572 * Switch to a temp context to avoid leaking memory in the executor's
2573 * query-lifespan memory context.
2574 */
2575 oldcontext = MemoryContextSwitchTo(prunestate->prune_context);
2576
2577 /*
2578 * For each hierarchy, do the pruning tests, and add nondeletable
2579 * subplans' indexes to "result".
2580 */
2581 for (i = 0; i < prunestate->num_partprunedata; i++)
2582 {
2583 PartitionPruningData *prunedata = prunestate->partprunedata[i];
2585
2586 /*
2587 * We pass the zeroth item, belonging to the root table of the
2588 * hierarchy, and find_matching_subplans_recurse() takes care of
2589 * recursing to other (lower-level) parents as needed.
2590 */
2591 pprune = &prunedata->partrelprunedata[0];
2592 find_matching_subplans_recurse(prunedata, pprune, initial_prune,
2593 &result, validsubplan_rtis);
2594
2595 /*
2596 * Expression eval may have used space in ExprContext too. Avoid
2597 * accessing exec_context during initial pruning, as it is not valid
2598 * at that stage.
2599 */
2600 if (!initial_prune && pprune->exec_pruning_steps)
2602 }
2603
2604 /* Add in any subplans that partition pruning didn't account for */
2605 result = bms_add_members(result, prunestate->other_subplans);
2606
2607 MemoryContextSwitchTo(oldcontext);
2608
2609 /* Copy result out of the temp context before we reset it */
2610 result = bms_copy(result);
2611 if (validsubplan_rtis)
2612 *validsubplan_rtis = bms_copy(*validsubplan_rtis);
2613
2614 MemoryContextReset(prunestate->prune_context);
2615
2616 return result;
2617}
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:672
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:414
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:1204
int errcode(int sqlerrcode)
Definition: elog.c:854
int errmsg(const char *fmt,...)
Definition: elog.c:1071
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
void CheckValidResultRel(ResultRelInfo *resultRelInfo, CmdType operation, List *mergeActions)
Definition: execMain.c:1152
bool ExecPartitionCheck(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate, bool emitError)
Definition: execMain.c:1932
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:1327
#define GetPerTupleExprContext(estate)
Definition: executor.h:678
#define GetPerTupleMemoryContext(estate)
Definition: executor.h:683
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:123
ResultRelInfo * ExecLookupResultRelByOid(ModifyTableState *node, Oid resultoid, bool missing_ok, bool update_cache)
@ CMD_INSERT
Definition: nodes.h:273
#define PARTITION_MAX_KEYS
uintptr_t Datum
Definition: postgres.h:69
#define RelationGetRelid(relation)
Definition: rel.h:516
#define RelationGetRelationName(relation)
Definition: rel.h:550
int errtable(Relation rel)
Definition: relcache.c:6046
Definition: attmap.h:35
TupleTableSlot * ecxt_scantuple
Definition: execnodes.h:268
ResultRelInfo * rootResultRelInfo
Definition: execnodes.h:1410
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:616
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:458

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

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

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

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