On 3/25/06 6:24 PM, John Siracusa wrote:
> I expect the following two pieces of code to give the same result.  One is
> SQL, fed directly to Postgres using the psql command-line tool, and the
> other is Perl code using DBI.  Before I file this as a bug in DBD::Pg, I
> want to make sure it's not a "feature" of DBI or something.

FYI, I filed this as a bug on DBD::Pg and it was just fixed in the newly
released version 1.48.  I have confirmed the fix.  Thanks to those who
helped narrow this down earlier.

-John

(Original message continues below.)

> In the code, note that I'm intentionally sending statements that I know will
> fail.  This seems to be necessary to reproduce the bug.
> 
> First, the SQL:
> 
>     DROP TABLE t1;
>     DROP TABLE t2;
> 
>     CREATE TABLE t2
>     (
>       id INT PRIMARY KEY
>     ); 
> 
>     CREATE TABLE t1
>     (
>       id     INT PRIMARY KEY,
>       t2_id  INT REFERENCES t2 (id) INITIALLY DEFERRED
>     );
> 
>     BEGIN;
>     INSERT INTO t2 (id) VALUES (1);
>     INSERT INTO t1 (id, t2_id) VALUES (1, 1);
>     COMMIT;
> 
>     BEGIN;
>     INSERT INTO t1 (id, t2_id) VALUES (2, 1);
>     INSERT INTO t1 (id, t2_id) VALUES (3, 2);
>     COMMIT;
> 
>     BEGIN;
>     INSERT INTO t1 (id, t2_id) VALUES (2, 1);
>     ROLLBACK;
> 
>     SELECT * FROM t1;
> 
> The final SELECT should find only one row:
> 
>      id | t2_id 
>     ----+-------
>       1 |     1
> 
> It works as expected.  Now the Perl code:
> 
>     use DBI;
>     
>     my $dbh = DBI->connect('dbi:Pg:dbname=test', 'postgres', '...',
>                            { PrintError => 1, RaiseError => 0 });
>     
>     $dbh->do('CREATE TABLE t2
>     (
>       id INT PRIMARY KEY
>     )');
>     
>     $dbh->do('CREATE TABLE t1
>     (
>       id     INT PRIMARY KEY,
>       t2_id  INT REFERENCES t2 (id) INITIALLY DEFERRED
>     )');
>     
>     $dbh->do('DELETE FROM t1');
>     $dbh->do('DELETE FROM t2');
>     
>     $dbh->begin_work;
>     
>     $dbh->do('INSERT INTO t2 (id) VALUES (1)');
>     $dbh->do('INSERT INTO t1 (id, t2_id) VALUES (1, 1)');
>     
>     $dbh->commit;
>     
>     $dbh->begin_work;
>     
>     $dbh->do('INSERT INTO t1 (id, t2_id) VALUES (2, 1)');
>     $dbh->do('INSERT INTO t1 (id, t2_id) VALUES (3, 2)');
>     
>     $dbh->commit;
>     
>     $dbh->begin_work;
>     
>     $dbh->do('INSERT INTO t1 (id, t2_id) VALUES (2, 1)');
>     
>     $dbh->rollback; # XXX: This doesn't seem to work
>     
>     my $sth = $dbh->prepare('SELECT * FROM t1');
>     $sth->execute;
>     
>     while(my $row = $sth->fetchrow_hashref)
>     {
>       print "$row->{'id'}, $row->{'t2_id'}\n";
>     }
>     
>     $dbh->do('DROP TABLE t1');
>     $dbh->do('DROP TABLE t2');
>     
>     $dbh->disconnect;
> 
> Unfortunately, it prints this:
> 
>     1, 1
>     2, 1
> 
> Basically, the call to rollback() appears to fail.  The row inserted is not
> rolled back but remains visible.  In fact, if you remove the DROP TABLE
> statements from the end of the Perl script, row id 2 in the t1 table stays
> in the database after the script exits.
> 
> So, is this correct behavior or a bug?
> 
> -John
> 
> 
> 


Reply via email to