diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c index 002e15a9fa..e585e6df71 100644 --- a/src/backend/parser/parse_func.c +++ b/src/backend/parser/parse_func.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_func.c,v 1.179 2005/04/23 22:09:58 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_func.c,v 1.180 2005/05/31 01:03:23 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -25,6 +25,7 @@ #include "parser/parse_expr.h" #include "parser/parse_func.h" #include "parser/parse_relation.h" +#include "parser/parse_target.h" #include "parser/parse_type.h" #include "utils/builtins.h" #include "utils/fmgroids.h" @@ -957,6 +958,9 @@ ParseComplexProjection(ParseState *pstate, char *funcname, Node *first_arg) * function. A bonus is that we avoid generating an unnecessary * FieldSelect; our result can omit the whole-row Var and just be a * Var for the selected field. + * + * This case could be handled by expandRecordVariable, but it's + * more efficient to do it this way when possible. */ if (IsA(first_arg, Var) && ((Var *) first_arg)->varattno == InvalidAttrNumber) @@ -971,12 +975,18 @@ ParseComplexProjection(ParseState *pstate, char *funcname, Node *first_arg) } /* - * Else do it the hard way. Note that if the arg is of RECORD type, - * and isn't resolvable as a function with OUT params, we will never - * be able to recognize a column name here. + * Else do it the hard way with get_expr_result_type(). + * + * If it's a Var of type RECORD, we have to work even harder: we have + * to find what the Var refers to, and pass that to get_expr_result_type. + * That task is handled by expandRecordVariable(). */ - if (get_expr_result_type(first_arg, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) + if (IsA(first_arg, Var) && + ((Var *) first_arg)->vartype == RECORDOID) + tupdesc = expandRecordVariable(pstate, (Var *) first_arg, 0); + else if (get_expr_result_type(first_arg, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) return NULL; /* unresolvable RECORD type */ + Assert(tupdesc); for (i = 0; i < tupdesc->natts; i++) { diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c index ee523be03e..12acfb8302 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.133 2005/04/25 22:02:30 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_target.c,v 1.134 2005/05/31 01:03:23 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -44,8 +44,6 @@ static Node *transformAssignmentIndirection(ParseState *pstate, static List *ExpandColumnRefStar(ParseState *pstate, ColumnRef *cref); static List *ExpandAllTables(ParseState *pstate); static List *ExpandIndirectionStar(ParseState *pstate, A_Indirection *ind); -static TupleDesc expandRecordVariable(ParseState *pstate, Var *var, - int levelsup); static int FigureColnameInternal(Node *node, char **name); @@ -905,7 +903,7 @@ ExpandIndirectionStar(ParseState *pstate, A_Indirection *ind) * * levelsup is an extra offset to interpret the Var's varlevelsup correctly. */ -static TupleDesc +TupleDesc expandRecordVariable(ParseState *pstate, Var *var, int levelsup) { TupleDesc tupleDesc; diff --git a/src/include/parser/parse_target.h b/src/include/parser/parse_target.h index 30abd52c1a..35c2a41baf 100644 --- a/src/include/parser/parse_target.h +++ b/src/include/parser/parse_target.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/parser/parse_target.h,v 1.35 2004/12/31 22:03:38 pgsql Exp $ + * $PostgreSQL: pgsql/src/include/parser/parse_target.h,v 1.36 2005/05/31 01:03:23 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -27,6 +27,8 @@ extern void updateTargetListEntry(ParseState *pstate, TargetEntry *tle, List *indirection); extern List *checkInsertTargets(ParseState *pstate, List *cols, List **attrnos); +extern TupleDesc expandRecordVariable(ParseState *pstate, Var *var, + int levelsup); extern char *FigureColname(Node *node); #endif /* PARSE_TARGET_H */