Thread: Problem with rule and null value

Problem with rule and null value

From
Marc Boucher
Date:
I'm using PostgreSQL 7.3.4.

I've set up a series of rules and triggers to complete an intermediate
table with similar informations from another table. This ensures better
performance over a solution with views.

Intermediate table:
   Table album_edit
   Field      Type     Length   Not Null    Default
   alb_id     int4        4       Yes
   ed_ref     varchar    30       Yes
   isbn       varchar    30       No
   flags      int2        2       No
   pls_id     int4        4       No

A set of rules is added to another table, "album".
The general principle of the relation between "album" and "album_edit", is
that each record of "album" is duplicated in "album_edit" (and these record
are uniquely identified in "album_edit" with the use of column "ed_ref").
So insert, update and delete on "album" are passed to "album_edit".

One of the update rules is this one:

CREATE OR REPLACE RULE albed_updalb3_rl AS
   ON UPDATE TO album WHERE new.pls_id != old.pls_id
  DO
   UPDATE album_edit SET pls_id=new.pls_id WHERE alb_id=new.id;

It works until new.pls_id or old.pls_id is null. The rule is still called
(based on my test), but the "DO" query is not executed correctly. The
values in "album_edit" are not updated.

To find the source of the problem I've modified the rule:

CREATE OR REPLACE RULE albed_updalb3_rl AS
   ON UPDATE TO album WHERE new.pls_id != old.pls_id
  DO
   select old.pls_id, new.pls_id;


Is this a bug or an intended behavior ?


Here is a log with some tests.

----------
bd=# CREATE OR REPLACE RULE albed_updalb3_rl AS ON UPDATE TO album WHERE
new.pls_id != old.pls_id DO select old.pls_id, new.pls_id;
CREATE RULE
bd=# update album set pls_id='666' where id='8838';
                                                  pls_id | pls_id
--------+--------
    100 |    666
(1 row)

bd=# update album set pls_id=null where id='8838';
 pls_id | pls_id
--------+--------
(0 rows)

bd=# update album set pls_id='666' where id='8838';
 pls_id | pls_id
--------+--------
(0 rows)

bd=# update album set pls_id='111' where id='8838';
 pls_id | pls_id
--------+--------
    666 |    111
(1 row)

bd=# update album set pls_id='0' where id='8838';
 pls_id | pls_id
--------+--------
    111 |      0
(1 row)

bd=# update album set pls_id='111' where id='8838';
 pls_id | pls_id
--------+--------
      0 |    111
(1 row)

bd=# update album set pls_id=null where id='8838';
 pls_id | pls_id
--------+--------
(0 rows)

Re: Problem with rule and null value

From
Harald Armin Massa
Date:
>    ON UPDATE TO album WHERE new.pls_id != old.pls_id

> It works until new.pls_id or old.pls_id is null. The rule is still called
> (based on my test), but the "DO" query is not executed correctly. The
> values in "album_edit" are not updated.


To compare "NULL" to something is allways a bad idea. The behaviour in
Postgres is exactly as documented and specified within the
SQL-standard.

BUT... that is quite different from what you would expect.

To test on "NULL" values within SQL only "is null" is helpfull.

I would strongly recommend to you to read the appropriate chapters
about Null-Values. It seems strange at first but managable.

Harald