Обсуждение: (Debian Bug#41223) cascaded updates with refint insert bogus data

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

(Debian Bug#41223) cascaded updates with refint insert bogus data

От
Carlos Fonseca
Дата:
Package: postgresql-contrib
Version: 6.5-2

Dear PostgreSQL hackers,

I have sent this message to pgsql-general and so far received no reply. 
This bug seems to be 100% reproducible on Linux (i386 and sparc). If this
problem is specific to Debian, then it would help me to know that, too.

Cascaded updates tend to write old data on top of new, as the following
minimal example shows:

CREATE TABLE "tipos" ("tipo" text NOT NULL,"designacao" text DEFAULT '');
CREATE TABLE "duracoes" ("tipo" text DEFAULT '' NOT NULL,"duracao" timespan NOT NULL);

CREATE FUNCTION "check_primary_key" ( ) RETURNS opaque AS '/usr/lib/postgresql/modules/refint.so' LANGUAGE 'C';
CREATE FUNCTION "check_foreign_key" ( ) RETURNS opaque AS '/usr/lib/postgresql/modules/refint.so' LANGUAGE 'C';

COPY "tipos" FROM stdin;
P    Prática
T    Teórica
S    Seminário
TP    Teorico-prática
\.
COPY "duracoes" FROM stdin;
P    @ 3 hours
T    @ 1 hour
T    @ 1 hour 30 mins
TP    @ 1 hour 30 mins
TP    @ 2 hours
TP    @ 3 hours
\.
CREATE UNIQUE INDEX "tipos_pkey" on "tipos" using btree ( "tipo" "text_ops" );
CREATE UNIQUE INDEX "duracoes_pkey" on "duracoes" using btree ( "tipo" "text_ops", "duracao" "timespan_ops" );
CREATE TRIGGER "tipos_trigger_d" BEFORE DELETE ON "tipos" FOR EACH ROW EXECUTE PROCEDURE check_foreign_key ('1',
'cascade','tipo', '"duracoes"', 'tipo');
 
CREATE TRIGGER "tipos_trigger_u" AFTER UPDATE ON "tipos" FOR EACH ROW EXECUTE PROCEDURE check_foreign_key ('1',
'cascade','tipo', '"duracoes"', 'tipo');
 
CREATE TRIGGER "tipos_duracoes" BEFORE INSERT OR UPDATE ON "duracoes" FOR EACH ROW EXECUTE PROCEDURE check_primary_key
('tipo','"tipos"', 'tipo');
 

After setting up a database as described above, do the following:

=> update tipos set tipo='Tx' where tipo='T';
UPDATE 1
=> select * from tipos;
tipo|designacao     
----+---------------
P   |Prática        
S   |Seminário      
TP  |Teorico-prática
Tx  |Teórica        
(4 rows)

=> select * from duracoes;
tipo|duracao         
----+----------------
P   |@ 3 hours       
TP  |@ 1 hour 30 mins
TP  |@ 2 hours       
TP  |@ 3 hours       
Tx  |@ 1 hour        
Tx  |@ 1 hour 30 mins
(6 rows)

So far so good! Now:

=> update tipos set tipo='Px' where tipo='P';
UPDATE 1
=> select * from tipos;
tipo|designacao     
----+---------------
S   |Seminário      
TP  |Teorico-prática
Tx  |Teórica        
Px  |Prática        
(4 rows)

=> select * from duracoes;
tipo|duracao         
----+----------------
TP  |@ 1 hour 30 mins
TP  |@ 2 hours       
TP  |@ 3 hours       
Tx  |@ 1 hour        
Tx  |@ 1 hour 30 mins
Tx  |@ 3 hours       
^^ should be Px, NOT Tx
(6 rows)

This makes cascaded updates unusable, unfortunately... I can reproduce the
same behaviour on a PC, as well. I am running slink, so I compiled the
packages myself, from the debianized sources.

Thanks for any help!

Carlos Fonseca


-- System Information
Debian Release: 2.1
Kernel Version: Linux diana 2.2.7 #1 Sat May 8 19:57:23 WEST 1999 sparc unknown

Versions of the packages postgresql-contrib depends on:
ii  postgresql      6.5-2          Object-relational SQL database, descended fr






Re: [HACKERS] (Debian Bug#41223) cascaded updates with refint insert bogus data

От
Vadim Mikheev
Дата:
Carlos Fonseca wrote:
> 
> I have sent this message to pgsql-general and so far received no reply.
> This bug seems to be 100% reproducible on Linux (i386 and sparc). If this
> problem is specific to Debian, then it would help me to know that, too.
> 
> Cascaded updates tend to write old data on top of new, as the following
> minimal example shows:

Unfortunately, when I wrote refint.c ~ 2.5 years ago I used
DELETE for both cascade UPDATE and DELETE. I don't remember why.
Massimo Lambertini (massimo.lambertini@everex.it) changed
refint.c to performe UPDATE of foreign keys on UPDATE of primary
ones, but he did error: he uses 1st update new primary key value 
in UPDATE _foreign_table_ SET and so execution plan is prepared,
saved, used with this value. Paramater ($1...$n) should be used there.
I have no time to fix it, sorry. Ask him or learn PL/pgSQL and write
trigger youself.

Vadim