Hello, I think this is a bug. The core of this problem is that coerce_type() fails for Var of type UNKNOWNOID.
The comment for the function says that, > * The caller should already have determined that the coercion is possible; > * see can_coerce_type. But can_coerce_type() should say it's possible to convert from unknown to any type as it doesn't see the target node type. I think this as an inconsistency between can_coerce_type and coerce_type. So making this consistent would be right way. Concerning only this issue, putting on-the-fly conversion for unkown nonconstant as attached patch worked for me. I'm not so confident on this, though.. regards, At Wed, 22 Apr 2015 23:26:43 -0700, Jeff Davis <pg...@j-davis.com> wrote in <1429770403.4604.22.camel@jeff-desktop> > On Wed, 2015-04-22 at 20:35 -0700, David G. Johnston wrote: > > > But the fact that column "b" has the data type "unknown" is only a > > warning - not an error. > > > I get an error: > > postgres=# SELECT ' '::text = 'a'; > ?column? > ---------- > f > (1 row) > > postgres=# SELECT a=b FROM (SELECT ''::text, ' ') x(a,b); > ERROR: failed to find conversion function from unknown to text > > So that means the column reference "b" is treated differently than the > literal. Here I don't mean a reference to an actual column of a real > table, just an identifier ("b") that parses as a columnref. > > Creating the table gives you a warning (not an error), but I think that > was a poor example for me to choose, and not important to my point. > > > > This seems to be a case of the common problem (or, at least recently > > mentioned) where type conversion only deals with data and not context. > > > > > > http://www.postgresql.org/message-id/CADx9qBmVPQvSH3 > > +2cH4cwwPmphW1mE18e=wumlfuc-qz-t7...@mail.gmail.com > > > > > I think that is a different problem. That's a runtime type conversion > error (execution time), and I'm talking about something happening at > parse analysis time. > > > > > but this too works - which is why the implicit cast concept above > > fails (I'm leaving it since the thought process may help in > > understanding): > > > > > > SELECT 1 = '1'; > > > > > > From which I infer that an unknown literal is allowed to be fed > > directly into a type's input function to facilitate a direct coercion. > > Yes, I believe that's what's happening. When we use an unknown literal, > it's acting more like a value constructor and will pass it to the type > input function. When it's a columnref, even if unknown, it tries to cast > it and fails. > > But that is very confusing. In the example at the top of this email, it > seems like the second query should be equivalent to the first, or even > that postgres should be able to rewrite the second into the first. But > the second query fails where the first succeeds. > > > > At this point...backward compatibility? > > Backwards compatibility of what queries? I guess the ones that return > unknowns to the client or create tables with unknown columns? > > > create table a(u) as select '1'; > > > > > > WARNING: "column "u" has type "unknown" > > DETAIL: Proceeding with relation creation anyway. > > > > > > Related question: was there ever a time when the above failed instead > > of just supplying a warning? > > Not that I recall. > > > > > My gut reaction is if you feel strongly enough to add some additional > > documentation or warnings/hints/details related to this topic they > > probably would get put in; but disallowing "unknown" as first-class > > type is likely to fail to pass a cost-benefit evaluation. > > I'm not proposing that we eliminate unknown. I just think columnrefs and > literals should behave consistently. If we really don't want unknown > columnrefs, it seems like we could at least throw a better error. > > If we were starting from scratch, I'd also not return unknown to the > client, but we have to worry about the backwards compatibility. > > > Distinguishing between "untyped" literals and "unknown type" literals > > seems promising concept to aid in understanding the difference in the > > face of not being able (or wanting) to actually change the behavior. > > Not sure I understand that proposal, can you elaborate? -- Kyotaro Horiguchi NTT Open Source Software Center
diff --git a/src/backend/parser/parse_coerce.c b/src/backend/parser/parse_coerce.c index a4e494b..b64d40b 100644 --- a/src/backend/parser/parse_coerce.c +++ b/src/backend/parser/parse_coerce.c @@ -221,7 +221,7 @@ coerce_type(ParseState *pstate, Node *node, return node; } } - if (inputTypeId == UNKNOWNOID && IsA(node, Const)) + if (inputTypeId == UNKNOWNOID) { /* * Input is a string constant with previously undetermined type. Apply @@ -275,6 +275,29 @@ coerce_type(ParseState *pstate, Node *node, targetType = typeidType(baseTypeId); + /* Perform on the fly conversion for non-constants */ + if(!IsA(node, Const)) + { + Form_pg_type typform = (Form_pg_type) GETSTRUCT(targetType); + Node *result = + (Node*) makeFuncExpr(typform->typinput, + targetTypeId, + list_make3(node, + makeConst(OIDOID, -1, InvalidOid, + sizeof(Oid), + ObjectIdGetDatum(InvalidOid), + false, true), + makeConst(INT4OID, -1, InvalidOid, + sizeof(uint32), + Int32GetDatum(inputTypeMod), + false, true)), + InvalidOid, InvalidOid, + COERCE_IMPLICIT_CAST); + ReleaseSysCache(targetType); + + return result; + } + newcon->consttype = baseTypeId; newcon->consttypmod = inputTypeMod; newcon->constcollid = typeTypeCollation(targetType);
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers