| From: | Manu <manuelreyesbravo(at)gmail(dot)com> |
|---|---|
| To: | jian he <jian(dot)universality(at)gmail(dot)com> |
| Cc: | Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>, PostgreSQL-development <pgsql-hackers(at)postgresql(dot)org>, exclusion(at)gmail(dot)com, Michael Paquier <michael(at)paquier(dot)xyz> |
| Subject: | Re: ERROR: failed to find conversion function from unknown to text |
| Date: | 2026-09-24 14:16:58 |
| Message-ID: | 179025941896.2174816.931420670756223956@gmail.com |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-hackers |
Hi jian,
> Another issue is
>
> src1=# select cast(NULL::text as unknown);
> ERROR: cannot cast type unknown to text
> ...
> The error cursor points to the word "cast", the statement is "cast
> text as unknown"
> and the error message is "cannot cast type unknown to text".
> So the whole thing is very confusing for regular users.
> Maybe removing parser_coercion_errposition?
I tried that on master (89829354de1), with the same query and ten
others that reach this error, before and after. The position turns
out to be the useful part. It points at the expression whose type is
unknown, which is what the user has to change:
select a, c, cast(b as unknown) as bad, c + 1 from t;
ERROR: cannot cast type unknown to text
LINE 1: select a, c, cast(b as unknown) as bad, c + 1 from t;
^
create view v as
select a,
c,
cast(b as unknown) as bad
from t;
ERROR: cannot cast type unknown to text
LINE 4: cast(b as unknown) as bad
^
Without parser_coercion_errposition() every case prints only the
ERROR line, so in a view like that there is nothing to say which
column it is.
What is confusing in your example is the "to text": that conversion
is the one that resolves the output column, and the user never wrote
it. A hint that says what to do covers that, and keeps the position:
ERROR: cannot cast type unknown to text
LINE 1: select cast(NULL::text as unknown);
^
HINT: Cast the expression to the type you want directly, not to
type unknown.
transformAssignedExpr() does the same for a type mismatch: it keeps
the position and adds "You will need to rewrite or cast the
expression."
I also tried an errdetail saying that only a literal of type unknown
can be converted to another type, and dropped it because it isn't
true: parameters of type unknown are converted too.
PREPARE p(unknown) AS SELECT $1::text works, before and after the
patch.
With the hint, make check passes (239), with no new warnings. One
case has no position with any wording, a UNION branch:
select a from t union all select cast(b as unknown) from t;
The set-operation coercion does not pass a location. That is how it
is today and I left it alone.
> I guess I understand your comments, below are the comments I came up
> with.
> What do you think?
It reads well, and what it says about can_coerce_type() is right: it
does "if (inputTypeId == UNKNOWNOID) continue;". One thing I would
add, for the same reason as the errdetail above: parameters of type
unknown are also handled before this point, through
p_coerce_param_hook, so "Unknown-type literals and parameters were
coerced above."
The SQL and the output of each variant are attached.
Regards,
Manu
| Attachment | Content-Type | Size |
|---|---|---|
| nocfbot-unknown-error-wording.sql.txt | text/plain | 8.4 KB |
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Peter Eisentraut | 2026-09-24 14:20:59 | pgindent to ignore build directories |
| Previous Message | Tom Lane | 2026-09-24 14:13:29 | Re: potentially missed pgindent in REL_19_STABLE |