Location for "makeWholeRowVar()"?

From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: pgsql-hackers(at)postgreSQL(dot)org
Subject: Location for "makeWholeRowVar()"?
Date: 2010-10-19 17:09:10
Message-ID: 28198.1287508150@sss.pgh.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

The cause of bug #5716 is that preprocess_targetlist is trying to get
away with creating a whole-row variable marked with type RECORDOID,
even in cases where a specific composite type is known for the
referenced RTE. This fails because now we might have non-equal Vars
representing the same RTE attribute in different places in the same
query.

I think the best fix for this is to have one and only one function
generating whole-row Vars, which means pulling out the guts of the
parser's transformWholeRowRef() function into a function that looks
like the attached. Now I'm wondering where to put it. I'm tempted
to put it into makefuncs.c next to makeVar(), and it fits there without
needing to add any new #includes; but it looks a tad more complicated
than most other functions in makefuncs.c. Does anyone think this is
a bad place for it, and if so where would you put it instead?

regards, tom lane

/*
* makeWholeRowVar -
* creates a Var node representing a whole row from the specified RTE
*/
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;
}

Browse pgsql-hackers by date

  From Date Subject
Next Message Marios Vodas 2010-10-19 17:12:35 Re: knngist plans
Previous Message Andrew Dunstan 2010-10-19 16:53:01 Re: WIP: extensible enums