aboutsummaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/nodes/makefuncs.c87
-rw-r--r--src/backend/optimizer/prep/preptlist.c8
-rw-r--r--src/backend/parser/parse_expr.c76
-rw-r--r--src/backend/rewrite/rewriteHandler.c18
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);