diff options
Diffstat (limited to 'src/include')
-rw-r--r-- | src/include/access/heapam.h | 13 | ||||
-rw-r--r-- | src/include/commands/trigger.h | 6 | ||||
-rw-r--r-- | src/include/executor/execPartition.h | 1 | ||||
-rw-r--r-- | src/include/executor/instrument.h | 7 | ||||
-rw-r--r-- | src/include/executor/nodeModifyTable.h | 21 | ||||
-rw-r--r-- | src/include/executor/spi.h | 1 | ||||
-rw-r--r-- | src/include/nodes/execnodes.h | 65 | ||||
-rw-r--r-- | src/include/nodes/nodes.h | 6 | ||||
-rw-r--r-- | src/include/nodes/parsenodes.h | 37 | ||||
-rw-r--r-- | src/include/nodes/plannodes.h | 8 | ||||
-rw-r--r-- | src/include/nodes/relation.h | 7 | ||||
-rw-r--r-- | src/include/optimizer/pathnode.h | 7 | ||||
-rw-r--r-- | src/include/parser/analyze.h | 5 | ||||
-rw-r--r-- | src/include/parser/kwlist.h | 2 | ||||
-rw-r--r-- | src/include/parser/parse_clause.h | 5 | ||||
-rw-r--r-- | src/include/parser/parse_node.h | 5 | ||||
-rw-r--r-- | src/include/rewrite/rewriteHandler.h | 1 |
17 files changed, 177 insertions, 20 deletions
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h index 4c0256b18a4..608f50b0616 100644 --- a/src/include/access/heapam.h +++ b/src/include/access/heapam.h @@ -53,23 +53,34 @@ typedef enum LockTupleMode * When heap_update, heap_delete, or heap_lock_tuple fail because the target * tuple is already outdated, they fill in this struct to provide information * to the caller about what happened. + * + * result is the result of HeapTupleSatisfiesUpdate, leading to the failure. + * It's set to HeapTupleMayBeUpdated when there is no failure. + * * ctid is the target's ctid link: it is the same as the target's TID if the * target was deleted, or the location of the replacement tuple if the target * was updated. + * * xmax is the outdating transaction's XID. If the caller wants to visit the * replacement tuple, it must check that this matches before believing the * replacement is really a match. + * * cmax is the outdating command's CID, but only when the failure code is * HeapTupleSelfUpdated (i.e., something in the current transaction outdated * the tuple); otherwise cmax is zero. (We make this restriction because * HeapTupleHeaderGetCmax doesn't work for tuples outdated in other * transactions.) + * + * lockmode is only relevant for callers of heap_update() and is the mode which + * the caller should use in case it needs to lock the updated tuple. */ typedef struct HeapUpdateFailureData { + HTSU_Result result; ItemPointerData ctid; TransactionId xmax; CommandId cmax; + LockTupleMode lockmode; } HeapUpdateFailureData; @@ -162,7 +173,7 @@ extern void heap_abort_speculative(Relation relation, HeapTuple tuple); extern HTSU_Result heap_update(Relation relation, ItemPointer otid, HeapTuple newtup, CommandId cid, Snapshot crosscheck, bool wait, - HeapUpdateFailureData *hufd, LockTupleMode *lockmode); + HeapUpdateFailureData *hufd); extern HTSU_Result heap_lock_tuple(Relation relation, HeapTuple tuple, CommandId cid, LockTupleMode mode, LockWaitPolicy wait_policy, bool follow_update, diff --git a/src/include/commands/trigger.h b/src/include/commands/trigger.h index a5b8610fa22..1b79a803103 100644 --- a/src/include/commands/trigger.h +++ b/src/include/commands/trigger.h @@ -206,7 +206,8 @@ extern bool ExecBRDeleteTriggers(EState *estate, EPQState *epqstate, ResultRelInfo *relinfo, ItemPointer tupleid, - HeapTuple fdw_trigtuple); + HeapTuple fdw_trigtuple, + HeapUpdateFailureData *hufdp); extern void ExecARDeleteTriggers(EState *estate, ResultRelInfo *relinfo, ItemPointer tupleid, @@ -225,7 +226,8 @@ extern TupleTableSlot *ExecBRUpdateTriggers(EState *estate, ResultRelInfo *relinfo, ItemPointer tupleid, HeapTuple fdw_trigtuple, - TupleTableSlot *slot); + TupleTableSlot *slot, + HeapUpdateFailureData *hufdp); extern void ExecARUpdateTriggers(EState *estate, ResultRelInfo *relinfo, ItemPointer tupleid, diff --git a/src/include/executor/execPartition.h b/src/include/executor/execPartition.h index 03a599ad57a..9f55f6409ef 100644 --- a/src/include/executor/execPartition.h +++ b/src/include/executor/execPartition.h @@ -114,6 +114,7 @@ extern int ExecFindPartition(ResultRelInfo *resultRelInfo, PartitionDispatch *pd, TupleTableSlot *slot, EState *estate); +extern int ExecFindPartitionByOid(PartitionTupleRouting *proute, Oid partoid); extern ResultRelInfo *ExecInitPartitionInfo(ModifyTableState *mtstate, ResultRelInfo *resultRelInfo, PartitionTupleRouting *proute, diff --git a/src/include/executor/instrument.h b/src/include/executor/instrument.h index b72f91898ad..28eb0093d47 100644 --- a/src/include/executor/instrument.h +++ b/src/include/executor/instrument.h @@ -58,8 +58,11 @@ typedef struct Instrumentation double total; /* Total total time (in seconds) */ double ntuples; /* Total tuples produced */ double nloops; /* # of run cycles for this node */ - double nfiltered1; /* # tuples removed by scanqual or joinqual */ - double nfiltered2; /* # tuples removed by "other" quals */ + double nfiltered1; /* # tuples removed by scanqual or joinqual OR + * # tuples inserted by MERGE */ + double nfiltered2; /* # tuples removed by "other" quals OR + * # tuples updated by MERGE */ + double nfiltered3; /* # tuples deleted by MERGE */ BufferUsage bufusage; /* Total buffer usage */ } Instrumentation; diff --git a/src/include/executor/nodeModifyTable.h b/src/include/executor/nodeModifyTable.h index 0d7e579e1cb..686cfa61710 100644 --- a/src/include/executor/nodeModifyTable.h +++ b/src/include/executor/nodeModifyTable.h @@ -18,5 +18,26 @@ extern ModifyTableState *ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags); extern void ExecEndModifyTable(ModifyTableState *node); extern void ExecReScanModifyTable(ModifyTableState *node); +extern TupleTableSlot *ExecPrepareTupleRouting(ModifyTableState *mtstate, + EState *estate, + struct PartitionTupleRouting *proute, + ResultRelInfo *targetRelInfo, + TupleTableSlot *slot); +extern TupleTableSlot *ExecDelete(ModifyTableState *mtstate, + ItemPointer tupleid, HeapTuple oldtuple, TupleTableSlot *planSlot, + EPQState *epqstate, EState *estate, bool *tupleDeleted, + bool processReturning, HeapUpdateFailureData *hufdp, + MergeActionState *actionState, bool canSetTag); +extern TupleTableSlot *ExecUpdate(ModifyTableState *mtstate, + ItemPointer tupleid, HeapTuple oldtuple, TupleTableSlot *slot, + TupleTableSlot *planSlot, EPQState *epqstate, EState *estate, + bool *tuple_updated, HeapUpdateFailureData *hufdp, + MergeActionState *actionState, bool canSetTag); +extern TupleTableSlot *ExecInsert(ModifyTableState *mtstate, + TupleTableSlot *slot, + TupleTableSlot *planSlot, + EState *estate, + MergeActionState *actionState, + bool canSetTag); #endif /* NODEMODIFYTABLE_H */ diff --git a/src/include/executor/spi.h b/src/include/executor/spi.h index e5bdaecc4e3..78410b9f772 100644 --- a/src/include/executor/spi.h +++ b/src/include/executor/spi.h @@ -64,6 +64,7 @@ typedef struct _SPI_plan *SPIPlanPtr; #define SPI_OK_REL_REGISTER 15 #define SPI_OK_REL_UNREGISTER 16 #define SPI_OK_TD_REGISTER 17 +#define SPI_OK_MERGE 18 #define SPI_OPT_NONATOMIC (1 << 0) diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h index 6070a42b6fe..ff63d179b2a 100644 --- a/src/include/nodes/execnodes.h +++ b/src/include/nodes/execnodes.h @@ -360,8 +360,17 @@ typedef struct JunkFilter AttrNumber *jf_cleanMap; TupleTableSlot *jf_resultSlot; AttrNumber jf_junkAttNo; + AttrNumber jf_otherJunkAttNo; } JunkFilter; +typedef struct MergeState +{ + /* List of MERGE MATCHED action states */ + List *matchedActionStates; + /* List of MERGE NOT MATCHED action states */ + List *notMatchedActionStates; +} MergeState; + /* * OnConflictSetState * @@ -452,8 +461,38 @@ typedef struct ResultRelInfo /* relation descriptor for root partitioned table */ Relation ri_PartitionRoot; + + int ri_PartitionLeafIndex; + /* for running MERGE on this result relation */ + MergeState *ri_mergeState; + + /* + * While executing MERGE, the target relation is processed twice; once + * as a target relation and once to run a join between the target and the + * source. We generate two different RTEs for these two purposes, one with + * rte->inh set to false and other with rte->inh set to true. + * + * Since the plan re-evaluated by EvalPlanQual uses the join RTE, we must + * install the updated tuple in the scan corresponding to that RTE. The + * following member tracks the index of the second RTE for EvalPlanQual + * purposes. ri_mergeTargetRTI is non-zero only when MERGE is in-progress. + * We use ri_mergeTargetRTI to run EvalPlanQual for MERGE and + * ri_RangeTableIndex elsewhere. + */ + Index ri_mergeTargetRTI; } ResultRelInfo; +/* + * Get the Range table index for EvalPlanQual. + * + * We use the ri_mergeTargetRTI if set, otherwise use ri_RangeTableIndex. + * ri_mergeTargetRTI should really be ever set iff we're running MERGE. + */ +#define GetEPQRangeTableIndex(r) \ + (((r)->ri_mergeTargetRTI > 0) \ + ? (r)->ri_mergeTargetRTI \ + : (r)->ri_RangeTableIndex) + /* ---------------- * EState information * @@ -966,6 +1005,11 @@ typedef struct PlanState if (((PlanState *)(node))->instrument) \ ((PlanState *)(node))->instrument->nfiltered2 += (delta); \ } while(0) +#define InstrCountFiltered3(node, delta) \ + do { \ + if (((PlanState *)(node))->instrument) \ + ((PlanState *)(node))->instrument->nfiltered3 += (delta); \ + } while(0) /* * EPQState is state for executing an EvalPlanQual recheck on a candidate @@ -1013,13 +1057,27 @@ typedef struct ProjectSetState } ProjectSetState; /* ---------------- + * MergeActionState information + * ---------------- + */ +typedef struct MergeActionState +{ + NodeTag type; + bool matched; /* true=MATCHED, false=NOT MATCHED */ + ExprState *whenqual; /* WHEN AND conditions */ + CmdType commandType; /* INSERT/UPDATE/DELETE/DO NOTHING */ + ProjectionInfo *proj; /* tuple projection info */ + TupleDesc tupDesc; /* tuple descriptor for projection */ +} MergeActionState; + +/* ---------------- * ModifyTableState information * ---------------- */ typedef struct ModifyTableState { PlanState ps; /* its first field is NodeTag */ - CmdType operation; /* INSERT, UPDATE, or DELETE */ + CmdType operation; /* INSERT, UPDATE, DELETE or MERGE */ bool canSetTag; /* do we set the command tag/es_processed? */ bool mt_done; /* are we done? */ PlanState **mt_plans; /* subplans (one per target rel) */ @@ -1035,6 +1093,8 @@ typedef struct ModifyTableState List *mt_excludedtlist; /* the excluded pseudo relation's tlist */ TupleTableSlot *mt_conflproj; /* CONFLICT ... SET ... projection target */ + TupleTableSlot *mt_mergeproj; /* MERGE action projection target */ + /* Tuple-routing support info */ struct PartitionTupleRouting *mt_partition_tuple_routing; @@ -1046,6 +1106,9 @@ typedef struct ModifyTableState /* Per plan map for tuple conversion from child to root */ TupleConversionMap **mt_per_subplan_tupconv_maps; + + /* Flags showing which subcommands are present INS/UPD/DEL/DO NOTHING */ + int mt_merge_subcommands; } ModifyTableState; /* ---------------- diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h index 443de227041..fce48026b6d 100644 --- a/src/include/nodes/nodes.h +++ b/src/include/nodes/nodes.h @@ -97,6 +97,7 @@ typedef enum NodeTag T_PlanState, T_ResultState, T_ProjectSetState, + T_MergeActionState, T_ModifyTableState, T_AppendState, T_MergeAppendState, @@ -308,6 +309,8 @@ typedef enum NodeTag T_InsertStmt, T_DeleteStmt, T_UpdateStmt, + T_MergeStmt, + T_MergeAction, T_SelectStmt, T_AlterTableStmt, T_AlterTableCmd, @@ -657,7 +660,8 @@ typedef enum CmdType CMD_SELECT, /* select stmt */ CMD_UPDATE, /* update stmt */ CMD_INSERT, /* insert stmt */ - CMD_DELETE, + CMD_DELETE, /* delete stmt */ + CMD_MERGE, /* merge stmt */ CMD_UTILITY, /* cmds like create, destroy, copy, vacuum, * etc. */ CMD_NOTHING /* dummy command for instead nothing rules diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 92082b3a7a2..d005beeba82 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -38,7 +38,7 @@ typedef enum OverridingKind typedef enum QuerySource { QSRC_ORIGINAL, /* original parsetree (explicit query) */ - QSRC_PARSER, /* added by parse analysis (now unused) */ + QSRC_PARSER, /* added by parse analysis in MERGE */ QSRC_INSTEAD_RULE, /* added by unconditional INSTEAD rule */ QSRC_QUAL_INSTEAD_RULE, /* added by conditional INSTEAD rule */ QSRC_NON_INSTEAD_RULE /* added by non-INSTEAD rule */ @@ -107,7 +107,7 @@ typedef struct Query { NodeTag type; - CmdType commandType; /* select|insert|update|delete|utility */ + CmdType commandType; /* select|insert|update|delete|merge|utility */ QuerySource querySource; /* where did I come from? */ @@ -118,7 +118,7 @@ typedef struct Query Node *utilityStmt; /* non-null if commandType == CMD_UTILITY */ int resultRelation; /* rtable index of target relation for - * INSERT/UPDATE/DELETE; 0 for SELECT */ + * INSERT/UPDATE/DELETE/MERGE; 0 for SELECT */ bool hasAggs; /* has aggregates in tlist or havingQual */ bool hasWindowFuncs; /* has window functions in tlist */ @@ -169,6 +169,9 @@ typedef struct Query List *withCheckOptions; /* a list of WithCheckOption's, which are * only added during rewrite and therefore * are not written out as part of Query. */ + int mergeTarget_relation; + List *mergeSourceTargetList; + List *mergeActionList; /* list of actions for MERGE (only) */ /* * The following two fields identify the portion of the source text string @@ -1128,7 +1131,9 @@ typedef enum WCOKind WCO_VIEW_CHECK, /* WCO on an auto-updatable view */ WCO_RLS_INSERT_CHECK, /* RLS INSERT WITH CHECK policy */ WCO_RLS_UPDATE_CHECK, /* RLS UPDATE WITH CHECK policy */ - WCO_RLS_CONFLICT_CHECK /* RLS ON CONFLICT DO UPDATE USING policy */ + WCO_RLS_CONFLICT_CHECK, /* RLS ON CONFLICT DO UPDATE USING policy */ + WCO_RLS_MERGE_UPDATE_CHECK, /* RLS MERGE UPDATE USING policy */ + WCO_RLS_MERGE_DELETE_CHECK /* RLS MERGE DELETE USING policy */ } WCOKind; typedef struct WithCheckOption @@ -1504,6 +1509,30 @@ typedef struct UpdateStmt } UpdateStmt; /* ---------------------- + * Merge Statement + * ---------------------- + */ +typedef struct MergeStmt +{ + NodeTag type; + RangeVar *relation; /* target relation to merge into */ + Node *source_relation; /* source relation */ + Node *join_condition; /* join condition between source and target */ + List *mergeActionList; /* list of MergeAction(s) */ +} MergeStmt; + +typedef struct MergeAction +{ + NodeTag type; + bool matched; /* true=MATCHED, false=NOT MATCHED */ + Node *condition; /* WHEN AND conditions (raw parser) */ + Node *qual; /* transformed WHEN AND conditions */ + CmdType commandType; /* INSERT/UPDATE/DELETE/DO NOTHING */ + Node *stmt; /* T_UpdateStmt etc */ + List *targetList; /* the target list (of ResTarget) */ +} MergeAction; + +/* ---------------------- * Select Statement * * A "simple" SELECT is represented in the output of gram.y by a single diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h index c922216b7d1..0a797f0a052 100644 --- a/src/include/nodes/plannodes.h +++ b/src/include/nodes/plannodes.h @@ -18,6 +18,7 @@ #include "lib/stringinfo.h" #include "nodes/bitmapset.h" #include "nodes/lockoptions.h" +#include "nodes/parsenodes.h" #include "nodes/primnodes.h" @@ -42,7 +43,7 @@ typedef struct PlannedStmt { NodeTag type; - CmdType commandType; /* select|insert|update|delete|utility */ + CmdType commandType; /* select|insert|update|delete|merge|utility */ uint64 queryId; /* query identifier (copied from Query) */ @@ -216,13 +217,14 @@ typedef struct ProjectSet typedef struct ModifyTable { Plan plan; - CmdType operation; /* INSERT, UPDATE, or DELETE */ + CmdType operation; /* INSERT, UPDATE, DELETE or MERGE */ bool canSetTag; /* do we set the command tag/es_processed? */ Index nominalRelation; /* Parent RT index for use of EXPLAIN */ /* RT indexes of non-leaf tables in a partition tree */ List *partitioned_rels; bool partColsUpdated; /* some part key in hierarchy updated */ List *resultRelations; /* integer list of RT indexes */ + Index mergeTargetRelation; /* RT index of the merge target */ int resultRelIndex; /* index of first resultRel in plan's list */ int rootResultRelIndex; /* index of the partitioned table root */ List *plans; /* plan(s) producing source data */ @@ -238,6 +240,8 @@ typedef struct ModifyTable Node *onConflictWhere; /* WHERE for ON CONFLICT UPDATE */ Index exclRelRTI; /* RTI of the EXCLUDED pseudo relation */ List *exclRelTlist; /* tlist of the EXCLUDED pseudo relation */ + List *mergeSourceTargetList; + List *mergeActionList; /* actions for MERGE */ } ModifyTable; /* ---------------- diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h index ea5251c6be2..a2dde70de58 100644 --- a/src/include/nodes/relation.h +++ b/src/include/nodes/relation.h @@ -1670,7 +1670,7 @@ typedef struct LockRowsPath } LockRowsPath; /* - * ModifyTablePath represents performing INSERT/UPDATE/DELETE modifications + * ModifyTablePath represents performing INSERT/UPDATE/DELETE/MERGE * * We represent most things that will be in the ModifyTable plan node * literally, except we have child Path(s) not Plan(s). But analysis of the @@ -1679,13 +1679,14 @@ typedef struct LockRowsPath typedef struct ModifyTablePath { Path path; - CmdType operation; /* INSERT, UPDATE, or DELETE */ + CmdType operation; /* INSERT, UPDATE, DELETE or MERGE */ bool canSetTag; /* do we set the command tag/es_processed? */ Index nominalRelation; /* Parent RT index for use of EXPLAIN */ /* RT indexes of non-leaf tables in a partition tree */ List *partitioned_rels; bool partColsUpdated; /* some part key in hierarchy updated */ List *resultRelations; /* integer list of RT indexes */ + Index mergeTargetRelation;/* RT index of merge target relation */ List *subpaths; /* Path(s) producing source data */ List *subroots; /* per-target-table PlannerInfos */ List *withCheckOptionLists; /* per-target-table WCO lists */ @@ -1693,6 +1694,8 @@ typedef struct ModifyTablePath List *rowMarks; /* PlanRowMarks (non-locking only) */ OnConflictExpr *onconflict; /* ON CONFLICT clause, or NULL */ int epqParam; /* ID of Param for EvalPlanQual re-eval */ + List *mergeSourceTargetList; + List *mergeActionList; /* actions for MERGE */ } ModifyTablePath; /* diff --git a/src/include/optimizer/pathnode.h b/src/include/optimizer/pathnode.h index 381bc30813c..895bf6959da 100644 --- a/src/include/optimizer/pathnode.h +++ b/src/include/optimizer/pathnode.h @@ -241,11 +241,14 @@ extern ModifyTablePath *create_modifytable_path(PlannerInfo *root, CmdType operation, bool canSetTag, Index nominalRelation, List *partitioned_rels, bool partColsUpdated, - List *resultRelations, List *subpaths, + List *resultRelations, + Index mergeTargetRelation, + List *subpaths, List *subroots, List *withCheckOptionLists, List *returningLists, List *rowMarks, OnConflictExpr *onconflict, - int epqParam); + List *mergeSourceTargetList, + List *mergeActionList, int epqParam); extern LimitPath *create_limit_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, Node *limitOffset, Node *limitCount, diff --git a/src/include/parser/analyze.h b/src/include/parser/analyze.h index 687ae1b5b7c..41fb10666e5 100644 --- a/src/include/parser/analyze.h +++ b/src/include/parser/analyze.h @@ -32,6 +32,11 @@ extern Query *parse_sub_analyze(Node *parseTree, ParseState *parentParseState, bool locked_from_parent, bool resolve_unknowns); +extern List *transformInsertRow(ParseState *pstate, List *exprlist, + List *stmtcols, List *icolumns, List *attrnos, + bool strip_indirection); +extern List *transformUpdateTargetList(ParseState *pstate, + List *targetList); extern Query *transformTopLevelStmt(ParseState *pstate, RawStmt *parseTree); extern Query *transformStmt(ParseState *pstate, Node *parseTree); diff --git a/src/include/parser/kwlist.h b/src/include/parser/kwlist.h index cf32197bc3e..4dff55a8e99 100644 --- a/src/include/parser/kwlist.h +++ b/src/include/parser/kwlist.h @@ -244,8 +244,10 @@ PG_KEYWORD("locked", LOCKED, UNRESERVED_KEYWORD) PG_KEYWORD("logged", LOGGED, UNRESERVED_KEYWORD) PG_KEYWORD("mapping", MAPPING, UNRESERVED_KEYWORD) PG_KEYWORD("match", MATCH, UNRESERVED_KEYWORD) +PG_KEYWORD("matched", MATCHED, UNRESERVED_KEYWORD) PG_KEYWORD("materialized", MATERIALIZED, UNRESERVED_KEYWORD) PG_KEYWORD("maxvalue", MAXVALUE, UNRESERVED_KEYWORD) +PG_KEYWORD("merge", MERGE, UNRESERVED_KEYWORD) PG_KEYWORD("method", METHOD, UNRESERVED_KEYWORD) PG_KEYWORD("minute", MINUTE_P, UNRESERVED_KEYWORD) PG_KEYWORD("minvalue", MINVALUE, UNRESERVED_KEYWORD) diff --git a/src/include/parser/parse_clause.h b/src/include/parser/parse_clause.h index 2c0e0928628..30121c98ed8 100644 --- a/src/include/parser/parse_clause.h +++ b/src/include/parser/parse_clause.h @@ -20,7 +20,10 @@ extern void transformFromClause(ParseState *pstate, List *frmList); extern int setTargetTable(ParseState *pstate, RangeVar *relation, bool inh, bool alsoSource, AclMode requiredPerms); extern bool interpretOidsOption(List *defList, bool allowOids); - +extern Node *transformFromClauseItem(ParseState *pstate, Node *n, + RangeTblEntry **top_rte, int *top_rti, + RangeTblEntry **right_rte, int *right_rti, + List **namespace); extern Node *transformWhereClause(ParseState *pstate, Node *clause, ParseExprKind exprKind, const char *constructName); extern Node *transformLimitClause(ParseState *pstate, Node *clause, diff --git a/src/include/parser/parse_node.h b/src/include/parser/parse_node.h index 0230543810f..3fd2151ccbe 100644 --- a/src/include/parser/parse_node.h +++ b/src/include/parser/parse_node.h @@ -50,6 +50,7 @@ typedef enum ParseExprKind EXPR_KIND_INSERT_TARGET, /* INSERT target list item */ EXPR_KIND_UPDATE_SOURCE, /* UPDATE assignment source item */ EXPR_KIND_UPDATE_TARGET, /* UPDATE assignment target item */ + EXPR_KIND_MERGE_WHEN_AND, /* MERGE WHEN ... AND condition */ EXPR_KIND_GROUP_BY, /* GROUP BY */ EXPR_KIND_ORDER_BY, /* ORDER BY */ EXPR_KIND_DISTINCT_ON, /* DISTINCT ON */ @@ -127,7 +128,7 @@ typedef Node *(*CoerceParamHook) (ParseState *pstate, Param *param, * p_parent_cte: CommonTableExpr that immediately contains the current query, * if any. * - * p_target_relation: target relation, if query is INSERT, UPDATE, or DELETE. + * p_target_relation: target relation, if query is INSERT/UPDATE/DELETE/MERGE * * p_target_rangetblentry: target relation's entry in the rtable list. * @@ -181,7 +182,7 @@ struct ParseState List *p_ctenamespace; /* current namespace for common table exprs */ List *p_future_ctes; /* common table exprs not yet in namespace */ CommonTableExpr *p_parent_cte; /* this query's containing CTE */ - Relation p_target_relation; /* INSERT/UPDATE/DELETE target rel */ + Relation p_target_relation; /* INSERT/UPDATE/DELETE/MERGE target rel */ RangeTblEntry *p_target_rangetblentry; /* target rel's RTE */ bool p_is_insert; /* process assignment like INSERT not UPDATE */ List *p_windowdefs; /* raw representations of window clauses */ diff --git a/src/include/rewrite/rewriteHandler.h b/src/include/rewrite/rewriteHandler.h index 8128199fc31..1ab5de39422 100644 --- a/src/include/rewrite/rewriteHandler.h +++ b/src/include/rewrite/rewriteHandler.h @@ -25,6 +25,7 @@ extern void AcquireRewriteLocks(Query *parsetree, extern Node *build_column_default(Relation rel, int attrno); extern void rewriteTargetListUD(Query *parsetree, RangeTblEntry *target_rte, Relation target_relation); +extern void rewriteTargetListMerge(Query *parsetree, Relation target_relation); extern Query *get_view_query(Relation view); extern const char *view_query_is_auto_updatable(Query *viewquery, |