diff options
Diffstat (limited to 'src/include')
-rw-r--r-- | src/include/commands/trigger.h | 4 | ||||
-rw-r--r-- | src/include/executor/nodeModifyTable.h | 3 | ||||
-rw-r--r-- | src/include/executor/spi.h | 1 | ||||
-rw-r--r-- | src/include/nodes/execnodes.h | 36 | ||||
-rw-r--r-- | src/include/nodes/nodes.h | 7 | ||||
-rw-r--r-- | src/include/nodes/parsenodes.h | 61 | ||||
-rw-r--r-- | src/include/nodes/pathnodes.h | 6 | ||||
-rw-r--r-- | src/include/nodes/plannodes.h | 7 | ||||
-rw-r--r-- | src/include/optimizer/pathnode.h | 2 | ||||
-rw-r--r-- | src/include/optimizer/prep.h | 1 | ||||
-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_merge.h | 21 | ||||
-rw-r--r-- | src/include/parser/parse_node.h | 5 | ||||
-rw-r--r-- | src/include/parser/parse_relation.h | 3 | ||||
-rw-r--r-- | src/include/tcop/cmdtaglist.h | 1 |
16 files changed, 150 insertions, 15 deletions
diff --git a/src/include/commands/trigger.h b/src/include/commands/trigger.h index 66bf6c16e34..194e8d5bc13 100644 --- a/src/include/commands/trigger.h +++ b/src/include/commands/trigger.h @@ -13,6 +13,7 @@ #ifndef TRIGGER_H #define TRIGGER_H +#include "access/tableam.h" #include "catalog/objectaddress.h" #include "nodes/execnodes.h" #include "nodes/parsenodes.h" @@ -229,7 +230,8 @@ extern bool ExecBRUpdateTriggers(EState *estate, ResultRelInfo *relinfo, ItemPointer tupleid, HeapTuple fdw_trigtuple, - TupleTableSlot *slot); + TupleTableSlot *slot, + TM_FailureData *tmfdp); extern void ExecARUpdateTriggers(EState *estate, ResultRelInfo *relinfo, ResultRelInfo *src_partinfo, diff --git a/src/include/executor/nodeModifyTable.h b/src/include/executor/nodeModifyTable.h index 1d225bc88d5..c318681b9ae 100644 --- a/src/include/executor/nodeModifyTable.h +++ b/src/include/executor/nodeModifyTable.h @@ -23,4 +23,7 @@ extern ModifyTableState *ExecInitModifyTable(ModifyTable *node, EState *estate, extern void ExecEndModifyTable(ModifyTableState *node); extern void ExecReScanModifyTable(ModifyTableState *node); +extern void ExecInitMergeTupleSlots(ModifyTableState *mtstate, + ResultRelInfo *resultRelInfo); + #endif /* NODEMODIFYTABLE_H */ diff --git a/src/include/executor/spi.h b/src/include/executor/spi.h index 6ec38514445..b2c0c7486ce 100644 --- a/src/include/executor/spi.h +++ b/src/include/executor/spi.h @@ -96,6 +96,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 44dd73fc80e..cbbcff81d2e 100644 --- a/src/include/nodes/execnodes.h +++ b/src/include/nodes/execnodes.h @@ -389,6 +389,22 @@ typedef struct OnConflictSetState ExprState *oc_WhereClause; /* state for the WHERE clause */ } OnConflictSetState; +/* ---------------- + * MergeActionState information + * + * Executor state for a MERGE action. + * ---------------- + */ +typedef struct MergeActionState +{ + NodeTag type; + + MergeAction *mas_action; /* associated MergeAction node */ + ProjectionInfo *mas_proj; /* projection of the action's targetlist for + * this rel */ + ExprState *mas_whenqual; /* WHEN [NOT] MATCHED AND conditions */ +} MergeActionState; + /* * ResultRelInfo * @@ -500,6 +516,10 @@ typedef struct ResultRelInfo /* ON CONFLICT evaluation state */ OnConflictSetState *ri_onConflict; + /* for MERGE, lists of MergeActionState */ + List *ri_matchedMergeAction; + List *ri_notMatchedMergeAction; + /* partition check expression state (NULL if not set up yet) */ ExprState *ri_PartitionCheckExpr; @@ -1190,6 +1210,12 @@ typedef struct ProjectSetState MemoryContext argcontext; /* context for SRF arguments */ } ProjectSetState; + +/* flags for mt_merge_subcommands */ +#define MERGE_INSERT 0x01 +#define MERGE_UPDATE 0x02 +#define MERGE_DELETE 0x04 + /* ---------------- * ModifyTableState information * ---------------- @@ -1197,7 +1223,7 @@ typedef struct ProjectSetState 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? */ int mt_nrels; /* number of entries in resultRelInfo[] */ @@ -1239,6 +1265,14 @@ typedef struct ModifyTableState /* controls transition table population for INSERT...ON CONFLICT UPDATE */ struct TransitionCaptureState *mt_oc_transition_capture; + + /* Flags showing which subcommands are present INS/UPD/DEL/DO NOTHING */ + int mt_merge_subcommands; + + /* tuple counters for MERGE */ + double mt_merge_inserted; + double mt_merge_updated; + double mt_merge_deleted; } ModifyTableState; /* ---------------- diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h index 05f0b79e82e..ca440eb75ff 100644 --- a/src/include/nodes/nodes.h +++ b/src/include/nodes/nodes.h @@ -35,6 +35,7 @@ typedef enum NodeTag T_ProjectionInfo, T_JunkFilter, T_OnConflictSetState, + T_MergeActionState, T_ResultRelInfo, T_EState, T_TupleTableSlot, @@ -283,6 +284,7 @@ typedef enum NodeTag T_RollupData, T_GroupingSetData, T_StatisticExtInfo, + T_MergeAction, /* * TAGS FOR MEMORY NODES (memnodes.h) @@ -321,6 +323,7 @@ typedef enum NodeTag T_InsertStmt, T_DeleteStmt, T_UpdateStmt, + T_MergeStmt, T_SelectStmt, T_ReturnStmt, T_PLAssignStmt, @@ -485,6 +488,7 @@ typedef enum NodeTag T_CTESearchClause, T_CTECycleClause, T_CommonTableExpr, + T_MergeWhenClause, T_RoleSpec, T_TriggerTransition, T_PartitionElem, @@ -698,7 +702,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 3b12a708ec0..6bf212b01a1 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -119,7 +119,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? */ @@ -130,7 +130,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 */ @@ -147,7 +147,11 @@ typedef struct Query List *cteList; /* WITH list (of CommonTableExpr's) */ List *rtable; /* list of range table entries */ - FromExpr *jointree; /* table join tree (FROM and WHERE clauses) */ + FromExpr *jointree; /* table join tree (FROM and WHERE clauses); + * also USING clause for MERGE */ + + List *mergeActionList; /* list of actions for MERGE (only) */ + bool mergeUseOuterJoin; /* whether to use outer join */ List *targetList; /* target list (of TargetEntry) */ @@ -1221,7 +1225,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 @@ -1538,6 +1544,39 @@ typedef struct CommonTableExpr ((Query *) (cte)->ctequery)->returningList) /* + * MergeWhenClause - + * raw parser representation of a WHEN clause in a MERGE statement + * + * This is transformed into MergeAction by parse analysis + */ +typedef struct MergeWhenClause +{ + NodeTag type; + bool matched; /* true=MATCHED, false=NOT MATCHED */ + CmdType commandType; /* INSERT/UPDATE/DELETE/DO NOTHING */ + OverridingKind override; /* OVERRIDING clause */ + Node *condition; /* WHEN conditions (raw parser) */ + List *targetList; /* INSERT/UPDATE targetlist */ + /* the following members are only used in INSERT actions */ + List *values; /* VALUES to INSERT, or NULL */ +} MergeWhenClause; + +/* + * MergeAction - + * Transformed representation of a WHEN clause in a MERGE statement + */ +typedef struct MergeAction +{ + NodeTag type; + bool matched; /* true=MATCHED, false=NOT MATCHED */ + CmdType commandType; /* INSERT/UPDATE/DELETE/DO NOTHING */ + OverridingKind override; /* OVERRIDING clause */ + Node *qual; /* transformed WHEN conditions */ + List *targetList; /* the target list (of TargetEntry) */ + List *updateColnos; /* target attribute numbers of an UPDATE */ +} MergeAction; + +/* * TriggerTransition - * representation of transition row or table naming clause * @@ -1738,6 +1777,20 @@ typedef struct UpdateStmt } UpdateStmt; /* ---------------------- + * Merge Statement + * ---------------------- + */ +typedef struct MergeStmt +{ + NodeTag type; + RangeVar *relation; /* target relation to merge into */ + Node *sourceRelation; /* source relation */ + Node *joinCondition; /* join condition between source and target */ + List *mergeWhenClauses; /* list of MergeWhenClause(es) */ + WithClause *withClause; /* WITH clause */ +} MergeStmt; + +/* ---------------------- * Select Statement * * A "simple" SELECT is represented in the output of gram.y by a single diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index 1f3845b3fec..365000bdcdb 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -1875,7 +1875,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 a child Path not Plan. But analysis of the @@ -1885,7 +1885,7 @@ typedef struct ModifyTablePath { Path path; Path *subpath; /* Path producing source data */ - 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 */ Index rootRelation; /* Root RT index, if target is partitioned */ @@ -1897,6 +1897,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 *mergeActionLists; /* per-target-table lists of actions for + * MERGE */ } ModifyTablePath; /* diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h index 0b518ce6b28..50ef3dda051 100644 --- a/src/include/nodes/plannodes.h +++ b/src/include/nodes/plannodes.h @@ -19,6 +19,7 @@ #include "lib/stringinfo.h" #include "nodes/bitmapset.h" #include "nodes/lockoptions.h" +#include "nodes/parsenodes.h" #include "nodes/primnodes.h" @@ -43,7 +44,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) */ @@ -217,7 +218,7 @@ 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 */ Index rootRelation; /* Root RT index, if target is partitioned */ @@ -237,6 +238,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 *mergeActionLists; /* per-target-table lists of actions for + * MERGE */ } ModifyTable; struct PartitionPruneInfo; /* forward reference to struct below */ diff --git a/src/include/optimizer/pathnode.h b/src/include/optimizer/pathnode.h index 620eeda2d60..6eca547af80 100644 --- a/src/include/optimizer/pathnode.h +++ b/src/include/optimizer/pathnode.h @@ -276,7 +276,7 @@ extern ModifyTablePath *create_modifytable_path(PlannerInfo *root, List *updateColnosLists, List *withCheckOptionLists, List *returningLists, List *rowMarks, OnConflictExpr *onconflict, - int epqParam); + List *mergeActionLists, int epqParam); extern LimitPath *create_limit_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, Node *limitOffset, Node *limitCount, diff --git a/src/include/optimizer/prep.h b/src/include/optimizer/prep.h index 006b4d02c3e..2b11ff1d1fe 100644 --- a/src/include/optimizer/prep.h +++ b/src/include/optimizer/prep.h @@ -21,6 +21,7 @@ /* * prototypes for prepjointree.c */ +extern void transform_MERGE_to_join(Query *parse); extern void replace_empty_jointree(Query *parse); extern void pull_up_sublinks(PlannerInfo *root); extern void preprocess_function_rtes(PlannerInfo *root); diff --git a/src/include/parser/analyze.h b/src/include/parser/analyze.h index b30cbd26bf8..c69920d1087 100644 --- a/src/include/parser/analyze.h +++ b/src/include/parser/analyze.h @@ -39,6 +39,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 f44440d4a94..10829941e0d 100644 --- a/src/include/parser/kwlist.h +++ b/src/include/parser/kwlist.h @@ -259,8 +259,10 @@ PG_KEYWORD("locked", LOCKED, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("logged", LOGGED, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("mapping", MAPPING, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("match", MATCH, UNRESERVED_KEYWORD, BARE_LABEL) +PG_KEYWORD("matched", MATCHED, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("materialized", MATERIALIZED, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("maxvalue", MAXVALUE, UNRESERVED_KEYWORD, BARE_LABEL) +PG_KEYWORD("merge", MERGE, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("method", METHOD, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("minute", MINUTE_P, UNRESERVED_KEYWORD, AS_LABEL) PG_KEYWORD("minvalue", MINVALUE, UNRESERVED_KEYWORD, BARE_LABEL) diff --git a/src/include/parser/parse_merge.h b/src/include/parser/parse_merge.h new file mode 100644 index 00000000000..1a1baa1f485 --- /dev/null +++ b/src/include/parser/parse_merge.h @@ -0,0 +1,21 @@ +/*------------------------------------------------------------------------- + * + * parse_merge.h + * handle MERGE statement in parser + * + * + * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/include/parser/parse_merge.h + * + *------------------------------------------------------------------------- + */ +#ifndef PARSE_MERGE_H +#define PARSE_MERGE_H + +#include "parser/parse_node.h" + +extern Query *transformMergeStmt(ParseState *pstate, MergeStmt *stmt); + +#endif /* PARSE_MERGE_H */ diff --git a/src/include/parser/parse_node.h b/src/include/parser/parse_node.h index 8c859d0d0e4..cf9c7590258 100644 --- a/src/include/parser/parse_node.h +++ b/src/include/parser/parse_node.h @@ -55,6 +55,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, /* MERGE WHEN [NOT] MATCHED condition */ EXPR_KIND_GROUP_BY, /* GROUP BY */ EXPR_KIND_ORDER_BY, /* ORDER BY */ EXPR_KIND_DISTINCT_ON, /* DISTINCT ON */ @@ -135,7 +136,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_nsitem: target relation's ParseNamespaceItem. * @@ -189,7 +190,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 */ ParseNamespaceItem *p_target_nsitem; /* target rel's NSItem, or NULL */ bool p_is_insert; /* process assignment like INSERT not UPDATE */ List *p_windowdefs; /* raw representations of window clauses */ diff --git a/src/include/parser/parse_relation.h b/src/include/parser/parse_relation.h index 06dc27995ba..de21c3c6497 100644 --- a/src/include/parser/parse_relation.h +++ b/src/include/parser/parse_relation.h @@ -113,7 +113,8 @@ extern List *expandNSItemVars(ParseNamespaceItem *nsitem, int sublevels_up, int location, List **colnames); extern List *expandNSItemAttrs(ParseState *pstate, ParseNamespaceItem *nsitem, - int sublevels_up, int location); + int sublevels_up, bool require_col_privs, + int location); extern int attnameAttNum(Relation rd, const char *attname, bool sysColOK); extern const NameData *attnumAttName(Relation rd, int attid); extern Oid attnumTypeId(Relation rd, int attid); diff --git a/src/include/tcop/cmdtaglist.h b/src/include/tcop/cmdtaglist.h index 4bc7ddf4107..2b1163ce33a 100644 --- a/src/include/tcop/cmdtaglist.h +++ b/src/include/tcop/cmdtaglist.h @@ -186,6 +186,7 @@ PG_CMDTAG(CMDTAG_INSERT, "INSERT", false, false, true) PG_CMDTAG(CMDTAG_LISTEN, "LISTEN", false, false, false) PG_CMDTAG(CMDTAG_LOAD, "LOAD", false, false, false) PG_CMDTAG(CMDTAG_LOCK_TABLE, "LOCK TABLE", false, false, false) +PG_CMDTAG(CMDTAG_MERGE, "MERGE", false, false, true) PG_CMDTAG(CMDTAG_MOVE, "MOVE", false, false, true) PG_CMDTAG(CMDTAG_NOTIFY, "NOTIFY", false, false, false) PG_CMDTAG(CMDTAG_PREPARE, "PREPARE", false, false, false) |