diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c index b7abfe98399..ee523be03e1 100644 --- a/src/backend/parser/parse_target.c +++ b/src/backend/parser/parse_target.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_target.c,v 1.132 2005/04/25 21:03:25 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_target.c,v 1.133 2005/04/25 22:02:30 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -204,8 +204,9 @@ markTargetListOrigin(ParseState *pstate, TargetEntry *tle, tle->resorigcol = attnum; break; case RTE_SUBQUERY: + /* Subselect-in-FROM: copy up from the subselect */ + if (attnum != InvalidAttrNumber) { - /* Subselect-in-FROM: copy up from the subselect */ TargetEntry *ste = get_tle_by_resno(rte->subquery->targetList, attnum); @@ -217,8 +218,9 @@ markTargetListOrigin(ParseState *pstate, TargetEntry *tle, } break; case RTE_JOIN: + /* Join RTE --- recursively inspect the alias variable */ + if (attnum != InvalidAttrNumber) { - /* Join RTE --- recursively inspect the alias variable */ Var *aliasvar; Assert(attnum > 0 && attnum <= list_length(rte->joinaliasvars)); @@ -920,6 +922,37 @@ expandRecordVariable(ParseState *pstate, Var *var, int levelsup) rte = GetRTEByRangeTablePosn(pstate, var->varno, netlevelsup); attnum = var->varattno; + if (attnum == InvalidAttrNumber) + { + /* Whole-row reference to an RTE, so expand the known fields */ + List *names, + *vars; + ListCell *lname, + *lvar; + int i; + + expandRTE(GetLevelNRangeTable(pstate, netlevelsup), + var->varno, 0, false, &names, &vars); + + tupleDesc = CreateTemplateTupleDesc(list_length(vars), false); + i = 1; + forboth(lname, names, lvar, vars) + { + char *label = strVal(lfirst(lname)); + Node *varnode = (Node *) lfirst(lvar); + + TupleDescInitEntry(tupleDesc, i, + label, + exprType(varnode), + exprTypmod(varnode), + 0); + i++; + } + Assert(lname == NULL && lvar == NULL); /* lists same length? */ + + return tupleDesc; + } + expr = (Node *) var; /* default if we can't drill down */ switch (rte->rtekind) @@ -927,10 +960,9 @@ expandRecordVariable(ParseState *pstate, Var *var, int levelsup) case RTE_RELATION: case RTE_SPECIAL: /* - * This case should not occur: a whole-row Var should have the - * table's named rowtype, and a column of a table shouldn't have - * type RECORD either. Fall through and fail (most likely) - * at the bottom. + * This case should not occur: a column of a table shouldn't have + * type RECORD. Fall through and fail (most likely) at the + * bottom. */ break; case RTE_SUBQUERY: @@ -963,37 +995,7 @@ expandRecordVariable(ParseState *pstate, Var *var, int levelsup) } break; case RTE_JOIN: - /* Join RTE */ - if (attnum == InvalidAttrNumber) - { - /* Whole-row reference to join, so expand the fields */ - List *names, - *vars; - ListCell *lname, - *lvar; - int i; - - expandRTE(GetLevelNRangeTable(pstate, netlevelsup), - var->varno, 0, false, &names, &vars); - - tupleDesc = CreateTemplateTupleDesc(list_length(vars), false); - i = 1; - forboth(lname, names, lvar, vars) - { - char *label = strVal(lfirst(lname)); - Node *varnode = (Node *) lfirst(lvar); - - TupleDescInitEntry(tupleDesc, i, - label, - exprType(varnode), - exprTypmod(varnode), - 0); - i++; - } - Assert(lname == NULL && lvar == NULL); /* lists same len? */ - return tupleDesc; - } - /* Else recursively inspect the alias variable */ + /* Join RTE --- recursively inspect the alias variable */ Assert(attnum > 0 && attnum <= list_length(rte->joinaliasvars)); expr = (Node *) list_nth(rte->joinaliasvars, attnum - 1); if (IsA(expr, Var)) @@ -1001,11 +1003,10 @@ expandRecordVariable(ParseState *pstate, Var *var, int levelsup) /* else fall through to inspect the expression */ break; case RTE_FUNCTION: - expr = rte->funcexpr; - /* The func expr probably can't be a Var, but check */ - if (IsA(expr, Var)) - return expandRecordVariable(pstate, (Var *) expr, netlevelsup); - /* else fall through to inspect the expression */ + /* + * We couldn't get here unless a function is declared with one + * of its result columns as RECORD, which is not allowed. + */ break; }