aboutsummaryrefslogtreecommitdiff
path: root/src/backend/rewrite/rewriteHandler.c
diff options
context:
space:
mode:
authorSimon Riggs <simon@2ndQuadrant.com>2018-04-02 21:12:47 +0100
committerSimon Riggs <simon@2ndQuadrant.com>2018-04-02 21:12:47 +0100
commit354f13855e6381d288dfaa52bcd4f2cb0fd4a5eb (patch)
tree92710660450acee59be62dea485cc26ab147f332 /src/backend/rewrite/rewriteHandler.c
parente6597dc3533946b98acba7871bd4ca1f7a3d4c1d (diff)
downloadpostgresql-354f13855e6381d288dfaa52bcd4f2cb0fd4a5eb.tar.gz
postgresql-354f13855e6381d288dfaa52bcd4f2cb0fd4a5eb.zip
Modified files for MERGE
Diffstat (limited to 'src/backend/rewrite/rewriteHandler.c')
-rw-r--r--src/backend/rewrite/rewriteHandler.c117
1 files changed, 110 insertions, 7 deletions
diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c
index 88140bc6877..98239f569ae 100644
--- a/src/backend/rewrite/rewriteHandler.c
+++ b/src/backend/rewrite/rewriteHandler.c
@@ -1377,6 +1377,57 @@ rewriteTargetListUD(Query *parsetree, RangeTblEntry *target_rte,
}
}
+void
+rewriteTargetListMerge(Query *parsetree, Relation target_relation)
+{
+ Var *var = NULL;
+ const char *attrname;
+ TargetEntry *tle;
+
+ Assert(target_relation->rd_rel->relkind == RELKIND_RELATION ||
+ target_relation->rd_rel->relkind == RELKIND_MATVIEW ||
+ target_relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE);
+
+ /*
+ * Emit CTID so that executor can find the row to update or delete.
+ */
+ var = makeVar(parsetree->mergeTarget_relation,
+ SelfItemPointerAttributeNumber,
+ TIDOID,
+ -1,
+ InvalidOid,
+ 0);
+
+ attrname = "ctid";
+ tle = makeTargetEntry((Expr *) var,
+ list_length(parsetree->targetList) + 1,
+ pstrdup(attrname),
+ true);
+
+ parsetree->targetList = lappend(parsetree->targetList, tle);
+
+ /*
+ * If we are dealing with partitioned table, then emit TABLEOID so that
+ * executor can find the partition the row belongs to.
+ */
+ if (target_relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
+ {
+ var = makeVar(parsetree->mergeTarget_relation,
+ TableOidAttributeNumber,
+ OIDOID,
+ -1,
+ InvalidOid,
+ 0);
+
+ attrname = "tableoid";
+ tle = makeTargetEntry((Expr *) var,
+ list_length(parsetree->targetList) + 1,
+ pstrdup(attrname),
+ true);
+
+ parsetree->targetList = lappend(parsetree->targetList, tle);
+ }
+}
/*
* matchLocks -
@@ -3331,6 +3382,7 @@ RewriteQuery(Query *parsetree, List *rewrite_events)
}
else if (event == CMD_UPDATE)
{
+ Assert(parsetree->override == OVERRIDING_NOT_SET);
parsetree->targetList =
rewriteTargetListIU(parsetree->targetList,
parsetree->commandType,
@@ -3338,6 +3390,50 @@ RewriteQuery(Query *parsetree, List *rewrite_events)
rt_entry_relation,
parsetree->resultRelation, NULL);
}
+ else if (event == CMD_MERGE)
+ {
+ Assert(parsetree->override == OVERRIDING_NOT_SET);
+
+ /*
+ * Rewrite each action targetlist separately
+ */
+ foreach(lc1, parsetree->mergeActionList)
+ {
+ MergeAction *action = (MergeAction *) lfirst(lc1);
+
+ switch (action->commandType)
+ {
+ case CMD_NOTHING:
+ case CMD_DELETE: /* Nothing to do here */
+ break;
+ case CMD_UPDATE:
+ action->targetList =
+ rewriteTargetListIU(action->targetList,
+ action->commandType,
+ parsetree->override,
+ rt_entry_relation,
+ parsetree->resultRelation,
+ NULL);
+ break;
+ case CMD_INSERT:
+ {
+ InsertStmt *istmt = (InsertStmt *) action->stmt;
+
+ action->targetList =
+ rewriteTargetListIU(action->targetList,
+ action->commandType,
+ istmt->override,
+ rt_entry_relation,
+ parsetree->resultRelation,
+ NULL);
+ }
+ break;
+ default:
+ elog(ERROR, "unrecognized commandType: %d", action->commandType);
+ break;
+ }
+ }
+ }
else if (event == CMD_DELETE)
{
/* Nothing to do here */
@@ -3351,13 +3447,20 @@ RewriteQuery(Query *parsetree, List *rewrite_events)
locks = matchLocks(event, rt_entry_relation->rd_rules,
result_relation, parsetree, &hasUpdate);
- product_queries = fireRules(parsetree,
- result_relation,
- event,
- locks,
- &instead,
- &returning,
- &qual_product);
+ /*
+ * XXX MERGE doesn't support write rules because they would violate
+ * the SQL Standard spec and would be unclear how they should work.
+ */
+ if (event == CMD_MERGE)
+ product_queries = NIL;
+ else
+ product_queries = fireRules(parsetree,
+ result_relation,
+ event,
+ locks,
+ &instead,
+ &returning,
+ &qual_product);
/*
* If there were no INSTEAD rules, and the target relation is a view