PostgreSQL Source Code git master
Functions
nodeModifyTable.h File Reference
#include "nodes/execnodes.h"
Include dependency graph for nodeModifyTable.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

void  ExecInitGenerated (ResultRelInfo *resultRelInfo, EState *estate, CmdType cmdtype)
 
void  ExecComputeStoredGenerated (ResultRelInfo *resultRelInfo, EState *estate, TupleTableSlot *slot, CmdType cmdtype)
 
ModifyTableStateExecInitModifyTable (ModifyTable *node, EState *estate, int eflags)
 
 
 
void  ExecInitMergeTupleSlots (ModifyTableState *mtstate, ResultRelInfo *resultRelInfo)
 

Function Documentation

ExecComputeStoredGenerated()

void ExecComputeStoredGenerated ( ResultRelInforesultRelInfo,
EStateestate,
TupleTableSlotslot,
CmdType  cmdtype 
)

Definition at line 544 of file nodeModifyTable.c.

547{
548 Relation rel = resultRelInfo->ri_RelationDesc;
549 TupleDesc tupdesc = RelationGetDescr(rel);
550 int natts = tupdesc->natts;
551 ExprContext *econtext = GetPerTupleExprContext(estate);
552 ExprState **ri_GeneratedExprs;
553 MemoryContext oldContext;
554 Datum *values;
555 bool *nulls;
556
557 /* We should not be called unless this is true */
558 Assert(tupdesc->constr && tupdesc->constr->has_generated_stored);
559
560 /*
561 * Initialize the expressions if we didn't already, and check whether we
562 * can exit early because nothing needs to be computed.
563 */
564 if (cmdtype == CMD_UPDATE)
565 {
566 if (resultRelInfo->ri_GeneratedExprsU == NULL)
567 ExecInitGenerated(resultRelInfo, estate, cmdtype);
568 if (resultRelInfo->ri_NumGeneratedNeededU == 0)
569 return;
570 ri_GeneratedExprs = resultRelInfo->ri_GeneratedExprsU;
571 }
572 else
573 {
574 if (resultRelInfo->ri_GeneratedExprsI == NULL)
575 ExecInitGenerated(resultRelInfo, estate, cmdtype);
576 /* Early exit is impossible given the prior Assert */
577 Assert(resultRelInfo->ri_NumGeneratedNeededI > 0);
578 ri_GeneratedExprs = resultRelInfo->ri_GeneratedExprsI;
579 }
580
582
583 values = palloc(sizeof(*values) * natts);
584 nulls = palloc(sizeof(*nulls) * natts);
585
586 slot_getallattrs(slot);
587 memcpy(nulls, slot->tts_isnull, sizeof(*nulls) * natts);
588
589 for (int i = 0; i < natts; i++)
590 {
591 CompactAttribute *attr = TupleDescCompactAttr(tupdesc, i);
592
593 if (ri_GeneratedExprs[i])
594 {
595 Datum val;
596 bool isnull;
597
598 Assert(TupleDescAttr(tupdesc, i)->attgenerated == ATTRIBUTE_GENERATED_STORED);
599
600 econtext->ecxt_scantuple = slot;
601
602 val = ExecEvalExpr(ri_GeneratedExprs[i], econtext, &isnull);
603
604 /*
605 * We must make a copy of val as we have no guarantees about where
606 * memory for a pass-by-reference Datum is located.
607 */
608 if (!isnull)
609 val = datumCopy(val, attr->attbyval, attr->attlen);
610
611 values[i] = val;
612 nulls[i] = isnull;
613 }
614 else
615 {
616 if (!nulls[i])
617 values[i] = datumCopy(slot->tts_values[i], attr->attbyval, attr->attlen);
618 }
619 }
620
621 ExecClearTuple(slot);
622 memcpy(slot->tts_values, values, sizeof(*values) * natts);
623 memcpy(slot->tts_isnull, nulls, sizeof(*nulls) * natts);
626
627 MemoryContextSwitchTo(oldContext);
628}
static Datum values[MAXATTR]
Definition: bootstrap.c:153
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:132
TupleTableSlot * ExecStoreVirtualTuple(TupleTableSlot *slot)
Definition: execTuples.c:1741
#define GetPerTupleExprContext(estate)
Definition: executor.h:653
#define GetPerTupleMemoryContext(estate)
Definition: executor.h:658
static Datum ExecEvalExpr(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:390
Assert(PointerIsAligned(start, uint64))
long val
Definition: informix.c:689
i
int i
Definition: isn.c:77
void * palloc(Size size)
Definition: mcxt.c:1365
void ExecInitGenerated(ResultRelInfo *resultRelInfo, EState *estate, CmdType cmdtype)
@ CMD_UPDATE
Definition: nodes.h:276
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
uint64_t Datum
Definition: postgres.h:70
#define RelationGetDescr(relation)
Definition: rel.h:540
bool attbyval
Definition: tupdesc.h:73
int16 attlen
Definition: tupdesc.h:71
TupleTableSlot * ecxt_scantuple
Definition: execnodes.h:273
Definition: rel.h:56
Relation ri_RelationDesc
Definition: execnodes.h:480
ExprState ** ri_GeneratedExprsI
Definition: execnodes.h:566
int ri_NumGeneratedNeededU
Definition: execnodes.h:571
ExprState ** ri_GeneratedExprsU
Definition: execnodes.h:567
int ri_NumGeneratedNeededI
Definition: execnodes.h:570
bool has_generated_stored
Definition: tupdesc.h:46
int natts
Definition: tupdesc.h:137
TupleConstr * constr
Definition: tupdesc.h:141
bool * tts_isnull
Definition: tuptable.h:126
Datum * tts_values
Definition: tuptable.h:124
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
Definition: tupdesc.h:160
static CompactAttribute * TupleDescCompactAttr(TupleDesc tupdesc, int i)
Definition: tupdesc.h:175
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:457
static void slot_getallattrs(TupleTableSlot *slot)
Definition: tuptable.h:371
static void ExecMaterializeSlot(TupleTableSlot *slot)
Definition: tuptable.h:475

References Assert(), CompactAttribute::attbyval, CompactAttribute::attlen, CMD_UPDATE, TupleDescData::constr, datumCopy(), ExprContext::ecxt_scantuple, ExecClearTuple(), ExecEvalExpr(), ExecInitGenerated(), ExecMaterializeSlot(), ExecStoreVirtualTuple(), GetPerTupleExprContext, GetPerTupleMemoryContext, TupleConstr::has_generated_stored, i, MemoryContextSwitchTo(), TupleDescData::natts, palloc(), RelationGetDescr, ResultRelInfo::ri_GeneratedExprsI, ResultRelInfo::ri_GeneratedExprsU, ResultRelInfo::ri_NumGeneratedNeededI, ResultRelInfo::ri_NumGeneratedNeededU, ResultRelInfo::ri_RelationDesc, slot_getallattrs(), TupleTableSlot::tts_isnull, TupleTableSlot::tts_values, TupleDescAttr(), TupleDescCompactAttr(), val, and values.

Referenced by CopyFrom(), ExecInsert(), ExecSimpleRelationInsert(), ExecSimpleRelationUpdate(), and ExecUpdatePrepareSlot().

ExecEndModifyTable()

void ExecEndModifyTable ( ModifyTableStatenode )

Definition at line 5192 of file nodeModifyTable.c.

5193{
5194 int i;
5195
5196 /*
5197 * Allow any FDWs to shut down
5198 */
5199 for (i = 0; i < node->mt_nrels; i++)
5200 {
5201 int j;
5202 ResultRelInfo *resultRelInfo = node->resultRelInfo + i;
5203
5204 if (!resultRelInfo->ri_usesFdwDirectModify &&
5205 resultRelInfo->ri_FdwRoutine != NULL &&
5206 resultRelInfo->ri_FdwRoutine->EndForeignModify != NULL)
5207 resultRelInfo->ri_FdwRoutine->EndForeignModify(node->ps.state,
5208 resultRelInfo);
5209
5210 /*
5211 * Cleanup the initialized batch slots. This only matters for FDWs
5212 * with batching, but the other cases will have ri_NumSlotsInitialized
5213 * == 0.
5214 */
5215 for (j = 0; j < resultRelInfo->ri_NumSlotsInitialized; j++)
5216 {
5217 ExecDropSingleTupleTableSlot(resultRelInfo->ri_Slots[j]);
5219 }
5220 }
5221
5222 /*
5223 * Close all the partitioned tables, leaf partitions, and their indices
5224 * and release the slot used for tuple routing, if set.
5225 */
5227 {
5229
5230 if (node->mt_root_tuple_slot)
5232 }
5233
5234 /*
5235 * Terminate EPQ execution if active
5236 */
5238
5239 /*
5240 * shut down subplan
5241 */
5243}
void EvalPlanQualEnd(EPQState *epqstate)
Definition: execMain.c:3169
void ExecCleanupTupleRouting(ModifyTableState *mtstate, PartitionTupleRouting *proute)
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:562
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
Definition: execTuples.c:1443
#define outerPlanState(node)
Definition: execnodes.h:1255
j
int j
Definition: isn.c:78
EndForeignModify_function EndForeignModify
Definition: fdwapi.h:237
ResultRelInfo * resultRelInfo
Definition: execnodes.h:1402
struct PartitionTupleRouting * mt_partition_tuple_routing
Definition: execnodes.h:1433
TupleTableSlot * mt_root_tuple_slot
Definition: execnodes.h:1430
EPQState mt_epqstate
Definition: execnodes.h:1412
PlanState ps
Definition: execnodes.h:1397
EState * state
Definition: execnodes.h:1161
TupleTableSlot ** ri_Slots
Definition: execnodes.h:545
int ri_NumSlotsInitialized
Definition: execnodes.h:543
struct FdwRoutine * ri_FdwRoutine
Definition: execnodes.h:533
TupleTableSlot ** ri_PlanSlots
Definition: execnodes.h:546
bool ri_usesFdwDirectModify
Definition: execnodes.h:539

References FdwRoutine::EndForeignModify, EvalPlanQualEnd(), ExecCleanupTupleRouting(), ExecDropSingleTupleTableSlot(), ExecEndNode(), i, j, ModifyTableState::mt_epqstate, ModifyTableState::mt_nrels, ModifyTableState::mt_partition_tuple_routing, ModifyTableState::mt_root_tuple_slot, outerPlanState, ModifyTableState::ps, ModifyTableState::resultRelInfo, ResultRelInfo::ri_FdwRoutine, ResultRelInfo::ri_NumSlotsInitialized, ResultRelInfo::ri_PlanSlots, ResultRelInfo::ri_Slots, ResultRelInfo::ri_usesFdwDirectModify, and PlanState::state.

Referenced by ExecEndNode().

ExecInitGenerated()

void ExecInitGenerated ( ResultRelInforesultRelInfo,
EStateestate,
CmdType  cmdtype 
)

Definition at line 430 of file nodeModifyTable.c.

433{
434 Relation rel = resultRelInfo->ri_RelationDesc;
435 TupleDesc tupdesc = RelationGetDescr(rel);
436 int natts = tupdesc->natts;
437 ExprState **ri_GeneratedExprs;
438 int ri_NumGeneratedNeeded;
439 Bitmapset *updatedCols;
440 MemoryContext oldContext;
441
442 /* Nothing to do if no generated columns */
443 if (!(tupdesc->constr && (tupdesc->constr->has_generated_stored || tupdesc->constr->has_generated_virtual)))
444 return;
445
446 /*
447 * In an UPDATE, we can skip computing any generated columns that do not
448 * depend on any UPDATE target column. But if there is a BEFORE ROW
449 * UPDATE trigger, we cannot skip because the trigger might change more
450 * columns.
451 */
452 if (cmdtype == CMD_UPDATE &&
454 updatedCols = ExecGetUpdatedCols(resultRelInfo, estate);
455 else
456 updatedCols = NULL;
457
458 /*
459 * Make sure these data structures are built in the per-query memory
460 * context so they'll survive throughout the query.
461 */
462 oldContext = MemoryContextSwitchTo(estate->es_query_cxt);
463
464 ri_GeneratedExprs = (ExprState **) palloc0(natts * sizeof(ExprState *));
465 ri_NumGeneratedNeeded = 0;
466
467 for (int i = 0; i < natts; i++)
468 {
469 char attgenerated = TupleDescAttr(tupdesc, i)->attgenerated;
470
471 if (attgenerated)
472 {
473 Expr *expr;
474
475 /* Fetch the GENERATED AS expression tree */
476 expr = (Expr *) build_column_default(rel, i + 1);
477 if (expr == NULL)
478 elog(ERROR, "no generation expression found for column number %d of table \"%s\"",
479 i + 1, RelationGetRelationName(rel));
480
481 /*
482 * If it's an update with a known set of update target columns,
483 * see if we can skip the computation.
484 */
485 if (updatedCols)
486 {
487 Bitmapset *attrs_used = NULL;
488
489 pull_varattnos((Node *) expr, 1, &attrs_used);
490
491 if (!bms_overlap(updatedCols, attrs_used))
492 continue; /* need not update this column */
493 }
494
495 /* No luck, so prepare the expression for execution */
496 if (attgenerated == ATTRIBUTE_GENERATED_STORED)
497 {
498 ri_GeneratedExprs[i] = ExecPrepareExpr(expr, estate);
499 ri_NumGeneratedNeeded++;
500 }
501
502 /* If UPDATE, mark column in resultRelInfo->ri_extraUpdatedCols */
503 if (cmdtype == CMD_UPDATE)
504 resultRelInfo->ri_extraUpdatedCols =
505 bms_add_member(resultRelInfo->ri_extraUpdatedCols,
507 }
508 }
509
510 if (ri_NumGeneratedNeeded == 0)
511 {
512 /* didn't need it after all */
513 pfree(ri_GeneratedExprs);
514 ri_GeneratedExprs = NULL;
515 }
516
517 /* Save in appropriate set of fields */
518 if (cmdtype == CMD_UPDATE)
519 {
520 /* Don't call twice */
521 Assert(resultRelInfo->ri_GeneratedExprsU == NULL);
522
523 resultRelInfo->ri_GeneratedExprsU = ri_GeneratedExprs;
524 resultRelInfo->ri_NumGeneratedNeededU = ri_NumGeneratedNeeded;
525
526 resultRelInfo->ri_extraUpdatedCols_valid = true;
527 }
528 else
529 {
530 /* Don't call twice */
531 Assert(resultRelInfo->ri_GeneratedExprsI == NULL);
532
533 resultRelInfo->ri_GeneratedExprsI = ri_GeneratedExprs;
534 resultRelInfo->ri_NumGeneratedNeededI = ri_NumGeneratedNeeded;
535 }
536
537 MemoryContextSwitchTo(oldContext);
538}
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:815
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:582
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:226
ExprState * ExecPrepareExpr(Expr *node, EState *estate)
Definition: execExpr.c:765
Bitmapset * ExecGetUpdatedCols(ResultRelInfo *relinfo, EState *estate)
Definition: execUtils.c:1382
void pfree(void *pointer)
Definition: mcxt.c:1594
void * palloc0(Size size)
Definition: mcxt.c:1395
#define RelationGetRelationName(relation)
Definition: rel.h:548
Node * build_column_default(Relation rel, int attrno)
MemoryContext es_query_cxt
Definition: execnodes.h:710
Definition: primnodes.h:189
Definition: nodes.h:135
TriggerDesc * trigdesc
Definition: rel.h:117
bool ri_extraUpdatedCols_valid
Definition: execnodes.h:500
Bitmapset * ri_extraUpdatedCols
Definition: execnodes.h:498
bool trig_update_before_row
Definition: reltrigger.h:61
bool has_generated_virtual
Definition: tupdesc.h:47
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:27
void pull_varattnos(Node *node, Index varno, Bitmapset **varattnos)
Definition: var.c:296

References Assert(), bms_add_member(), bms_overlap(), build_column_default(), CMD_UPDATE, TupleDescData::constr, elog, ERROR, EState::es_query_cxt, ExecGetUpdatedCols(), ExecPrepareExpr(), FirstLowInvalidHeapAttributeNumber, TupleConstr::has_generated_stored, TupleConstr::has_generated_virtual, i, MemoryContextSwitchTo(), TupleDescData::natts, palloc0(), pfree(), pull_varattnos(), RelationGetDescr, RelationGetRelationName, ResultRelInfo::ri_extraUpdatedCols, ResultRelInfo::ri_extraUpdatedCols_valid, ResultRelInfo::ri_GeneratedExprsI, ResultRelInfo::ri_GeneratedExprsU, ResultRelInfo::ri_NumGeneratedNeededI, ResultRelInfo::ri_NumGeneratedNeededU, ResultRelInfo::ri_RelationDesc, TriggerDesc::trig_update_before_row, RelationData::trigdesc, and TupleDescAttr().

Referenced by ExecComputeStoredGenerated(), and ExecGetExtraUpdatedCols().

ExecInitMergeTupleSlots()

void ExecInitMergeTupleSlots ( ModifyTableStatemtstate,
ResultRelInforesultRelInfo 
)

Definition at line 3948 of file nodeModifyTable.c.

3950{
3951 EState *estate = mtstate->ps.state;
3952
3953 Assert(!resultRelInfo->ri_projectNewInfoValid);
3954
3955 resultRelInfo->ri_oldTupleSlot =
3956 table_slot_create(resultRelInfo->ri_RelationDesc,
3957 &estate->es_tupleTable);
3958 resultRelInfo->ri_newTupleSlot =
3959 table_slot_create(resultRelInfo->ri_RelationDesc,
3960 &estate->es_tupleTable);
3961 resultRelInfo->ri_projectNewInfoValid = true;
3962}
Definition: execnodes.h:655
List * es_tupleTable
Definition: execnodes.h:712
bool ri_projectNewInfoValid
Definition: execnodes.h:509
TupleTableSlot * ri_oldTupleSlot
Definition: execnodes.h:507
TupleTableSlot * ri_newTupleSlot
Definition: execnodes.h:505
TupleTableSlot * table_slot_create(Relation relation, List **reglist)
Definition: tableam.c:92

References Assert(), EState::es_tupleTable, ModifyTableState::ps, ResultRelInfo::ri_newTupleSlot, ResultRelInfo::ri_oldTupleSlot, ResultRelInfo::ri_projectNewInfoValid, ResultRelInfo::ri_RelationDesc, PlanState::state, and table_slot_create().

Referenced by ExecInitMerge(), and ExecInitPartitionInfo().

ExecInitModifyTable()

ModifyTableState * ExecInitModifyTable ( ModifyTablenode,
EStateestate,
int  eflags 
)

Definition at line 4616 of file nodeModifyTable.c.

4617{
4618 ModifyTableState *mtstate;
4619 Plan *subplan = outerPlan(node);
4620 CmdType operation = node->operation;
4621 int total_nrels = list_length(node->resultRelations);
4622 int nrels;
4623 List *resultRelations = NIL;
4624 List *withCheckOptionLists = NIL;
4625 List *returningLists = NIL;
4626 List *updateColnosLists = NIL;
4627 List *mergeActionLists = NIL;
4628 List *mergeJoinConditions = NIL;
4629 ResultRelInfo *resultRelInfo;
4630 List *arowmarks;
4631 ListCell *l;
4632 int i;
4633 Relation rel;
4634
4635 /* check for unsupported flags */
4636 Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
4637
4638 /*
4639 * Only consider unpruned relations for initializing their ResultRelInfo
4640 * struct and other fields such as withCheckOptions, etc.
4641 *
4642 * Note: We must avoid pruning every result relation. This is important
4643 * for MERGE, since even if every result relation is pruned from the
4644 * subplan, there might still be NOT MATCHED rows, for which there may be
4645 * INSERT actions to perform. To allow these actions to be found, at
4646 * least one result relation must be kept. Also, when inserting into a
4647 * partitioned table, ExecInitPartitionInfo() needs a ResultRelInfo struct
4648 * as a reference for building the ResultRelInfo of the target partition.
4649 * In either case, it doesn't matter which result relation is kept, so we
4650 * just keep the first one, if all others have been pruned. See also,
4651 * ExecDoInitialPruning(), which ensures that this first result relation
4652 * has been locked.
4653 */
4654 i = 0;
4655 foreach(l, node->resultRelations)
4656 {
4657 Index rti = lfirst_int(l);
4658 bool keep_rel;
4659
4660 keep_rel = bms_is_member(rti, estate->es_unpruned_relids);
4661 if (!keep_rel && i == total_nrels - 1 && resultRelations == NIL)
4662 {
4663 /* all result relations pruned; keep the first one */
4664 keep_rel = true;
4665 rti = linitial_int(node->resultRelations);
4666 i = 0;
4667 }
4668
4669 if (keep_rel)
4670 {
4671 resultRelations = lappend_int(resultRelations, rti);
4672 if (node->withCheckOptionLists)
4673 {
4674 List *withCheckOptions = list_nth_node(List,
4676 i);
4677
4678 withCheckOptionLists = lappend(withCheckOptionLists, withCheckOptions);
4679 }
4680 if (node->returningLists)
4681 {
4682 List *returningList = list_nth_node(List,
4683 node->returningLists,
4684 i);
4685
4686 returningLists = lappend(returningLists, returningList);
4687 }
4688 if (node->updateColnosLists)
4689 {
4690 List *updateColnosList = list_nth(node->updateColnosLists, i);
4691
4692 updateColnosLists = lappend(updateColnosLists, updateColnosList);
4693 }
4694 if (node->mergeActionLists)
4695 {
4696 List *mergeActionList = list_nth(node->mergeActionLists, i);
4697
4698 mergeActionLists = lappend(mergeActionLists, mergeActionList);
4699 }
4700 if (node->mergeJoinConditions)
4701 {
4702 List *mergeJoinCondition = list_nth(node->mergeJoinConditions, i);
4703
4704 mergeJoinConditions = lappend(mergeJoinConditions, mergeJoinCondition);
4705 }
4706 }
4707 i++;
4708 }
4709 nrels = list_length(resultRelations);
4710 Assert(nrels > 0);
4711
4712 /*
4713 * create state structure
4714 */
4715 mtstate = makeNode(ModifyTableState);
4716 mtstate->ps.plan = (Plan *) node;
4717 mtstate->ps.state = estate;
4718 mtstate->ps.ExecProcNode = ExecModifyTable;
4719
4720 mtstate->operation = operation;
4721 mtstate->canSetTag = node->canSetTag;
4722 mtstate->mt_done = false;
4723
4724 mtstate->mt_nrels = nrels;
4725 mtstate->resultRelInfo = (ResultRelInfo *)
4726 palloc(nrels * sizeof(ResultRelInfo));
4727
4728 mtstate->mt_merge_pending_not_matched = NULL;
4729 mtstate->mt_merge_inserted = 0;
4730 mtstate->mt_merge_updated = 0;
4731 mtstate->mt_merge_deleted = 0;
4732 mtstate->mt_updateColnosLists = updateColnosLists;
4733 mtstate->mt_mergeActionLists = mergeActionLists;
4734 mtstate->mt_mergeJoinConditions = mergeJoinConditions;
4735
4736 /*----------
4737 * Resolve the target relation. This is the same as:
4738 *
4739 * - the relation for which we will fire FOR STATEMENT triggers,
4740 * - the relation into whose tuple format all captured transition tuples
4741 * must be converted, and
4742 * - the root partitioned table used for tuple routing.
4743 *
4744 * If it's a partitioned or inherited table, the root partition or
4745 * appendrel RTE doesn't appear elsewhere in the plan and its RT index is
4746 * given explicitly in node->rootRelation. Otherwise, the target relation
4747 * is the sole relation in the node->resultRelations list and, since it can
4748 * never be pruned, also in the resultRelations list constructed above.
4749 *----------
4750 */
4751 if (node->rootRelation > 0)
4752 {
4756 node->rootRelation);
4757 }
4758 else
4759 {
4760 Assert(list_length(node->resultRelations) == 1);
4761 Assert(list_length(resultRelations) == 1);
4762 mtstate->rootResultRelInfo = mtstate->resultRelInfo;
4763 ExecInitResultRelation(estate, mtstate->resultRelInfo,
4764 linitial_int(resultRelations));
4765 }
4766
4767 /* set up epqstate with dummy subplan data for the moment */
4768 EvalPlanQualInit(&mtstate->mt_epqstate, estate, NULL, NIL,
4769 node->epqParam, resultRelations);
4770 mtstate->fireBSTriggers = true;
4771
4772 /*
4773 * Build state for collecting transition tuples. This requires having a
4774 * valid trigger query context, so skip it in explain-only mode.
4775 */
4776 if (!(eflags & EXEC_FLAG_EXPLAIN_ONLY))
4777 ExecSetupTransitionCaptureState(mtstate, estate);
4778
4779 /*
4780 * Open all the result relations and initialize the ResultRelInfo structs.
4781 * (But root relation was initialized above, if it's part of the array.)
4782 * We must do this before initializing the subplan, because direct-modify
4783 * FDWs expect their ResultRelInfos to be available.
4784 */
4785 resultRelInfo = mtstate->resultRelInfo;
4786 i = 0;
4787 foreach(l, resultRelations)
4788 {
4789 Index resultRelation = lfirst_int(l);
4790 List *mergeActions = NIL;
4791
4792 if (mergeActionLists)
4793 mergeActions = list_nth(mergeActionLists, i);
4794
4795 if (resultRelInfo != mtstate->rootResultRelInfo)
4796 {
4797 ExecInitResultRelation(estate, resultRelInfo, resultRelation);
4798
4799 /*
4800 * For child result relations, store the root result relation
4801 * pointer. We do so for the convenience of places that want to
4802 * look at the query's original target relation but don't have the
4803 * mtstate handy.
4804 */
4805 resultRelInfo->ri_RootResultRelInfo = mtstate->rootResultRelInfo;
4806 }
4807
4808 /* Initialize the usesFdwDirectModify flag */
4809 resultRelInfo->ri_usesFdwDirectModify =
4811
4812 /*
4813 * Verify result relation is a valid target for the current operation
4814 */
4815 CheckValidResultRel(resultRelInfo, operation, node->onConflictAction,
4816 mergeActions);
4817
4818 resultRelInfo++;
4819 i++;
4820 }
4821
4822 /*
4823 * Now we may initialize the subplan.
4824 */
4825 outerPlanState(mtstate) = ExecInitNode(subplan, estate, eflags);
4826
4827 /*
4828 * Do additional per-result-relation initialization.
4829 */
4830 for (i = 0; i < nrels; i++)
4831 {
4832 resultRelInfo = &mtstate->resultRelInfo[i];
4833
4834 /* Let FDWs init themselves for foreign-table result rels */
4835 if (!resultRelInfo->ri_usesFdwDirectModify &&
4836 resultRelInfo->ri_FdwRoutine != NULL &&
4837 resultRelInfo->ri_FdwRoutine->BeginForeignModify != NULL)
4838 {
4839 List *fdw_private = (List *) list_nth(node->fdwPrivLists, i);
4840
4841 resultRelInfo->ri_FdwRoutine->BeginForeignModify(mtstate,
4842 resultRelInfo,
4843 fdw_private,
4844 i,
4845 eflags);
4846 }
4847
4848 /*
4849 * For UPDATE/DELETE/MERGE, find the appropriate junk attr now, either
4850 * a 'ctid' or 'wholerow' attribute depending on relkind. For foreign
4851 * tables, the FDW might have created additional junk attr(s), but
4852 * those are no concern of ours.
4853 */
4854 if (operation == CMD_UPDATE || operation == CMD_DELETE ||
4855 operation == CMD_MERGE)
4856 {
4857 char relkind;
4858
4859 relkind = resultRelInfo->ri_RelationDesc->rd_rel->relkind;
4860 if (relkind == RELKIND_RELATION ||
4861 relkind == RELKIND_MATVIEW ||
4862 relkind == RELKIND_PARTITIONED_TABLE)
4863 {
4864 resultRelInfo->ri_RowIdAttNo =
4865 ExecFindJunkAttributeInTlist(subplan->targetlist, "ctid");
4866 if (!AttributeNumberIsValid(resultRelInfo->ri_RowIdAttNo))
4867 elog(ERROR, "could not find junk ctid column");
4868 }
4869 else if (relkind == RELKIND_FOREIGN_TABLE)
4870 {
4871 /*
4872 * We don't support MERGE with foreign tables for now. (It's
4873 * problematic because the implementation uses CTID.)
4874 */
4875 Assert(operation != CMD_MERGE);
4876
4877 /*
4878 * When there is a row-level trigger, there should be a
4879 * wholerow attribute. We also require it to be present in
4880 * UPDATE and MERGE, so we can get the values of unchanged
4881 * columns.
4882 */
4883 resultRelInfo->ri_RowIdAttNo =
4885 "wholerow");
4886 if ((mtstate->operation == CMD_UPDATE || mtstate->operation == CMD_MERGE) &&
4887 !AttributeNumberIsValid(resultRelInfo->ri_RowIdAttNo))
4888 elog(ERROR, "could not find junk wholerow column");
4889 }
4890 else
4891 {
4892 /* Other valid target relkinds must provide wholerow */
4893 resultRelInfo->ri_RowIdAttNo =
4895 "wholerow");
4896 if (!AttributeNumberIsValid(resultRelInfo->ri_RowIdAttNo))
4897 elog(ERROR, "could not find junk wholerow column");
4898 }
4899 }
4900 }
4901
4902 /*
4903 * If this is an inherited update/delete/merge, there will be a junk
4904 * attribute named "tableoid" present in the subplan's targetlist. It
4905 * will be used to identify the result relation for a given tuple to be
4906 * updated/deleted/merged.
4907 */
4908 mtstate->mt_resultOidAttno =
4909 ExecFindJunkAttributeInTlist(subplan->targetlist, "tableoid");
4910 Assert(AttributeNumberIsValid(mtstate->mt_resultOidAttno) || total_nrels == 1);
4911 mtstate->mt_lastResultOid = InvalidOid; /* force lookup at first tuple */
4912 mtstate->mt_lastResultIndex = 0; /* must be zero if no such attr */
4913
4914 /* Get the root target relation */
4915 rel = mtstate->rootResultRelInfo->ri_RelationDesc;
4916
4917 /*
4918 * Build state for tuple routing if it's a partitioned INSERT. An UPDATE
4919 * or MERGE might need this too, but only if it actually moves tuples
4920 * between partitions; in that case setup is done by
4921 * ExecCrossPartitionUpdate.
4922 */
4923 if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE &&
4924 operation == CMD_INSERT)
4926 ExecSetupPartitionTupleRouting(estate, rel);
4927
4928 /*
4929 * Initialize any WITH CHECK OPTION constraints if needed.
4930 */
4931 resultRelInfo = mtstate->resultRelInfo;
4932 foreach(l, withCheckOptionLists)
4933 {
4934 List *wcoList = (List *) lfirst(l);
4935 List *wcoExprs = NIL;
4936 ListCell *ll;
4937
4938 foreach(ll, wcoList)
4939 {
4940 WithCheckOption *wco = (WithCheckOption *) lfirst(ll);
4941 ExprState *wcoExpr = ExecInitQual((List *) wco->qual,
4942 &mtstate->ps);
4943
4944 wcoExprs = lappend(wcoExprs, wcoExpr);
4945 }
4946
4947 resultRelInfo->ri_WithCheckOptions = wcoList;
4948 resultRelInfo->ri_WithCheckOptionExprs = wcoExprs;
4949 resultRelInfo++;
4950 }
4951
4952 /*
4953 * Initialize RETURNING projections if needed.
4954 */
4955 if (returningLists)
4956 {
4957 TupleTableSlot *slot;
4958 ExprContext *econtext;
4959
4960 /*
4961 * Initialize result tuple slot and assign its rowtype using the plan
4962 * node's declared targetlist, which the planner set up to be the same
4963 * as the first (before runtime pruning) RETURNING list. We assume
4964 * all the result rels will produce compatible output.
4965 */
4967 slot = mtstate->ps.ps_ResultTupleSlot;
4968
4969 /* Need an econtext too */
4970 if (mtstate->ps.ps_ExprContext == NULL)
4971 ExecAssignExprContext(estate, &mtstate->ps);
4972 econtext = mtstate->ps.ps_ExprContext;
4973
4974 /*
4975 * Build a projection for each result rel.
4976 */
4977 resultRelInfo = mtstate->resultRelInfo;
4978 foreach(l, returningLists)
4979 {
4980 List *rlist = (List *) lfirst(l);
4981
4982 resultRelInfo->ri_returningList = rlist;
4983 resultRelInfo->ri_projectReturning =
4984 ExecBuildProjectionInfo(rlist, econtext, slot, &mtstate->ps,
4985 resultRelInfo->ri_RelationDesc->rd_att);
4986 resultRelInfo++;
4987 }
4988 }
4989 else
4990 {
4991 /*
4992 * We still must construct a dummy result tuple type, because InitPlan
4993 * expects one (maybe should change that?).
4994 */
4995 ExecInitResultTypeTL(&mtstate->ps);
4996
4997 mtstate->ps.ps_ExprContext = NULL;
4998 }
4999
5000 /* Set the list of arbiter indexes if needed for ON CONFLICT */
5001 resultRelInfo = mtstate->resultRelInfo;
5002 if (node->onConflictAction != ONCONFLICT_NONE)
5003 {
5004 /* insert may only have one relation, inheritance is not expanded */
5005 Assert(total_nrels == 1);
5006 resultRelInfo->ri_onConflictArbiterIndexes = node->arbiterIndexes;
5007 }
5008
5009 /*
5010 * If needed, Initialize target list, projection and qual for ON CONFLICT
5011 * DO UPDATE.
5012 */
5014 {
5016 ExprContext *econtext;
5017 TupleDesc relationDesc;
5018
5019 /* already exists if created by RETURNING processing above */
5020 if (mtstate->ps.ps_ExprContext == NULL)
5021 ExecAssignExprContext(estate, &mtstate->ps);
5022
5023 econtext = mtstate->ps.ps_ExprContext;
5024 relationDesc = resultRelInfo->ri_RelationDesc->rd_att;
5025
5026 /* create state for DO UPDATE SET operation */
5027 resultRelInfo->ri_onConflict = onconfl;
5028
5029 /* initialize slot for the existing tuple */
5030 onconfl->oc_Existing =
5031 table_slot_create(resultRelInfo->ri_RelationDesc,
5032 &mtstate->ps.state->es_tupleTable);
5033
5034 /*
5035 * Create the tuple slot for the UPDATE SET projection. We want a slot
5036 * of the table's type here, because the slot will be used to insert
5037 * into the table, and for RETURNING processing - which may access
5038 * system attributes.
5039 */
5040 onconfl->oc_ProjSlot =
5041 table_slot_create(resultRelInfo->ri_RelationDesc,
5042 &mtstate->ps.state->es_tupleTable);
5043
5044 /* build UPDATE SET projection state */
5045 onconfl->oc_ProjInfo =
5047 true,
5048 node->onConflictCols,
5049 relationDesc,
5050 econtext,
5051 onconfl->oc_ProjSlot,
5052 &mtstate->ps);
5053
5054 /* initialize state to evaluate the WHERE clause, if any */
5055 if (node->onConflictWhere)
5056 {
5057 ExprState *qualexpr;
5058
5059 qualexpr = ExecInitQual((List *) node->onConflictWhere,
5060 &mtstate->ps);
5061 onconfl->oc_WhereClause = qualexpr;
5062 }
5063 }
5064
5065 /*
5066 * If we have any secondary relations in an UPDATE or DELETE, they need to
5067 * be treated like non-locked relations in SELECT FOR UPDATE, i.e., the
5068 * EvalPlanQual mechanism needs to be told about them. This also goes for
5069 * the source relations in a MERGE. Locate the relevant ExecRowMarks.
5070 */
5071 arowmarks = NIL;
5072 foreach(l, node->rowMarks)
5073 {
5075 ExecRowMark *erm;
5076 ExecAuxRowMark *aerm;
5077
5078 /*
5079 * Ignore "parent" rowmarks, because they are irrelevant at runtime.
5080 * Also ignore the rowmarks belonging to child tables that have been
5081 * pruned in ExecDoInitialPruning().
5082 */
5083 if (rc->isParent ||
5084 !bms_is_member(rc->rti, estate->es_unpruned_relids))
5085 continue;
5086
5087 /* Find ExecRowMark and build ExecAuxRowMark */
5088 erm = ExecFindRowMark(estate, rc->rti, false);
5089 aerm = ExecBuildAuxRowMark(erm, subplan->targetlist);
5090 arowmarks = lappend(arowmarks, aerm);
5091 }
5092
5093 /* For a MERGE command, initialize its state */
5094 if (mtstate->operation == CMD_MERGE)
5095 ExecInitMerge(mtstate, estate);
5096
5097 EvalPlanQualSetPlan(&mtstate->mt_epqstate, subplan, arowmarks);
5098
5099 /*
5100 * If there are a lot of result relations, use a hash table to speed the
5101 * lookups. If there are not a lot, a simple linear search is faster.
5102 *
5103 * It's not clear where the threshold is, but try 64 for starters. In a
5104 * debugging build, use a small threshold so that we get some test
5105 * coverage of both code paths.
5106 */
5107#ifdef USE_ASSERT_CHECKING
5108#define MT_NRELS_HASH 4
5109#else
5110#define MT_NRELS_HASH 64
5111#endif
5112 if (nrels >= MT_NRELS_HASH)
5113 {
5114 HASHCTL hash_ctl;
5115
5116 hash_ctl.keysize = sizeof(Oid);
5117 hash_ctl.entrysize = sizeof(MTTargetRelLookup);
5118 hash_ctl.hcxt = CurrentMemoryContext;
5119 mtstate->mt_resultOidHash =
5120 hash_create("ModifyTable target hash",
5121 nrels, &hash_ctl,
5123 for (i = 0; i < nrels; i++)
5124 {
5125 Oid hashkey;
5126 MTTargetRelLookup *mtlookup;
5127 bool found;
5128
5129 resultRelInfo = &mtstate->resultRelInfo[i];
5130 hashkey = RelationGetRelid(resultRelInfo->ri_RelationDesc);
5131 mtlookup = (MTTargetRelLookup *)
5132 hash_search(mtstate->mt_resultOidHash, &hashkey,
5133 HASH_ENTER, &found);
5134 Assert(!found);
5135 mtlookup->relationIndex = i;
5136 }
5137 }
5138 else
5139 mtstate->mt_resultOidHash = NULL;
5140
5141 /*
5142 * Determine if the FDW supports batch insert and determine the batch size
5143 * (a FDW may support batching, but it may be disabled for the
5144 * server/table).
5145 *
5146 * We only do this for INSERT, so that for UPDATE/DELETE the batch size
5147 * remains set to 0.
5148 */
5149 if (operation == CMD_INSERT)
5150 {
5151 /* insert may only have one relation, inheritance is not expanded */
5152 Assert(total_nrels == 1);
5153 resultRelInfo = mtstate->resultRelInfo;
5154 if (!resultRelInfo->ri_usesFdwDirectModify &&
5155 resultRelInfo->ri_FdwRoutine != NULL &&
5156 resultRelInfo->ri_FdwRoutine->GetForeignModifyBatchSize &&
5157 resultRelInfo->ri_FdwRoutine->ExecForeignBatchInsert)
5158 {
5159 resultRelInfo->ri_BatchSize =
5160 resultRelInfo->ri_FdwRoutine->GetForeignModifyBatchSize(resultRelInfo);
5161 Assert(resultRelInfo->ri_BatchSize >= 1);
5162 }
5163 else
5164 resultRelInfo->ri_BatchSize = 1;
5165 }
5166
5167 /*
5168 * Lastly, if this is not the primary (canSetTag) ModifyTable node, add it
5169 * to estate->es_auxmodifytables so that it will be run to completion by
5170 * ExecPostprocessPlan. (It'd actually work fine to add the primary
5171 * ModifyTable node too, but there's no need.) Note the use of lcons not
5172 * lappend: we need later-initialized ModifyTable nodes to be shut down
5173 * before earlier ones. This ensures that we don't throw away RETURNING
5174 * rows that need to be seen by a later CTE subplan.
5175 */
5176 if (!mtstate->canSetTag)
5177 estate->es_auxmodifytables = lcons(mtstate,
5178 estate->es_auxmodifytables);
5179
5180 return mtstate;
5181}
#define AttributeNumberIsValid(attributeNumber)
Definition: attnum.h:34
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:510
unsigned int Index
Definition: c.h:619
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:952
HTAB * hash_create(const char *tabname, int64 nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:358
ProjectionInfo * ExecBuildProjectionInfo(List *targetList, ExprContext *econtext, TupleTableSlot *slot, PlanState *parent, TupleDesc inputDesc)
Definition: execExpr.c:370
ExprState * ExecInitQual(List *qual, PlanState *parent)
Definition: execExpr.c:229
ProjectionInfo * ExecBuildUpdateProjection(List *targetList, bool evalTargetList, List *targetColnos, TupleDesc relDesc, ExprContext *econtext, TupleTableSlot *slot, PlanState *parent)
Definition: execExpr.c:547
AttrNumber ExecFindJunkAttributeInTlist(List *targetlist, const char *attrName)
Definition: execJunk.c:222
ExecRowMark * ExecFindRowMark(EState *estate, Index rti, bool missing_ok)
Definition: execMain.c:2546
ExecAuxRowMark * ExecBuildAuxRowMark(ExecRowMark *erm, List *targetlist)
Definition: execMain.c:2569
void CheckValidResultRel(ResultRelInfo *resultRelInfo, CmdType operation, OnConflictAction onConflictAction, List *mergeActions)
Definition: execMain.c:1050
void EvalPlanQualInit(EPQState *epqstate, EState *parentestate, Plan *subplan, List *auxrowmarks, int epqParam, List *resultRelations)
Definition: execMain.c:2708
void EvalPlanQualSetPlan(EPQState *epqstate, Plan *subplan, List *auxrowmarks)
Definition: execMain.c:2750
PartitionTupleRouting * ExecSetupPartitionTupleRouting(EState *estate, Relation rel)
Definition: execPartition.c:218
PlanState * ExecInitNode(Plan *node, EState *estate, int eflags)
Definition: execProcnode.c:142
const TupleTableSlotOps TTSOpsVirtual
Definition: execTuples.c:84
void ExecInitResultTypeTL(PlanState *planstate)
Definition: execTuples.c:1944
void ExecInitResultTupleSlotTL(PlanState *planstate, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1988
void ExecInitResultRelation(EState *estate, ResultRelInfo *resultRelInfo, Index rti)
Definition: execUtils.c:880
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition: execUtils.c:485
#define EXEC_FLAG_BACKWARD
Definition: executor.h:69
#define EXEC_FLAG_EXPLAIN_ONLY
Definition: executor.h:66
#define EXEC_FLAG_MARK
Definition: executor.h:70
@ HASH_ENTER
Definition: hsearch.h:114
#define HASH_CONTEXT
Definition: hsearch.h:102
#define HASH_ELEM
Definition: hsearch.h:95
#define HASH_BLOBS
Definition: hsearch.h:97
List * lappend(List *list, void *datum)
Definition: list.c:339
List * lappend_int(List *list, int datum)
Definition: list.c:357
List * lcons(void *datum, List *list)
Definition: list.c:495
MemoryContext CurrentMemoryContext
Definition: mcxt.c:160
static void ExecSetupTransitionCaptureState(ModifyTableState *mtstate, EState *estate)
static TupleTableSlot * ExecModifyTable(PlanState *pstate)
struct MTTargetRelLookup MTTargetRelLookup
#define MT_NRELS_HASH
static void ExecInitMerge(ModifyTableState *mtstate, EState *estate)
@ ONCONFLICT_NONE
Definition: nodes.h:428
@ ONCONFLICT_UPDATE
Definition: nodes.h:430
CmdType
Definition: nodes.h:273
@ CMD_MERGE
Definition: nodes.h:279
@ CMD_INSERT
Definition: nodes.h:277
@ CMD_DELETE
Definition: nodes.h:278
#define makeNode(_type_)
Definition: nodes.h:161
#define lfirst(lc)
Definition: pg_list.h:172
#define lfirst_node(type, lc)
Definition: pg_list.h:176
static int list_length(const List *l)
Definition: pg_list.h:152
#define NIL
Definition: pg_list.h:68
#define lfirst_int(lc)
Definition: pg_list.h:173
#define linitial_int(l)
Definition: pg_list.h:179
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
#define outerPlan(node)
Definition: plannodes.h:252
#define InvalidOid
Definition: postgres_ext.h:37
unsigned int Oid
Definition: postgres_ext.h:32
#define RelationGetRelid(relation)
Definition: rel.h:514
Bitmapset * es_unpruned_relids
Definition: execnodes.h:673
List * es_auxmodifytables
Definition: execnodes.h:727
BeginForeignModify_function BeginForeignModify
Definition: fdwapi.h:231
ExecForeignBatchInsert_function ExecForeignBatchInsert
Definition: fdwapi.h:233
GetForeignModifyBatchSize_function GetForeignModifyBatchSize
Definition: fdwapi.h:234
Definition: hsearch.h:66
Size keysize
Definition: hsearch.h:75
Size entrysize
Definition: hsearch.h:76
MemoryContext hcxt
Definition: hsearch.h:86
Definition: pg_list.h:54
List * mt_mergeJoinConditions
Definition: execnodes.h:1466
CmdType operation
Definition: execnodes.h:1398
TupleTableSlot * mt_merge_pending_not_matched
Definition: execnodes.h:1452
int mt_resultOidAttno
Definition: execnodes.h:1421
double mt_merge_deleted
Definition: execnodes.h:1457
List * mt_updateColnosLists
Definition: execnodes.h:1464
double mt_merge_inserted
Definition: execnodes.h:1455
Oid mt_lastResultOid
Definition: execnodes.h:1422
double mt_merge_updated
Definition: execnodes.h:1456
bool fireBSTriggers
Definition: execnodes.h:1413
List * mt_mergeActionLists
Definition: execnodes.h:1465
HTAB * mt_resultOidHash
Definition: execnodes.h:1424
ResultRelInfo * rootResultRelInfo
Definition: execnodes.h:1410
int mt_lastResultIndex
Definition: execnodes.h:1423
List * updateColnosLists
Definition: plannodes.h:337
List * arbiterIndexes
Definition: plannodes.h:357
List * onConflictCols
Definition: plannodes.h:361
List * mergeJoinConditions
Definition: plannodes.h:371
CmdType operation
Definition: plannodes.h:325
int epqParam
Definition: plannodes.h:353
List * resultRelations
Definition: plannodes.h:335
Bitmapset * fdwDirectModifyPlans
Definition: plannodes.h:349
List * onConflictSet
Definition: plannodes.h:359
List * mergeActionLists
Definition: plannodes.h:369
bool canSetTag
Definition: plannodes.h:327
List * fdwPrivLists
Definition: plannodes.h:347
List * returningLists
Definition: plannodes.h:345
List * withCheckOptionLists
Definition: plannodes.h:339
Index rootRelation
Definition: plannodes.h:331
Node * onConflictWhere
Definition: plannodes.h:363
List * rowMarks
Definition: plannodes.h:351
OnConflictAction onConflictAction
Definition: plannodes.h:355
TupleTableSlot * oc_ProjSlot
Definition: execnodes.h:434
TupleTableSlot * oc_Existing
Definition: execnodes.h:433
ExprState * oc_WhereClause
Definition: execnodes.h:436
ProjectionInfo * oc_ProjInfo
Definition: execnodes.h:435
Index rti
Definition: plannodes.h:1583
bool isParent
Definition: plannodes.h:1597
Plan * plan
Definition: execnodes.h:1159
ExprContext * ps_ExprContext
Definition: execnodes.h:1198
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:1197
ExecProcNodeMtd ExecProcNode
Definition: execnodes.h:1165
Definition: plannodes.h:177
List * targetlist
Definition: plannodes.h:220
TupleDesc rd_att
Definition: rel.h:112
Form_pg_class rd_rel
Definition: rel.h:111
OnConflictSetState * ri_onConflict
Definition: execnodes.h:583
List * ri_onConflictArbiterIndexes
Definition: execnodes.h:580
struct ResultRelInfo * ri_RootResultRelInfo
Definition: execnodes.h:618
List * ri_WithCheckOptions
Definition: execnodes.h:549
List * ri_WithCheckOptionExprs
Definition: execnodes.h:552
ProjectionInfo * ri_projectReturning
Definition: execnodes.h:577
List * ri_returningList
Definition: execnodes.h:574
AttrNumber ri_RowIdAttNo
Definition: execnodes.h:495
int ri_BatchSize
Definition: execnodes.h:544
Definition: pg_list.h:46

References ModifyTable::arbiterIndexes, Assert(), AttributeNumberIsValid, FdwRoutine::BeginForeignModify, bms_is_member(), ModifyTableState::canSetTag, ModifyTable::canSetTag, CheckValidResultRel(), CMD_DELETE, CMD_INSERT, CMD_MERGE, CMD_UPDATE, CurrentMemoryContext, elog, HASHCTL::entrysize, ModifyTable::epqParam, ERROR, EState::es_auxmodifytables, EState::es_tupleTable, EState::es_unpruned_relids, EvalPlanQualInit(), EvalPlanQualSetPlan(), EXEC_FLAG_BACKWARD, EXEC_FLAG_EXPLAIN_ONLY, EXEC_FLAG_MARK, ExecAssignExprContext(), ExecBuildAuxRowMark(), ExecBuildProjectionInfo(), ExecBuildUpdateProjection(), ExecFindJunkAttributeInTlist(), ExecFindRowMark(), FdwRoutine::ExecForeignBatchInsert, ExecInitMerge(), ExecInitNode(), ExecInitQual(), ExecInitResultRelation(), ExecInitResultTupleSlotTL(), ExecInitResultTypeTL(), ExecModifyTable(), PlanState::ExecProcNode, ExecSetupPartitionTupleRouting(), ExecSetupTransitionCaptureState(), ModifyTable::fdwDirectModifyPlans, ModifyTable::fdwPrivLists, ModifyTableState::fireBSTriggers, FdwRoutine::GetForeignModifyBatchSize, HASH_BLOBS, HASH_CONTEXT, hash_create(), HASH_ELEM, HASH_ENTER, hash_search(), HASHCTL::hcxt, i, InvalidOid, PlanRowMark::isParent, HASHCTL::keysize, lappend(), lappend_int(), lcons(), lfirst, lfirst_int, lfirst_node, linitial_int, list_length(), list_nth(), list_nth_node, makeNode, ModifyTable::mergeActionLists, ModifyTable::mergeJoinConditions, ModifyTableState::mt_done, ModifyTableState::mt_epqstate, ModifyTableState::mt_lastResultIndex, ModifyTableState::mt_lastResultOid, ModifyTableState::mt_merge_deleted, ModifyTableState::mt_merge_inserted, ModifyTableState::mt_merge_pending_not_matched, ModifyTableState::mt_merge_updated, ModifyTableState::mt_mergeActionLists, ModifyTableState::mt_mergeJoinConditions, ModifyTableState::mt_nrels, MT_NRELS_HASH, ModifyTableState::mt_partition_tuple_routing, ModifyTableState::mt_resultOidAttno, ModifyTableState::mt_resultOidHash, ModifyTableState::mt_updateColnosLists, NIL, OnConflictSetState::oc_Existing, OnConflictSetState::oc_ProjInfo, OnConflictSetState::oc_ProjSlot, OnConflictSetState::oc_WhereClause, ONCONFLICT_NONE, ONCONFLICT_UPDATE, ModifyTable::onConflictAction, ModifyTable::onConflictCols, ModifyTable::onConflictSet, ModifyTable::onConflictWhere, ModifyTableState::operation, ModifyTable::operation, outerPlan, outerPlanState, palloc(), PlanState::plan, ModifyTableState::ps, PlanState::ps_ExprContext, PlanState::ps_ResultTupleSlot, WithCheckOption::qual, RelationData::rd_att, RelationData::rd_rel, RelationGetRelid, MTTargetRelLookup::relationIndex, ModifyTable::resultRelations, ModifyTableState::resultRelInfo, ModifyTable::returningLists, ResultRelInfo::ri_BatchSize, ResultRelInfo::ri_FdwRoutine, ResultRelInfo::ri_onConflict, ResultRelInfo::ri_onConflictArbiterIndexes, ResultRelInfo::ri_projectReturning, ResultRelInfo::ri_RelationDesc, ResultRelInfo::ri_returningList, ResultRelInfo::ri_RootResultRelInfo, ResultRelInfo::ri_RowIdAttNo, ResultRelInfo::ri_usesFdwDirectModify, ResultRelInfo::ri_WithCheckOptionExprs, ResultRelInfo::ri_WithCheckOptions, ModifyTable::rootRelation, ModifyTableState::rootResultRelInfo, ModifyTable::rowMarks, PlanRowMark::rti, PlanState::state, table_slot_create(), Plan::targetlist, TTSOpsVirtual, ModifyTable::updateColnosLists, and ModifyTable::withCheckOptionLists.

Referenced by ExecInitNode().

ExecReScanModifyTable()

void ExecReScanModifyTable ( ModifyTableStatenode )

Definition at line 5246 of file nodeModifyTable.c.

5247{
5248 /*
5249 * Currently, we don't need to support rescan on ModifyTable nodes. The
5250 * semantics of that would be a bit debatable anyway.
5251 */
5252 elog(ERROR, "ExecReScanModifyTable is not implemented");
5253}

References elog, and ERROR.

Referenced by ExecReScan().

AltStyle によって変換されたページ (->オリジナル) /