Обсуждение: BUG #5053: domain constraints still leak

Поиск
Список
Период
Сортировка

BUG #5053: domain constraints still leak

От
"Andrew Gierth"
Дата:
The following bug has been logged online:

Bug reference:      5053
Logged by:          Andrew Gierth
Email address:      andrew@tao11.riddles.org.uk
PostgreSQL version: 8.5devel
Operating system:   FreeBSD
Description:        domain constraints still leak
Details:

Domain NOT NULL constraints (and probably other constraints too) aren't
being enforced in some code paths. e.g.

\pset null '<NULL>'
create domain tstdom as integer not null;
create table test (a tstdom);
insert into test values (null);
ERROR:  domain tstdom does not allow null values

all correct up to now, but:

insert into test select (r).* from (select null::test as r) s;
INSERT 0 1

oops.

select * from test;
   a
--------
 <NULL>
(1 row)

Re: BUG #5053: domain constraints still leak

От
Tom Lane
Дата:
"Andrew Gierth" <andrew@tao11.riddles.org.uk> writes:
> Domain NOT NULL constraints (and probably other constraints too) aren't
> being enforced in some code paths. e.g.

The example you give seems to tie really closely into the debate about
whether a composite null is identically the same thing as ROW(NULL,NULL)
or not.  In short, we have

regression=# create domain tstdom as integer not null;
CREATE DOMAIN
regression=# create table test (a tstdom);
CREATE TABLE
regression=# select null::test;
 test
------

(1 row)

regression=# select row(null)::test;
ERROR:  domain tstdom does not allow null values

It's possible to argue that in the first form, there isn't any tstdom
column there at all, so no constraint violation.  So I guess this is
a case that we need to think about while debating the what-is-a-null
question.

            regards, tom lane

PS: of course, domain not null constraints are horribly broken and
impossible to make behave sanely anyhow ...

Re: BUG #5053: domain constraints still leak

От
Robert Haas
Дата:
On Sun, Sep 13, 2009 at 10:28 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
> "Andrew Gierth" <andrew@tao11.riddles.org.uk> writes:
>> Domain NOT NULL constraints (and probably other constraints too) aren't
>> being enforced in some code paths. e.g.
>
> The example you give seems to tie really closely into the debate about
> whether a composite null is identically the same thing as ROW(NULL,NULL)
> or not. =A0In short, we have

It seems like regardless of this discussion you oughtn't to be able to
store a NULL into that table column.  But maybe I'm just confused.

...Robert

Re: BUG #5053: domain constraints still leak

От
Tom Lane
Дата:
Robert Haas <robertmhaas@gmail.com> writes:
> It seems like regardless of this discussion you oughtn't to be able to
> store a NULL into that table column.  But maybe I'm just confused.

The system is relying on the not-unreasonable assumption that if it
extracts a column of type X from someplace, what it has is a valid value
of type X.  Depending on what we decide about the whole composite-null
mess, maybe we will be forced to abandon that assumption ... but I'm
sure not going to do so until my back is to the wall.

            regards, tom lane

Re: BUG #5053: domain constraints still leak

От
Sam Mason
Дата:
On Mon, Sep 14, 2009 at 10:22:34AM -0400, Tom Lane wrote:
> Robert Haas <robertmhaas@gmail.com> writes:
> > It seems like regardless of this discussion you oughtn't to be able to
> > store a NULL into that table column.  But maybe I'm just confused.
>
> The system is relying on the not-unreasonable assumption that if it
> extracts a column of type X from someplace, what it has is a valid value
> of type X.

Yup; the deeper problem seems to be that the table was created as:

  create table test (a tstdom);

and not as:

  create table test (a tstdom not null);

which is how you seem to be treating it.

> Depending on what we decide about the whole composite-null
> mess, maybe we will be forced to abandon that assumption ... but I'm
> sure not going to do so until my back is to the wall.

There seems to be a little space yet!


This whole issue seems only distantly related to the treatment of null
rows to me.  I think PG has got its semantics confused along the way
somewhere and things need tweaking.  The only way I can get it all to
work nicely in my head is if ROW(NULL) evaluates to a NULL value (and
not a row containing a NULL value, as it does at the moment) and the
NULL/NOT NULL constraint on the CREATE DOMAIN is used somehow for the
nullness constraint of any columns using this domain.  It's the second
part that seems to be more critical, but there are various ways of
interpreting the meaning.

I'm tempted to say that the nullness specified in the domain puts a
bound on the amount of nullness available--i.e. it would be impossible
to create a nullable column from a domain that specified NOT NULL.  The
reason it's only a "limit" is that it seems useful to be able to say
that a normally nullable domain can't be null for this column in this
table.  Not sure if this is what people want though.

You then get into fun cases like:

  create domain tstdom as integer;
  create domain tstdom2 as tstdom;

--
  Sam  http://samason.me.uk/

Re: BUG #5053: domain constraints still leak

От
Robert Haas
Дата:
On Mon, Sep 14, 2009 at 10:22 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
> Robert Haas <robertmhaas@gmail.com> writes:
>> It seems like regardless of this discussion you oughtn't to be able to
>> store a NULL into that table column. =A0But maybe I'm just confused.
>
> The system is relying on the not-unreasonable assumption that if it
> extracts a column of type X from someplace, what it has is a valid value
> of type X. =A0Depending on what we decide about the whole composite-null
> mess, maybe we will be forced to abandon that assumption ... but I'm
> sure not going to do so until my back is to the wall.

I haven't read the code in this area, but for what it's worth, I guess
I lean toward the view that treating a row of NULLs as being the same
thing as an undecorated NULL does not make very much sense.  If I have
a table row which contains (1, NULL, NULL) and I update the first
column to be NULL, I feel like I now have (NULL, NULL, NULL), not just
NULL.  Every other programming language I'm aware of makes this
distinction - for good reasons - and I don't really see any reason why
SQL should do anything different.

Under that view, null::test is not itself a test, but denotes the
absence of one.  Trying to store this value in a table can either fail
outright (on the theory that you can't store the absence of something
in a table), or else we can - as a special case - treat assignment
from null to an actual object as a request to assign null to each
column (which will fail if there exists a column into which a NULL of
the associated column type can't be stored).

...Robert

Re: BUG #5053: domain constraints still leak

От
Sam Mason
Дата:
On Mon, Sep 14, 2009 at 11:16:23AM -0400, Robert Haas wrote:
> I haven't read the code in this area, but for what it's worth, I guess
> I lean toward the view that treating a row of NULLs as being the same
> thing as an undecorated NULL does not make very much sense.

I agree; when compared to most languages it doesn't.  When compared
to the semantics of the other operators in SQL it gets better.  I
personally think PG should strive to be internally consistent rather
than consistency with other (non-SQL based) languages.

> If I have
> a table row which contains (1, NULL, NULL) and I update the first
> column to be NULL, I feel like I now have (NULL, NULL, NULL), not just
> NULL.  Every other programming language I'm aware of makes this
> distinction - for good reasons - and I don't really see any reason why
> SQL should do anything different.

I'm not aware of any other language that does the automatic "lifting"
(to borrow nomenclature from Haskell) that SQL does, allowing NULL
appear in *every* type.  Java, for example, has null references,
but these are very different creatures from nulls in databases--the
programmer has to explicitly deal with them all the time and also they
only apply to references.  Taken another way, each object in a normal
imperative language has its own identity, but in a database two rows
that "look" the same are the same.  Thirdly, IS NULL is defined to look
"inside" composite values to see if they're "really" null.  Its these
differences in semantics that seem to make it all OK.

> Under that view, null::test is not itself a test, but denotes the
> absence of one.

OK, but how can you distinguish NULL from ROW(NULL,NULL)?

  SELECT v IS NULL, v.a, v.b
  FROM (SELECT NULL, NULL) v(a,b);

Would appear to return the same thing if ROW(NULL,NULL) evaluated to
NULL or not.  The only time it would show up is when you're trying to
save the value into a table and I think this would tend to do the right
thing more often.  For example:

  INSERT INTO t (id,rv)
    SELECT f.id, b
    FROM foo f
      LEFT JOIN bar b ON (f.id = b.id);

Would fail if any bar's didn't exist, whereas the current behavior is
to insert a row with rv containing all null values.  You can't test for
this case because IS NULL would return the "wrong" thing as it looks
inside composites.

--
  Sam  http://samason.me.uk/

Re: BUG #5053: domain constraints still leak

От
"Kevin Grittner"
Дата:
Sam Mason <sam@samason.me.uk> wrote:

> the deeper problem seems to be that the table was created as:
>
>   create table test (a tstdom);
>
> and not as:
>
>   create table test (a tstdom not null);

Given that tstdom is declared as NOT NULL, is this difference
considered a *feature* or is it an implementation quirk?

-Kevin

Re: BUG #5053: domain constraints still leak

От
Sam Mason
Дата:
On Mon, Sep 14, 2009 at 10:54:07AM -0500, Kevin Grittner wrote:
> Sam Mason <sam@samason.me.uk> wrote:
> > the deeper problem seems to be that the table was created as:
> >
> >   create table test (a tstdom);
> >
> > and not as:
> >
> >   create table test (a tstdom not null);
>
> Given that tstdom is declared as NOT NULL, is this difference
> considered a *feature* or is it an implementation quirk?

That's why I pointed it out!

Based on my reading of the SQL spec (and reading about Codd's
descriptions of domains) I'd say it was a bug/implementation quirk.

--
  Sam  http://samason.me.uk/

Re: BUG #5053: domain constraints still leak

От
Bruce Momjian
Дата:
Sam Mason wrote:
> On Mon, Sep 14, 2009 at 10:54:07AM -0500, Kevin Grittner wrote:
> > Sam Mason <sam@samason.me.uk> wrote:
> > > the deeper problem seems to be that the table was created as:
> > >
> > >   create table test (a tstdom);
> > >
> > > and not as:
> > >
> > >   create table test (a tstdom not null);
> >
> > Given that tstdom is declared as NOT NULL, is this difference
> > considered a *feature* or is it an implementation quirk?
>
> That's why I pointed it out!
>
> Based on my reading of the SQL spec (and reading about Codd's
> descriptions of domains) I'd say it was a bug/implementation quirk.

Do we need a TODO for this item?  Also, I see this odd behavior even
without domains:

    test=> CREATE TYPE xx AS (x INT);
    CREATE TYPE
    test=> CREATE TABLE test4(col1 xx NOT NULL);
    CREATE TABLE
    test=> INSERT INTO test4 VALUES (ROW(NULL));
    INSERT 0 1
    test=> SELECT * FROM test4 WHERE col1 IS NULL;
     col1
    ------
     ()
    (1 row)

Here I am illustrating that NOT NULL and IS NULL have different ideas of
what a NULL is?  That seems odd too.

--
  Bruce Momjian  <bruce@momjian.us>        http://momjian.us
  EnterpriseDB                             http://enterprisedb.com

  + If your life is a hard drive, Christ can be your backup. +

Re: BUG #5053: domain constraints still leak

От
Robert Haas
Дата:
On Mon, Sep 21, 2009 at 12:31 PM, Bruce Momjian <bruce@momjian.us> wrote:
> Sam Mason wrote:
>> On Mon, Sep 14, 2009 at 10:54:07AM -0500, Kevin Grittner wrote:
>> > Sam Mason <sam@samason.me.uk> wrote:
>> > > the deeper problem seems to be that the table was created as:
>> > >
>> > > =A0 create table test (a tstdom);
>> > >
>> > > and not as:
>> > >
>> > > =A0 create table test (a tstdom not null);
>> >
>> > Given that tstdom is declared as NOT NULL, is this difference
>> > considered a *feature* or is it an implementation quirk?
>>
>> That's why I pointed it out!
>>
>> Based on my reading of the SQL spec (and reading about Codd's
>> descriptions of domains) I'd say it was a bug/implementation quirk.
>
> Do we need a TODO for this item? =A0Also, I see this odd behavior even
> without domains:
>
> =A0 =A0 =A0 =A0test=3D> CREATE TYPE xx AS (x INT);
> =A0 =A0 =A0 =A0CREATE TYPE
> =A0 =A0 =A0 =A0test=3D> CREATE TABLE test4(col1 xx NOT NULL);
> =A0 =A0 =A0 =A0CREATE TABLE
> =A0 =A0 =A0 =A0test=3D> INSERT INTO test4 VALUES (ROW(NULL));
> =A0 =A0 =A0 =A0INSERT 0 1
> =A0 =A0 =A0 =A0test=3D> SELECT * FROM test4 WHERE col1 IS NULL;
> =A0 =A0 =A0 =A0 col1
> =A0 =A0 =A0 =A0------
> =A0 =A0 =A0 =A0 ()
> =A0 =A0 =A0 =A0(1 row)
>
> Here I am illustrating that NOT NULL and IS NULL have different ideas of
> what a NULL is? =A0That seems odd too.

I think what you're demonstrating is that there is a difference
between a NULL, and a row consisting of a single NULL.  We've had some
dispute (on this thread) about whether that ought to be the case, but
this is certainly a lot less weird and more debatable than the domain
example, at least IMO.

...Robert