From 23160139617f6cb998604c7324da2175f7409db5 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Thu, 16 Mar 2006 00:31:55 +0000 Subject: Clean up representation of function RTEs for functions returning RECORD. The original coding stored the raw parser output (ColumnDef and TypeName nodes) which was ugly, bulky, and wrong because it failed to create any dependency on the referenced datatype --- and in fact would not track type renamings and suchlike. Instead store a list of column type OIDs in the RTE. Also fix up general failure of recordDependencyOnExpr to do anything sane about recording dependencies on datatypes. While there are many cases where there will be an indirect dependency (eg if an operator returns a datatype, the dependency on the operator is enough), we do have to record the datatype as a separate dependency in examples like CoerceToDomain. initdb forced because of change of stored rules. --- src/backend/parser/parse_clause.c | 24 ++++++++------ src/backend/parser/parse_relation.c | 63 +++++++++++++++++++------------------ 2 files changed, 47 insertions(+), 40 deletions(-) (limited to 'src/backend/parser') diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c index 4384a4eaab8..9bdb91b4744 100644 --- a/src/backend/parser/parse_clause.c +++ b/src/backend/parser/parse_clause.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_clause.c,v 1.148 2006/03/14 22:48:20 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_clause.c,v 1.149 2006/03/16 00:31:55 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -537,23 +537,27 @@ transformRangeFunction(ParseState *pstate, RangeFunction *r) } /* - * If a coldeflist is supplied, ensure it defines a legal set of names (no - * duplicates) and datatypes (no pseudo-types, for instance). + * OK, build an RTE for the function. + */ + rte = addRangeTableEntryForFunction(pstate, funcname, funcexpr, + r, true); + + /* + * If a coldeflist was supplied, ensure it defines a legal set of names + * (no duplicates) and datatypes (no pseudo-types, for instance). + * addRangeTableEntryForFunction looked up the type names but didn't + * check them further than that. */ if (r->coldeflist) { TupleDesc tupdesc; - tupdesc = BuildDescForRelation(r->coldeflist); + tupdesc = BuildDescFromLists(rte->eref->colnames, + rte->funccoltypes, + rte->funccoltypmods); CheckAttributeNamesTypes(tupdesc, RELKIND_COMPOSITE_TYPE); } - /* - * OK, build an RTE for the function. - */ - rte = addRangeTableEntryForFunction(pstate, funcname, funcexpr, - r, true); - return rte; } diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c index d0f78b119cd..e8e11ad167a 100644 --- a/src/backend/parser/parse_relation.c +++ b/src/backend/parser/parse_relation.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_relation.c,v 1.120 2006/03/14 22:48:21 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_relation.c,v 1.121 2006/03/16 00:31:55 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -835,7 +835,8 @@ addRangeTableEntryForFunction(ParseState *pstate, rte->relid = InvalidOid; rte->subquery = NULL; rte->funcexpr = funcexpr; - rte->coldeflist = coldeflist; + rte->funccoltypes = NIL; + rte->funccoltypmods = NIL; rte->alias = alias; eref = makeAlias(alias ? alias->aliasname : funcname, NIL); @@ -883,14 +884,28 @@ addRangeTableEntryForFunction(ParseState *pstate, { ListCell *col; - /* Use the column definition list to form the alias list */ + /* + * Use the column definition list to form the alias list and + * funccoltypes/funccoltypmods lists. + */ foreach(col, coldeflist) { - ColumnDef *n = lfirst(col); + ColumnDef *n = (ColumnDef *) lfirst(col); char *attrname; + Oid attrtype; + int32 attrtypmod; attrname = pstrdup(n->colname); + if (n->typename->setof) + ereport(ERROR, + (errcode(ERRCODE_INVALID_TABLE_DEFINITION), + errmsg("column \"%s\" cannot be declared SETOF", + attrname))); eref->colnames = lappend(eref->colnames, makeString(attrname)); + attrtype = typenameTypeId(pstate, n->typename); + attrtypmod = n->typename->typmod; + rte->funccoltypes = lappend_oid(rte->funccoltypes, attrtype); + rte->funccoltypmods = lappend_int(rte->funccoltypmods, attrtypmod); } } else @@ -1181,36 +1196,26 @@ expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up, } else if (functypclass == TYPEFUNC_RECORD) { - List *coldeflist = rte->coldeflist; - ListCell *col; - int attnum = 0; - - foreach(col, coldeflist) + if (colnames) + *colnames = copyObject(rte->eref->colnames); + if (colvars) { - ColumnDef *colDef = lfirst(col); + ListCell *l1; + ListCell *l2; + int attnum = 0; - attnum++; - if (colnames) - { - char *attrname; - - attrname = pstrdup(colDef->colname); - *colnames = lappend(*colnames, makeString(attrname)); - } - - if (colvars) + forboth(l1, rte->funccoltypes, l2, rte->funccoltypmods) { + Oid attrtype = lfirst_oid(l1); + int32 attrtypmod = lfirst_int(l2); Var *varnode; - Oid atttypid; - - atttypid = typenameTypeId(NULL, colDef->typename); + attnum++; varnode = makeVar(rtindex, attnum, - atttypid, - colDef->typename->typmod, + attrtype, + attrtypmod, sublevels_up); - *colvars = lappend(*colvars, varnode); } } @@ -1548,10 +1553,8 @@ get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum, } else if (functypclass == TYPEFUNC_RECORD) { - ColumnDef *colDef = list_nth(rte->coldeflist, attnum - 1); - - *vartype = typenameTypeId(NULL, colDef->typename); - *vartypmod = colDef->typename->typmod; + *vartype = list_nth_oid(rte->funccoltypes, attnum - 1); + *vartypmod = list_nth_int(rte->funccoltypmods, attnum - 1); } else { -- cgit v1.2.3