diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2008-10-05 22:50:55 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2008-10-05 22:50:55 +0000 |
commit | 1e4b03847c95287a81d531ab2a249ad07081c767 (patch) | |
tree | 8d6bb560129d18e278a3c2d9748ed8e5160fe446 /src/backend/parser | |
parent | 08142504743bc79feb233f42ae24246273102813 (diff) | |
download | postgresql-1e4b03847c95287a81d531ab2a249ad07081c767.tar.gz postgresql-1e4b03847c95287a81d531ab2a249ad07081c767.zip |
Improve behavior of WITH RECURSIVE with an untyped literal in the
non-recursive term. Per an example from Dickson S. Guedes.
Diffstat (limited to 'src/backend/parser')
-rw-r--r-- | src/backend/parser/parse_cte.c | 26 |
1 files changed, 21 insertions, 5 deletions
diff --git a/src/backend/parser/parse_cte.c b/src/backend/parser/parse_cte.c index 64f5e51c28f..29111acb968 100644 --- a/src/backend/parser/parse_cte.c +++ b/src/backend/parser/parse_cte.c @@ -8,12 +8,13 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_cte.c,v 2.1 2008/10/04 21:56:54 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_cte.c,v 2.2 2008/10/05 22:50:55 tgl Exp $ * *------------------------------------------------------------------------- */ #include "postgres.h" +#include "catalog/pg_type.h" #include "nodes/nodeFuncs.h" #include "parser/analyze.h" #include "parser/parse_cte.h" @@ -339,6 +340,8 @@ analyzeCTETargetList(ParseState *pstate, CommonTableExpr *cte, List *tlist) foreach(tlistitem, tlist) { TargetEntry *te = (TargetEntry *) lfirst(tlistitem); + Oid coltype; + int32 coltypmod; if (te->resjunk) continue; @@ -351,10 +354,23 @@ analyzeCTETargetList(ParseState *pstate, CommonTableExpr *cte, List *tlist) attrname = pstrdup(te->resname); cte->ctecolnames = lappend(cte->ctecolnames, makeString(attrname)); } - cte->ctecoltypes = lappend_oid(cte->ctecoltypes, - exprType((Node *) te->expr)); - cte->ctecoltypmods = lappend_int(cte->ctecoltypmods, - exprTypmod((Node *) te->expr)); + coltype = exprType((Node *) te->expr); + coltypmod = exprTypmod((Node *) te->expr); + /* + * If the CTE is recursive, force the exposed column type of any + * "unknown" column to "text". This corresponds to the fact that + * SELECT 'foo' UNION SELECT 'bar' will ultimately produce text. + * We might see "unknown" as a result of an untyped literal in + * the non-recursive term's select list, and if we don't convert + * to text then we'll have a mismatch against the UNION result. + */ + if (cte->cterecursive && coltype == UNKNOWNOID) + { + coltype = TEXTOID; + coltypmod = -1; /* should be -1 already, but be sure */ + } + cte->ctecoltypes = lappend_oid(cte->ctecoltypes, coltype); + cte->ctecoltypmods = lappend_int(cte->ctecoltypmods, coltypmod); } if (varattno < numaliases) ereport(ERROR, |