aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser/parse_merge.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/parser/parse_merge.c')
-rw-r--r--src/backend/parser/parse_merge.c86
1 files changed, 33 insertions, 53 deletions
diff --git a/src/backend/parser/parse_merge.c b/src/backend/parser/parse_merge.c
index eb4c615ce1c..722cb23b86c 100644
--- a/src/backend/parser/parse_merge.c
+++ b/src/backend/parser/parse_merge.c
@@ -33,8 +33,8 @@
static int transformMergeJoinClause(ParseState *pstate, Node *merge,
List **mergeSourceTargetList);
-static void setNamespaceForMergeAction(ParseState *pstate,
- MergeAction *action);
+static void setNamespaceForMergeWhen(ParseState *pstate,
+ MergeWhenClause *mergeWhenClause);
static void setNamespaceVisibilityForRTE(List *namespace, RangeTblEntry *rte,
bool rel_visible,
bool cols_visible);
@@ -138,7 +138,7 @@ transformMergeJoinClause(ParseState *pstate, Node *merge,
* that columns can be referenced unqualified from these relations.
*/
static void
-setNamespaceForMergeAction(ParseState *pstate, MergeAction *action)
+setNamespaceForMergeWhen(ParseState *pstate, MergeWhenClause *mergeWhenClause)
{
RangeTblEntry *targetRelRTE,
*sourceRelRTE;
@@ -152,7 +152,7 @@ setNamespaceForMergeAction(ParseState *pstate, MergeAction *action)
*/
sourceRelRTE = rt_fetch(list_length(pstate->p_rtable) - 1, pstate->p_rtable);
- switch (action->commandType)
+ switch (mergeWhenClause->commandType)
{
case CMD_INSERT:
@@ -198,6 +198,7 @@ transformMergeStmt(ParseState *pstate, MergeStmt *stmt)
bool is_terminal[2];
JoinExpr *joinexpr;
RangeTblEntry *resultRelRTE, *mergeRelRTE;
+ List *mergeActionList;
/* There can't be any outer WITH to worry about */
Assert(pstate->p_ctenamespace == NIL);
@@ -222,43 +223,18 @@ transformMergeStmt(ParseState *pstate, MergeStmt *stmt)
*/
is_terminal[0] = false;
is_terminal[1] = false;
- foreach(l, stmt->mergeActionList)
+ foreach(l, stmt->mergeWhenClauses)
{
- MergeAction *action = (MergeAction *) lfirst(l);
- int when_type = (action->matched ? 0 : 1);
+ MergeWhenClause *mergeWhenClause = (MergeWhenClause *) lfirst(l);
+ int when_type = (mergeWhenClause->matched ? 0 : 1);
/*
* Collect action types so we can check Target permissions
*/
- switch (action->commandType)
+ switch (mergeWhenClause->commandType)
{
case CMD_INSERT:
- {
- InsertStmt *istmt = (InsertStmt *) action->stmt;
- SelectStmt *selectStmt = (SelectStmt *) istmt->selectStmt;
-
- /*
- * The grammar allows attaching ORDER BY, LIMIT, FOR
- * UPDATE, or WITH to a VALUES clause and also multiple
- * VALUES clauses. If we have any of those, ERROR.
- */
- if (selectStmt && (selectStmt->valuesLists == NIL ||
- selectStmt->sortClause != NIL ||
- selectStmt->limitOffset != NULL ||
- selectStmt->limitCount != NULL ||
- selectStmt->lockingClause != NIL ||
- selectStmt->withClause != NULL))
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("SELECT not allowed in MERGE INSERT statement")));
-
- if (selectStmt && list_length(selectStmt->valuesLists) > 1)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("Multiple VALUES clauses not allowed in MERGE INSERT statement")));
-
- targetPerms |= ACL_INSERT;
- }
+ targetPerms |= ACL_INSERT;
break;
case CMD_UPDATE:
targetPerms |= ACL_UPDATE;
@@ -275,7 +251,7 @@ transformMergeStmt(ParseState *pstate, MergeStmt *stmt)
/*
* Check for unreachable WHEN clauses
*/
- if (action->condition == NULL)
+ if (mergeWhenClause->condition == NULL)
is_terminal[when_type] = true;
else if (is_terminal[when_type])
ereport(ERROR,
@@ -461,15 +437,20 @@ transformMergeStmt(ParseState *pstate, MergeStmt *stmt)
* both of those already have RTEs. There is nothing like the EXCLUDED
* pseudo-relation for INSERT ON CONFLICT.
*/
- foreach(l, stmt->mergeActionList)
+ mergeActionList = NIL;
+ foreach(l, stmt->mergeWhenClauses)
{
- MergeAction *action = (MergeAction *) lfirst(l);
+ MergeWhenClause *mergeWhenClause = (MergeWhenClause *) lfirst(l);
+ MergeAction *action = makeNode(MergeAction);
+
+ action->commandType = mergeWhenClause->commandType;
+ action->matched = mergeWhenClause->matched;
/*
* Set namespace for the specific action. This must be done before
* analyzing the WHEN quals and the action targetlisst.
*/
- setNamespaceForMergeAction(pstate, action);
+ setNamespaceForMergeWhen(pstate, mergeWhenClause);
/*
* Transform the when condition.
@@ -478,7 +459,7 @@ transformMergeStmt(ParseState *pstate, MergeStmt *stmt)
* are evaluated separately during execution to decide which of the
* WHEN MATCHED or WHEN NOT MATCHED actions to execute.
*/
- action->qual = transformWhereClause(pstate, action->condition,
+ action->qual = transformWhereClause(pstate, mergeWhenClause->condition,
EXPR_KIND_MERGE_WHEN_AND, "WHEN");
/*
@@ -488,8 +469,6 @@ transformMergeStmt(ParseState *pstate, MergeStmt *stmt)
{
case CMD_INSERT:
{
- InsertStmt *istmt = (InsertStmt *) action->stmt;
- SelectStmt *selectStmt = (SelectStmt *) istmt->selectStmt;
List *exprList = NIL;
ListCell *lc;
RangeTblEntry *rte;
@@ -500,13 +479,17 @@ transformMergeStmt(ParseState *pstate, MergeStmt *stmt)
pstate->p_is_insert = true;
- icolumns = checkInsertTargets(pstate, istmt->cols, &attrnos);
+ icolumns = checkInsertTargets(pstate,
+ mergeWhenClause->cols,
+ &attrnos);
Assert(list_length(icolumns) == list_length(attrnos));
+ action->override = mergeWhenClause->override;
+
/*
* Handle INSERT much like in transformInsertStmt
*/
- if (selectStmt == NULL)
+ if (mergeWhenClause->values == NIL)
{
/*
* We have INSERT ... DEFAULT VALUES. We can handle
@@ -525,23 +508,19 @@ transformMergeStmt(ParseState *pstate, MergeStmt *stmt)
* as the Query's targetlist, with no VALUES RTE. So
* it works just like a SELECT without any FROM.
*/
- List *valuesLists = selectStmt->valuesLists;
-
- Assert(list_length(valuesLists) == 1);
- Assert(selectStmt->intoClause == NULL);
/*
* Do basic expression transformation (same as a ROW()
* expr, but allow SetToDefault at top level)
*/
exprList = transformExpressionList(pstate,
- (List *) linitial(valuesLists),
+ mergeWhenClause->values,
EXPR_KIND_VALUES_SINGLE,
true);
/* Prepare row for assignment to target table */
exprList = transformInsertRow(pstate, exprList,
- istmt->cols,
+ mergeWhenClause->cols,
icolumns, attrnos,
false);
}
@@ -580,10 +559,9 @@ transformMergeStmt(ParseState *pstate, MergeStmt *stmt)
break;
case CMD_UPDATE:
{
- UpdateStmt *ustmt = (UpdateStmt *) action->stmt;
-
pstate->p_is_insert = false;
- action->targetList = transformUpdateTargetList(pstate, ustmt->targetList);
+ action->targetList = transformUpdateTargetList(pstate,
+ mergeWhenClause->targetList);
}
break;
case CMD_DELETE:
@@ -595,9 +573,11 @@ transformMergeStmt(ParseState *pstate, MergeStmt *stmt)
default:
elog(ERROR, "unknown action in MERGE WHEN clause");
}
+
+ mergeActionList = lappend(mergeActionList, action);
}
- qry->mergeActionList = stmt->mergeActionList;
+ qry->mergeActionList = mergeActionList;
/* XXX maybe later */
qry->returningList = NULL;