Обсуждение: Bug with rules in 7.0.3?
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
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
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
> 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