When is a record NULL?

Started by David E. Wheelerover 16 years ago56 messageshackers
Jump to latest
#1David E. Wheeler
david@kineticode.com

How can a record be neither NULL or NOT NULL?

try=# select ROW(1, NULL) IS NULL;
?column?
----------
f
(1 row)

try=# select ROW(1, NULL) IS NOT NULL;
?column?
----------
f
(1 row)

This makes it rather hard to tell, in PL/pgSQL, when I've fetched the
last record from a cursor…

Best,

David

#2David E. Wheeler
david@kineticode.com
In reply to: David E. Wheeler (#1)
Re: When is a record NULL?

On Jul 23, 2009, at 3:19 PM, David E. Wheeler wrote:

How can a record be neither NULL or NOT NULL?

try=# select ROW(1, NULL) IS NULL;
?column?
----------
f
(1 row)

try=# select ROW(1, NULL) IS NOT NULL;
?column?
----------
f
(1 row)

This makes it rather hard to tell, in PL/pgSQL, when I've fetched
the last record from a cursor…

Also:

select ROW(1, NULL) IS DISTINCT FROM ROW(2, NULL);
?column?
----------
t

As expected, but the IS NULL above is not expected (by this bunny,
anyway).

Best,

David

#3Jeff Davis
pgsql@j-davis.com
In reply to: David E. Wheeler (#1)
Re: When is a record NULL?

On Thu, 2009-07-23 at 15:19 -0700, David E. Wheeler wrote:

How can a record be neither NULL or NOT NULL?

You could do:

not ROW(1, NULL) is null and not ROW(1, NULL) is not null

I don't know what the SQL standard says about this.

Regards,
Jeff Davis

#4Tom Lane
tgl@sss.pgh.pa.us
In reply to: David E. Wheeler (#1)
Re: When is a record NULL?

"David E. Wheeler" <david@kineticode.com> writes:

How can a record be neither NULL or NOT NULL?

This is per SQL standard. IS NULL is true if *all* the record's
fields are null; IS NOT NULL is true if *none* of them are.

Yeah, it's a bit dubious, but that's what they said.

regards, tom lane

#5David E. Wheeler
david@kineticode.com
In reply to: Tom Lane (#4)
Re: When is a record NULL?

On Jul 23, 2009, at 4:08 PM, Tom Lane wrote:

This is per SQL standard. IS NULL is true if *all* the record's
fields are null; IS NOT NULL is true if *none* of them are.

Yeah, it's a bit dubious, but that's what they said.

And yet they're DISTINCT FROM each other if either or both contain
NULLs and some other values? It seems to me that, to be consistent, it
should be:

select ROW(1, NULL) IS DISTINCT FROM ROW(2, NULL);
?column?
----------
f

No?

Best,

David

#6Tom Lane
tgl@sss.pgh.pa.us
In reply to: David E. Wheeler (#5)
Re: When is a record NULL?

"David E. Wheeler" <david@kineticode.com> writes:

And yet they're DISTINCT FROM each other if either or both contain
NULLs and some other values?

Well, that would depend on what the values were and in what columns...

It seems to me that, to be consistent, it
should be:

select ROW(1, NULL) IS DISTINCT FROM ROW(2, NULL);
?column?
----------
f

Dunno how you can possibly come to that conclusion. Those row
values are certainly distinct (according to both PG and the spec).

regards, tom lane

#7David E. Wheeler
david@kineticode.com
In reply to: Tom Lane (#6)
Re: When is a record NULL?

On Jul 23, 2009, at 4:22 PM, Tom Lane wrote:

Dunno how you can possibly come to that conclusion. Those row
values are certainly distinct (according to both PG and the spec).

Are they not both null?

David

#8David E. Wheeler
david@kineticode.com
In reply to: Jeff Davis (#3)
Re: When is a record NULL?

On Jul 23, 2009, at 3:33 PM, Jeff Davis wrote:

not ROW(1, NULL) is null and not ROW(1, NULL) is not null

I don't know what the SQL standard says about this

Thanks Jeff, that's just what I needed.

Best,

David

#9Jeff Davis
pgsql@j-davis.com
In reply to: David E. Wheeler (#7)
Re: When is a record NULL?

On Thu, 2009-07-23 at 17:32 -0700, David E. Wheeler wrote:

On Jul 23, 2009, at 4:22 PM, Tom Lane wrote:

Dunno how you can possibly come to that conclusion. Those row
values are certainly distinct (according to both PG and the spec).

Are they not both null?

[ Is that a play on words? ;) ]

Here's the logical breakdown of your argument:

x = ROW(1, NULL)

0. x IS NOT NULL = false
1. => NOT x IS NOT NULL = true
2. => NOT NOT x IS NULL = true
3. => x IS NULL = true

However, in step 2, you transformed:
x IS NOT NULL => NOT x IS NULL

But in SQL that is not a tautology!

I don't think it's wise to assume SQL is consistent. I think it is
possible to create a consistent 3VL system, but you have to give up some
other very important property. I can't remember the details at the
moment, but there's an interesting proof in "Logic and Databases" by
C.J. Date.

Does the SQL spec lay out the tautologies anywhere, so that we can get a
clear picture of what's going on with NULLs? I won't make the claim that
SQL is inconsistent without actually seeing the system as a whole, but,
at a minimum, many of the tautologies that people are accustomed to are
not true in SQL.

Regards,
Jeff Davis

#10Bruce Momjian
bruce@momjian.us
In reply to: David E. Wheeler (#7)
Re: When is a record NULL?

On Fri, Jul 24, 2009 at 1:32 AM, David E. Wheeler<david@kineticode.com> wrote:

On Jul 23, 2009, at 4:22 PM, Tom Lane wrote:

Dunno how you can possibly come to that conclusion.  Those row
values are certainly distinct (according to both PG and the spec).

Are they not both null?

Isn't that just what you were complaining about not being the case:

On Thu, Jul 23, 2009 at 11:29 PM, David E. Wheeler<david@kineticode.com> wrote:

try=# select ROW(1, NULL) IS NULL;
?column?
----------
f
(1 row)

--
greg
http://mit.edu/~gsstark/resume.pdf

#11David E. Wheeler
david@kineticode.com
In reply to: Bruce Momjian (#10)
Re: When is a record NULL?

On Jul 23, 2009, at 6:21 PM, Greg Stark wrote:

Are they not both null?

Isn't that just what you were complaining about not being the case:

Yes, but given that the standard says that `ROW(1, NULL)` is NULL,
then I would expect it to be NOT DISTINCT from `ROW(2, NULL)`.

Best,

David

#12David E. Wheeler
david@kineticode.com
In reply to: Jeff Davis (#9)
Re: When is a record NULL?

On Jul 23, 2009, at 6:06 PM, Jeff Davis wrote:

However, in step 2, you transformed:
x IS NOT NULL => NOT x IS NULL

But in SQL that is not a tautology!

No, that's not the problem I see -- that solved the problem in my
particular code. The problem I see is that, given that the standard
says (according to Tom) that if any value is NULL then the record is
NULL, then I would expect this to return false:

SELECT ROW(1, NULL) IS DISTINCT FROM ROW(2, NULL);

But it returns true.

I don't think it's wise to assume SQL is consistent. I think it is
possible to create a consistent 3VL system, but you have to give up
some
other very important property. I can't remember the details at the
moment, but there's an interesting proof in "Logic and Databases" by
C.J. Date.

If the standard says that, in the case of records, two NULLs are
distinct, then fine. Completely bizarre, but fine. But I suspect that
such is not the case.

Best,

David

#13David E. Wheeler
david@kineticode.com
In reply to: David E. Wheeler (#12)
Re: When is a record NULL?

On Jul 23, 2009, at 6:52 PM, David E. Wheeler wrote:

No, that's not the problem I see -- that solved the problem in my
particular code. The problem I see is that, given that the standard
says (according to Tom) that if any value is NULL then the record is
NULL, then I would expect this to return false:

SELECT ROW(1, NULL) IS DISTINCT FROM ROW(2, NULL);

But it returns true.

Sorry, I'm confused. Understandable I think. So:

ROW(1, NULL) is neither NULL nor NOT NULL. I've no idea what state it
is, but I guess that's the standard. In this case, IS DISTINCT FROM
gives me a sensible return value -- it assumes that the records are
NOT NULL, I guess, for its purposes. This is still inconsistent, since
the records are neither NULL nor NOT NULL, but perhaps sensible.

It's pretty insane, frankly. Gotta love SQL.

Best,

David

#14Brendan Jurd
direvus@gmail.com
In reply to: David E. Wheeler (#13)
Re: When is a record NULL?

2009/7/24 David E. Wheeler <david@kineticode.com>:

ROW(1, NULL) is neither NULL nor NOT NULL. I've no idea what state it is,
but I guess that's the standard.

Well, a ROW is an ordered set of values, each one of which may be
either NULL or NOT NULL.

It doesn't really make sense to talk about the ROW itself being NULL
or NOT NULL, only its member values (but for extra confusion, contrast
with the treatment of arrays, which can themselves be NULL).

It does make sense, however, to talk about the ROW's member values
being entirely NULL or entirely NOT NULL, and that's what the IS NULL
and IS NOT NULL tests tell you about.

I guess the spec authors figured they might as well make IS [NOT] NULL
do something useful when applied to a row rather than throwing an
error. I tend to agree.

I hope that provides some clarity.

Cheers,
BJ

#15David E. Wheeler
david@kineticode.com
In reply to: Brendan Jurd (#14)
Re: When is a record NULL?

On Jul 23, 2009, at 9:34 PM, Brendan Jurd wrote:

Well, a ROW is an ordered set of values, each one of which may be
either NULL or NOT NULL.

Right.

It doesn't really make sense to talk about the ROW itself being NULL
or NOT NULL, only its member values (but for extra confusion, contrast
with the treatment of arrays, which can themselves be NULL).

Well then maybe a record (row) should *never* be null.

It does make sense, however, to talk about the ROW's member values
being entirely NULL or entirely NOT NULL, and that's what the IS NULL
and IS NOT NULL tests tell you about.

Ah! So that's where the three-valued logic comes in to play with
records:

try=# SELECT ROW(1, NULL) IS NULL, ROW (1, 1) IS NULL, ROW(NULL,
NULL) IS NULL;
?column? | ?column? | ?column?
----------+----------+----------
f | f | t

I guess the spec authors figured they might as well make IS [NOT] NULL
do something useful when applied to a row rather than throwing an
error. I tend to agree.

Frankly, I find the state where a record with a NULL and a not-null
value being neither NULL nor not NULL bizarre.

I hope that provides some clarity.

It's useful to learn that `ROW(NULL, NULL)` is NULL, but I find the
whole thing totally bizarre. Is it me?

Best,

David

#16Richard Huxton
dev@archonet.com
In reply to: David E. Wheeler (#15)
Re: When is a record NULL?

David E. Wheeler wrote:

On Jul 23, 2009, at 9:34 PM, Brendan Jurd wrote:

I guess the spec authors figured they might as well make IS [NOT] NULL
do something useful when applied to a row rather than throwing an
error. I tend to agree.

Frankly, I find the state where a record with a NULL and a not-null
value being neither NULL nor not NULL bizarre.

I'm guessing the justification (and presumably this was worked out based
on the behaviour of one or more of the big DB providers and then
justified afterwards) is that the composite is "partially unknown". Of
course you should either introduce a new code or throw an error, but
four-valued logic isn't going to win you any friends.

If the argument *is* that because you know part of the overall value the
composite isn't null then I'd argue that ('abc' || null) isn't null
either. After all, the first three characters are perfectly well
established.

I hope that provides some clarity.

It's useful to learn that `ROW(NULL, NULL)` is NULL, but I find the
whole thing totally bizarre. Is it me?

Yes, just you. None of the rest of us have any problems with this at all :-)

--
Richard Huxton
Archonet Ltd

#17Brendan Jurd
direvus@gmail.com
In reply to: David E. Wheeler (#15)
Re: When is a record NULL?

2009/7/24 David E. Wheeler <david@kineticode.com>:

It's useful to learn that `ROW(NULL, NULL)` is NULL, but I find the whole
thing totally bizarre. Is it me?

*shrug* The IS [NOT] NULL tests mean something different when applied
to a ROW than they do when applied to a scalar value or an array.

"SELECT 1 IS NULL"
=> means "is this scalar set to the special value NULL?".

"SELECT ROW(1, 2) IS NULL"
=> means "are all the member values of this row set to the special
value NULL?"

So it is wrong to talk about ROW(NULL, NULL) being NULL. It doesn't
have the property of being NULL or not NULL, because it is a composite
value. "ROW(NULL, NULL) IS NULL" returns true, but that is not the
same as saying that it actually is NULL, because of the different
semantics above.

It's slightly different semantics from what you get with ordinary
scalar values, but that is cognisant with the fact that composites are
fundamentally different things from ordinary scalar values.

Cheers,
BJ

#18Michael Gould
mgould@intermodalsoftwaresolutions.net
In reply to: Richard Huxton (#16)
Re: When is a record NULL?

Does this also apply at the column level?

In Postgres is If column IS NOT NULL or If column IS NULL? Do all
columns in the record have to be NULL to have IF column IS NULL = true?

Best Regards
--
Michael Gould, Managing Partner
Intermodal Software Solutions, LLC
904.226.0978
904.592.5250 fax

#19Tom Lane
tgl@sss.pgh.pa.us
In reply to: Brendan Jurd (#17)
Re: When is a record NULL?

Brendan Jurd <direvus@gmail.com> writes:

So it is wrong to talk about ROW(NULL, NULL) being NULL. It doesn't
have the property of being NULL or not NULL, because it is a composite
value. "ROW(NULL, NULL) IS NULL" returns true, but that is not the
same as saying that it actually is NULL, because of the different
semantics above.

It's worse than that, because there actually is also such a thing as
the row value being NULL --- ie, there's no row structure at all.
At least internally, that's a completely different thing from having
a row all of whose fields are null.

SQL doesn't provide a test for this case that's separate from the test
involving null-ness of individual fields. Not much we can do about
it though. I'm not entirely sure that exposing the distinction would
be helpful anyway ...

regards, tom lane

#20Joshua Tolley
eggyknap@gmail.com
In reply to: David E. Wheeler (#11)
Re: When is a record NULL?

On Thu, Jul 23, 2009 at 06:46:25PM -0700, David E. Wheeler wrote:

Yes, but given that the standard says that `ROW(1, NULL)` is NULL, then I
would expect it to be NOT DISTINCT from `ROW(2, NULL)`.

Wait, didn't we decide upthread that the standard said ROW(1, NULL) isn't
NULL?

(From Tom):

This is per SQL standard. IS NULL is true if *all* the record's
fields are null; IS NOT NULL is true if *none* of them are.

--
Joshua Tolley / eggyknap
End Point Corporation
http://www.endpoint.com

#21Tom Lane
tgl@sss.pgh.pa.us
In reply to: Joshua Tolley (#20)
#22Jeff Davis
pgsql@j-davis.com
In reply to: Tom Lane (#19)
#23Sam Mason
sam@samason.me.uk
In reply to: Tom Lane (#19)
#24Kevin Grittner
Kevin.Grittner@wicourts.gov
In reply to: Sam Mason (#23)
#25Merlin Moncure
mmoncure@gmail.com
In reply to: David E. Wheeler (#15)
#26Merlin Moncure
mmoncure@gmail.com
In reply to: Merlin Moncure (#25)
#27Tom Lane
tgl@sss.pgh.pa.us
In reply to: Merlin Moncure (#25)
#28Tom Lane
tgl@sss.pgh.pa.us
In reply to: Jeff Davis (#22)
#29David E. Wheeler
david@kineticode.com
In reply to: Brendan Jurd (#17)
#30David E. Wheeler
david@kineticode.com
In reply to: Tom Lane (#28)
#31Jeff Davis
pgsql@j-davis.com
In reply to: Merlin Moncure (#25)
#32Jeff Davis
pgsql@j-davis.com
In reply to: Tom Lane (#28)
#33Merlin Moncure
mmoncure@gmail.com
In reply to: Tom Lane (#27)
#34Bruce Momjian
bruce@momjian.us
In reply to: Merlin Moncure (#33)
#35Merlin Moncure
mmoncure@gmail.com
In reply to: Bruce Momjian (#34)
#36David E. Wheeler
david@kineticode.com
In reply to: Jeff Davis (#22)
#37David E. Wheeler
david@kineticode.com
In reply to: Jeff Davis (#32)
#38Sam Mason
sam@samason.me.uk
In reply to: Kevin Grittner (#24)
#39David E. Wheeler
david@kineticode.com
In reply to: David E. Wheeler (#36)
#40Kevin Grittner
Kevin.Grittner@wicourts.gov
In reply to: David E. Wheeler (#39)
#41Jeff Davis
pgsql@j-davis.com
In reply to: David E. Wheeler (#39)
#42Kevin Grittner
Kevin.Grittner@wicourts.gov
In reply to: Sam Mason (#38)
#43David E. Wheeler
david@kineticode.com
In reply to: Jeff Davis (#41)
#44David E. Wheeler
david@kineticode.com
In reply to: Kevin Grittner (#42)
#45Sam Mason
sam@samason.me.uk
In reply to: Kevin Grittner (#42)
#46Kevin Grittner
Kevin.Grittner@wicourts.gov
In reply to: Sam Mason (#45)
#47Bruce Momjian
bruce@momjian.us
In reply to: Kevin Grittner (#46)
#48Sam Mason
sam@samason.me.uk
In reply to: Kevin Grittner (#46)
#49David E. Wheeler
david@kineticode.com
In reply to: David E. Wheeler (#44)
#50Eric Ridge
ebr@tcdi.com
In reply to: David E. Wheeler (#49)
#51Sam Mason
sam@samason.me.uk
In reply to: David E. Wheeler (#49)
#52Kevin Grittner
Kevin.Grittner@wicourts.gov
In reply to: Bruce Momjian (#47)
#53Kevin Grittner
Kevin.Grittner@wicourts.gov
In reply to: Sam Mason (#48)
#54Robert Haas
robertmhaas@gmail.com
In reply to: Kevin Grittner (#52)
#55David E. Wheeler
david@kineticode.com
In reply to: Eric Ridge (#50)
#56David E. Wheeler
david@kineticode.com
In reply to: David E. Wheeler (#55)