Thread: Bug with rules in 7.0.3?

Bug with rules in 7.0.3?

From
Tod McQuillin
Date:
Hi there... I've spotted something weird in 7.0.3 with rules.  By now I've
realised I probably need to use a trigger to do what I have in mind, but
even so, there no way I can explain the behaviour I am getting with a
rule.

Given this SQL script:

CREATE TABLE menu (menu_id        SERIAL PRIMARY KEY,name        TEXT,price        integer
);

INSERT INTO menu(name, price) VALUES ('Beer', 5);
INSERT INTO menu(name, price) VALUES ('Vodka', 10);
INSERT INTO menu(name, price) VALUES ('Scotch', 8);

CREATE TABLE orders (order_id    SERIAL PRIMARY KEY,menu_id        INTEGER REFERENCES menu,price        INTEGER NOT
NULLDEFAULT -1
 
);

CREATE RULE fix_order_price AS
ON INSERT TO orders
DOUPDATE ordersSET price = M.priceFROM menu MWHERE M.menu_id = new.menu_idAND new.price = -1;

INSERT INTO orders (menu_id) VALUES (2);

SELECT * FROM orders;

Here's what happens:

% createdb buggy
CREATE DATABASE
% psql buggy < ~/pg.bug
NOTICE:  CREATE TABLE will create implicit sequence 'menu_menu_id_seq' for SERIAL column 'menu.menu_id'
NOTICE:  CREATE TABLE/PRIMARY KEY will create implicit index 'menu_pkey' for table 'menu'
CREATE
INSERT 259680 1
INSERT 259681 1
INSERT 259682 1
NOTICE:  CREATE TABLE will create implicit sequence 'orders_order_id_seq' for SERIAL column 'orders.order_id'
NOTICE:  CREATE TABLE/PRIMARY KEY will create implicit index 'orders_pkey' for table 'orders'
NOTICE:  CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s)
CREATE
CREATE 259722 1
INSERT 0 3order_id | menu_id | price
----------+---------+-------       1 |       2 |    -1       2 |       2 |    -1       3 |       2 |    -1
(3 rows)

How the heck can one insert and update generate three rows?
-- 
Tod McQuillin





Re: Bug with rules in 7.0.3?

From
Tom Lane
Date:
Tod McQuillin <devin@spamcop.net> writes:
> How the heck can one insert and update generate three rows?

Looks like a rule rewriter bug to me.  It seems to be fixed in 7.1;
I get

regression=# SELECT * FROM orders;order_id | menu_id | price
----------+---------+-------       1 |       2 |    -1
(1 row)

which is the correct result given that rules are executed before the
original query.  (Which is why you need a trigger for this...)
        regards, tom lane


Re: Bug with rules in 7.0.3?

From
Tod McQuillin
Date:
On Sat, 3 Feb 2001, Tom Lane wrote:

> I get
>
> regression=# SELECT * FROM orders;
>  order_id | menu_id | price
> ----------+---------+-------
>         1 |       2 |    -1
> (1 row)
>
> which is the correct result given that rules are executed before the
> original query.  (Which is why you need a trigger for this...)

OK.

I think that Bruce's book is inaccurate then.  In section D.19 (p. 299),
also reproduced on the web at
http://www.postgresql.org/docs/aw_pgsql_book/node490.html, this example is
given:

All new employees must make 5,000 or less:

CREATE RULE example_5 AS
ON INSERT TO emp
WHERE new.salary > 5000 DO
UPDATE emp SET salary = 5000
WHERE emp.oid = new.oid;
-- 
Tod McQuillin




Re: Bug with rules in 7.0.3?

From
Bruce Momjian
Date:
> On Sat, 3 Feb 2001, Tom Lane wrote:
> 
> > I get
> >
> > regression=# SELECT * FROM orders;
> >  order_id | menu_id | price
> > ----------+---------+-------
> >         1 |       2 |    -1
> > (1 row)
> >
> > which is the correct result given that rules are executed before the
> > original query.  (Which is why you need a trigger for this...)
> 
> OK.
> 
> I think that Bruce's book is inaccurate then.  In section D.19 (p. 299),
> also reproduced on the web at
> http://www.postgresql.org/docs/aw_pgsql_book/node490.html, this example is
> given:
> 
> All new employees must make 5,000 or less:
> 
> CREATE RULE example_5 AS
> ON INSERT TO emp
> WHERE new.salary > 5000 DO
> UPDATE emp SET salary = 5000
> WHERE emp.oid = new.oid;

I checked the current create_rule.sgml file, and this example query is
no longer in the file.  Not sure why it was removed, but it will not
appear in 7.1.

--  Bruce Momjian                        |  http://candle.pha.pa.us pgman@candle.pha.pa.us               |  (610)
853-3000+  If your life is a hard drive,     |  830 Blythe Avenue +  Christ can be your backup.        |  Drexel Hill,
Pennsylvania19026