Forum OpenACS Development: Response to Weird error invoking a plpgsql function (content_revision__delete)
Posted by
Jowell Sabino
on 06/19/01 09:38 PM
How timely. I am trying to construct a regression test of an acs service (I'm helping out Rafael port acs-events). I can trigger the data change violation if, as Dan pointed out, in one transaction I insert and delete a row in a table whose primary key is a foreign key of another table. This happens even if the other table is not involved at all. Here's a simplified script that will reproduce the data change violation.
create table ut_time_intervals (
interval_id integer
primary key,
start_date timestamp,
end_date timestamp,
constraint ut_time_interval_date_order_ck
check(start_date <= end_date)
);
-- Need a source of primary keys
create sequence ut_timespan_seq;
-- Make a table that references the primary key of above
-- If this table is not created, no data-change violation is
-- triggered. Note that this table is not used by the functions below.
create table ut_timespans (
timespan_id integer not null,
interval_id integer
references ut_time_intervals on delete cascade
);
create function ut_time_interval__new (timestamp,timestamp)
returns integer as '
declare
new__start_date alias for $1; -- default null,
new__end_date alias for $2; -- default null
v_interval_id ut_time_intervals.interval_id%TYPE;
begin
select nextval(''ut_timespan_seq'') into v_interval_id;
insert into ut_time_intervals
(interval_id, start_date, end_date)
values
(v_interval_id, new__start_date, new__end_date);
return v_interval_id;
end;' language 'plpgsql';
-- end new;
create function ut_time_interval__delete (
integer -- in time_intervals.interval_id%TYPE
)
returns integer as '
declare
delete__interval_id alias for $1;
begin
delete from ut_time_intervals
where interval_id = delete__interval_id;
return 0;
end;' language 'plpgsql';
-- end delete;
create function simple_regression()
returns integer as '
declare
date1 timestamp := ''2001-01-01'';
date2 timestamp := ''2001-01-02'';
v_id time_intervals.interval_id%TYPE;
begin
-- Do insertion into the table and deletion in same
-- transaction to trigger a data change violation
-- Create an entry
v_id := ut_time_interval__new(date1,date2);
-- Other regression tests presumably done here.
-- Delete the entry. Will trigger a data change violation
-- if a table exists (i.e., ut_timespans) that references
-- the primary key
PERFORM ut_time_interval__delete(v_id);
return 0;
end;' language 'plpgsql';
select (case when simple_regression() = 0
then
'Regression test successful'
end) as regression_result;
-- Clean up
drop table ut_timespans;
drop table ut_time_intervals;
drop sequence ut_timespan_seq;
drop function ut_time_interval__new(timestamp,timestamp);
drop function ut_time_interval__delete(integer);
drop function simple_regression();
I guess the point is that the "bug" can also affect regression testing, not only audit tables. Dan, is there a regression toolkit similar to utplsql in Oracle? Since a service does not have any "interface", the only way to test it is to actually construct a test. BTW, I am using PG 7.1.1.