Thread: No error when column doesn't exist

No error when column doesn't exist

From
Dean Rasheed
Date:
I've just spent a couple of hours tracking down a bug which turned out
to be a typo in my code. What surprises me is that the SQL in question
didn't immediately produce an error. Here's a simplified example:

CREATE TABLE foo(a int, b int);
INSERT INTO foo VALUES(1,2);
SELECT foo.text FROM foo;

I expected that to generate an error: column foo.text does not exist.
Instead it treats "foo.text" as "foo.*::text AS text":

SELECT foo.text FROM foo;
 text
-------
 (1,2)
(1 row)

If foo actually does have a column called text, this works as expected,
selecting just that column.

Is this a feature or a bug?

Dean

_________________________________________________________________
Make a mini you and download it into Windows Live Messenger
http://clk.atdmt.com/UKM/go/111354029/direct/01/

Re: No error when column doesn't exist

From
Tom Lane
Date:
Dean Rasheed <dean_rasheed@hotmail.com> writes:
> CREATE TABLE foo(a int, b int);
> INSERT INTO foo VALUES(1,2);
> SELECT foo.text FROM foo;

> I expected that to generate an error: column foo.text does not exist.
> Instead it treats "foo.text" as "foo.*::text AS text":
> Is this a feature or a bug?

Hmm.  It's a feature, but maybe a dangerous one.  The expression is
being treated as text(foo), which is intentional in order to allow
use of functions as if they were virtual columns.  However, then it
decides that what you've got there is a cast request.  There wasn't
any ability to cast composite types to text before 8.3, so this fails
in the expected way in 8.2 and before; but in 8.3 the cast
interpretation succeeds, and away we go.

foo.char and foo.varchar have similarly unexpected behavior; I think
that's probably the end of it, though, since those are the only types
that CoerceViaIO will take as targets.

Maybe we could/should restrict things so that the syntax continues to
fail, but I can't think of any restrictions that don't seem like warts.
What's worse, they might break stuff that used to work.

            regards, tom lane

Re: No error when column doesn't exist

From
Artacus
Date:
>> I expected that to generate an error: column foo.text does not exist.
>> Instead it treats "foo.text" as "foo.*::text AS text":
>> Is this a feature or a bug?
>
> Hmm.  It's a feature, but maybe a dangerous one.  The expression is
> being treated as text(foo), which is intentional in order to allow
> use of functions as if they were virtual columns.  However, then it
> decides that what you've got there is a cast request.  There wasn't
> any ability to cast composite types to text before 8.3, so this fails
> in the expected way in 8.2 and before; but in 8.3 the cast
> interpretation succeeds, and away we go.
>
> foo.char and foo.varchar have similarly unexpected behavior; I think
> that's probably the end of it, though, since those are the only types
> that CoerceViaIO will take as targets.
>
> Maybe we could/should restrict things so that the syntax continues to
> fail, but I can't think of any restrictions that don't seem like warts.
> What's worse, they might break stuff that used to work.

I like that functionality and think the behavior is as it should be.
Best practice is to not name columns with reserved words. So maybe we
could update the manual with another reason not to use SQL reserved
words as column names.


Re: No error when column doesn't exist

From
Dean Rasheed
Date:
> Hmm.  It's a feature, but maybe a dangerous one.  The expression is
> being treated as text(foo), which is intentional in order to allow
> use of functions as if they were virtual columns.  However, then it
> decides that what you've got there is a cast request.  There wasn't
> any ability to cast composite types to text before 8.3, so this fails
> in the expected way in 8.2 and before; but in 8.3 the cast
> interpretation succeeds, and away we go.
>

Thanks for the explanation. I see what's going on now.

> foo.char and foo.varchar have similarly unexpected behavior; I think
> that's probably the end of it, though, since those are the only types
> that CoerceViaIO will take as targets.
>

... and also any user defined domains based on those, which is
what I actually had. I was unlucky enough that the row text matched
the regexp on my domain, so my typo went unnoticed for a while ;-(

> Maybe we could/should restrict things so that the syntax continues to
> fail, but I can't think of any restrictions that don't seem like warts.
> What's worse, they might break stuff that used to work.
>
>             regards, tom lane

OK, I can live with that. At least I know what to look out for now!

Cheers, Dean

_________________________________________________________________
Win New York holidays with Kellogg’s & Live Search
http://clk.atdmt.com/UKM/go/111354033/direct/01/

Re: No error when column doesn't exist

From
Tom Lane
Date:
Dean Rasheed <dean_rasheed@hotmail.com> writes:
>> foo.char and foo.varchar have similarly unexpected behavior; I think
>> that's probably the end of it, though, since those are the only types
>> that CoerceViaIO will take as targets.

> ... and also any user defined domains based on those, which is
> what I actually had.

Ouch.  That makes the scope for unexpected behavior wider than I thought.
Maybe we do need some restriction here?

The ideas I had involved not considering the cast interpretation when
the actual syntax is table.column and some-set-of-other-conditions.
While this is certainly possible to implement, any variant of it will
break the existing 100% equivalence of foo.bar and bar(foo); which
seems to me to be a nice principle, though I grant you won't find it
anywhere in the SQL standard.

The other-conditions are a bit up for grabs.  The narrowest restriction
that would serve the purpose is "table variable is of composite type
and the cast would be a CoerceViaIO cast", but that definitely seems
like a wart.  However, cleaner-seeming restrictions like "no casts on
composites at all" could potentially break applications that worked
okay before 8.3.

Comments anyone?  Should we try to change this, or leave well enough
alone?

            regards, tom lane

Re: No error when column doesn't exist

From
Peter Eisentraut
Date:
Tom Lane wrote:
> The ideas I had involved not considering the cast interpretation when
> the actual syntax is table.column and some-set-of-other-conditions.
> While this is certainly possible to implement, any variant of it will
> break the existing 100% equivalence of foo.bar and bar(foo); which
> seems to me to be a nice principle, though I grant you won't find it
> anywhere in the SQL standard.

I think if we say that functions can be used as table attributes, and
types can be used as (cast) functions, and tables are types, then we are
simply stuck with the current behavior.  Individually, these all make
sense, so you can't break that chain without some really complicated warts.