diff options
author | Simon Riggs <simon@2ndQuadrant.com> | 2018-04-02 21:12:47 +0100 |
---|---|---|
committer | Simon Riggs <simon@2ndQuadrant.com> | 2018-04-02 21:12:47 +0100 |
commit | 354f13855e6381d288dfaa52bcd4f2cb0fd4a5eb (patch) | |
tree | 92710660450acee59be62dea485cc26ab147f332 /src/backend/rewrite/rewriteHandler.c | |
parent | e6597dc3533946b98acba7871bd4ca1f7a3d4c1d (diff) | |
download | postgresql-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.c | 117 |
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 |