diff options
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/nodes/makefuncs.c | 87 | ||||
-rw-r--r-- | src/backend/optimizer/prep/preptlist.c | 8 | ||||
-rw-r--r-- | src/backend/parser/parse_expr.c | 76 | ||||
-rw-r--r-- | src/backend/rewrite/rewriteHandler.c | 18 |
4 files changed, 101 insertions, 88 deletions
diff --git a/src/backend/nodes/makefuncs.c b/src/backend/nodes/makefuncs.c index ee15695b914..4b268f3c6b3 100644 --- a/src/backend/nodes/makefuncs.c +++ b/src/backend/nodes/makefuncs.c @@ -108,6 +108,93 @@ makeVarFromTargetEntry(Index varno, } /* + * makeWholeRowVar - + * creates a Var node representing a whole row of the specified RTE + * + * A whole-row reference is a Var with varno set to the correct range + * table entry, and varattno == 0 to signal that it references the whole + * tuple. (Use of zero here is unclean, since it could easily be confused + * with error cases, but it's not worth changing now.) The vartype indicates + * a rowtype; either a named composite type, or RECORD. This function + * encapsulates the logic for determining the correct rowtype OID to use. + */ +Var * +makeWholeRowVar(RangeTblEntry *rte, + Index varno, + Index varlevelsup) +{ + Var *result; + Oid toid; + + switch (rte->rtekind) + { + case RTE_RELATION: + /* relation: the rowtype is a named composite type */ + toid = get_rel_type_id(rte->relid); + if (!OidIsValid(toid)) + elog(ERROR, "could not find type OID for relation %u", + rte->relid); + result = makeVar(varno, + InvalidAttrNumber, + toid, + -1, + varlevelsup); + break; + case RTE_FUNCTION: + toid = exprType(rte->funcexpr); + if (type_is_rowtype(toid)) + { + /* func returns composite; same as relation case */ + result = makeVar(varno, + InvalidAttrNumber, + toid, + -1, + varlevelsup); + } + else + { + /* + * func returns scalar; instead of making a whole-row Var, + * just reference the function's scalar output. (XXX this + * seems a tad inconsistent, especially if "f.*" was + * explicitly written ...) + */ + result = makeVar(varno, + 1, + toid, + -1, + varlevelsup); + } + break; + case RTE_VALUES: + toid = RECORDOID; + /* returns composite; same as relation case */ + result = makeVar(varno, + InvalidAttrNumber, + toid, + -1, + varlevelsup); + break; + default: + + /* + * RTE is a join or subselect. We represent this as a whole-row + * Var of RECORD type. (Note that in most cases the Var will be + * expanded to a RowExpr during planning, but that is not our + * concern here.) + */ + result = makeVar(varno, + InvalidAttrNumber, + RECORDOID, + -1, + varlevelsup); + break; + } + + return result; +} + +/* * makeTargetEntry - * creates a TargetEntry node */ diff --git a/src/backend/optimizer/prep/preptlist.c b/src/backend/optimizer/prep/preptlist.c index 2c97c71472a..bc8b7709d37 100644 --- a/src/backend/optimizer/prep/preptlist.c +++ b/src/backend/optimizer/prep/preptlist.c @@ -139,11 +139,9 @@ preprocess_targetlist(PlannerInfo *root, List *tlist) else { /* Not a table, so we need the whole row as a junk var */ - var = makeVar(rc->rti, - InvalidAttrNumber, - RECORDOID, - -1, - 0); + var = makeWholeRowVar(rt_fetch(rc->rti, range_table), + rc->rti, + 0); snprintf(resname, sizeof(resname), "wholerow%u", rc->rti); tle = makeTargetEntry((Expr *) var, list_length(tlist) + 1, diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c index e49473cc817..addd0d4fffe 100644 --- a/src/backend/parser/parse_expr.c +++ b/src/backend/parser/parse_expr.c @@ -2015,12 +2015,6 @@ transformCurrentOfExpr(ParseState *pstate, CurrentOfExpr *cexpr) /* * Construct a whole-row reference to represent the notation "relation.*". - * - * A whole-row reference is a Var with varno set to the correct range - * table entry, and varattno == 0 to signal that it references the whole - * tuple. (Use of zero here is unclean, since it could easily be confused - * with error cases, but it's not worth changing now.) The vartype indicates - * a rowtype; either a named composite type, or RECORD. */ static Node * transformWholeRowRef(ParseState *pstate, RangeTblEntry *rte, int location) @@ -2028,80 +2022,14 @@ transformWholeRowRef(ParseState *pstate, RangeTblEntry *rte, int location) Var *result; int vnum; int sublevels_up; - Oid toid; /* Find the RTE's rangetable location */ - vnum = RTERangeTablePosn(pstate, rte, &sublevels_up); /* Build the appropriate referencing node */ + result = makeWholeRowVar(rte, vnum, sublevels_up); - switch (rte->rtekind) - { - case RTE_RELATION: - /* relation: the rowtype is a named composite type */ - toid = get_rel_type_id(rte->relid); - if (!OidIsValid(toid)) - elog(ERROR, "could not find type OID for relation %u", - rte->relid); - result = makeVar(vnum, - InvalidAttrNumber, - toid, - -1, - sublevels_up); - break; - case RTE_FUNCTION: - toid = exprType(rte->funcexpr); - if (type_is_rowtype(toid)) - { - /* func returns composite; same as relation case */ - result = makeVar(vnum, - InvalidAttrNumber, - toid, - -1, - sublevels_up); - } - else - { - /* - * func returns scalar; instead of making a whole-row Var, - * just reference the function's scalar output. (XXX this - * seems a tad inconsistent, especially if "f.*" was - * explicitly written ...) - */ - result = makeVar(vnum, - 1, - toid, - -1, - sublevels_up); - } - break; - case RTE_VALUES: - toid = RECORDOID; - /* returns composite; same as relation case */ - result = makeVar(vnum, - InvalidAttrNumber, - toid, - -1, - sublevels_up); - break; - default: - - /* - * RTE is a join or subselect. We represent this as a whole-row - * Var of RECORD type. (Note that in most cases the Var will be - * expanded to a RowExpr during planning, but that is not our - * concern here.) - */ - result = makeVar(vnum, - InvalidAttrNumber, - RECORDOID, - -1, - sublevels_up); - break; - } - - /* location is not filled in by makeVar */ + /* location is not filled in by makeWholeRowVar */ result->location = location; /* mark relation as requiring whole-row SELECT access */ diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c index 31b25957b60..a332611a586 100644 --- a/src/backend/rewrite/rewriteHandler.c +++ b/src/backend/rewrite/rewriteHandler.c @@ -52,7 +52,8 @@ static TargetEntry *process_matched_tle(TargetEntry *src_tle, static Node *get_assignment_input(Node *node); static void rewriteValuesRTE(RangeTblEntry *rte, Relation target_relation, List *attrnos); -static void rewriteTargetListUD(Query *parsetree, Relation target_relation); +static void rewriteTargetListUD(Query *parsetree, RangeTblEntry *target_rte, + Relation target_relation); static void markQueryForLocking(Query *qry, Node *jtnode, bool forUpdate, bool noWait, bool pushedDown); static List *matchLocks(CmdType event, RuleLock *rulelocks, @@ -1110,7 +1111,8 @@ rewriteValuesRTE(RangeTblEntry *rte, Relation target_relation, List *attrnos) * ordering isn't actually critical at the moment. */ static void -rewriteTargetListUD(Query *parsetree, Relation target_relation) +rewriteTargetListUD(Query *parsetree, RangeTblEntry *target_rte, + Relation target_relation) { Var *var; const char *attrname; @@ -1135,11 +1137,9 @@ rewriteTargetListUD(Query *parsetree, Relation target_relation) * Emit whole-row Var so that executor will have the "old" view row * to pass to the INSTEAD OF trigger. */ - var = makeVar(parsetree->resultRelation, - InvalidAttrNumber, - RECORDOID, - -1, - 0); + var = makeWholeRowVar(target_rte, + parsetree->resultRelation, + 0); attrname = "wholerow"; } @@ -1858,11 +1858,11 @@ RewriteQuery(Query *parsetree, List *rewrite_events) else if (event == CMD_UPDATE) { rewriteTargetListIU(parsetree, rt_entry_relation, NULL); - rewriteTargetListUD(parsetree, rt_entry_relation); + rewriteTargetListUD(parsetree, rt_entry, rt_entry_relation); } else if (event == CMD_DELETE) { - rewriteTargetListUD(parsetree, rt_entry_relation); + rewriteTargetListUD(parsetree, rt_entry, rt_entry_relation); } else elog(ERROR, "unrecognized commandType: %d", (int) event); |