Author: turnstep
Date: Mon Mar 23 17:59:45 2009
New Revision: 12626

Modified:
   DBD-Pg/trunk/Changes
   DBD-Pg/trunk/Pg.pm
   DBD-Pg/trunk/Pg.xs
   DBD-Pg/trunk/dbdimp.c
   DBD-Pg/trunk/t/03dbmethod.t

Log:
Change large object interface from old, non-DBI friendly lo_ to pg_lo_, per 
suggestion 
on ticket 44467.
Add tests for AutoCommit/lo_import interaction, plus tests for old-style lo_ 
interface.


Modified: DBD-Pg/trunk/Changes
==============================================================================
--- DBD-Pg/trunk/Changes        (original)
+++ DBD-Pg/trunk/Changes        Mon Mar 23 17:59:45 2009
@@ -1,9 +1,12 @@
 ('GSM' is Greg Sabino Mullane, [email protected])
 
-2.11.9
+2.12.0
 
+  - Change large object interface from lo_* to pg_lo_* and make them 
accessible 
+    via direct $dbh calls (e.g. $dbh->pg_lo_import instead of 
$dbh->func(..,'pg_lo_import').
+    The use of $dbh->func(... 'lo_*') is deprecated. [GSM] (CPAN bug #44467)
   - Throw an exception for large_object functions called when AutoCommit is 
on, 
-    but allow lo_import and lo_export to work. Reported by Kynn Jones.
+    but allow pg_lo_import and pg_lo_export to work. Reported by Kynn Jones.
     [GSM] (CPAN bug #44461)
   - Fix a memory leak when parsing returned arrays. Reported by Bálint 
Szilakszi.
     [GSM] (CPAN bug #44225)

Modified: DBD-Pg/trunk/Pg.pm
==============================================================================
--- DBD-Pg/trunk/Pg.pm  (original)
+++ DBD-Pg/trunk/Pg.pm  Mon Mar 23 17:59:45 2009
@@ -143,6 +143,17 @@
                DBD::Pg::st->install_method('pg_result');
                DBD::Pg::st->install_method('pg_ready');
 
+               DBD::Pg::db->install_method('pg_lo_creat');
+               DBD::Pg::db->install_method('pg_lo_open');
+               DBD::Pg::db->install_method('pg_lo_write');
+               DBD::Pg::db->install_method('pg_lo_read');
+               DBD::Pg::db->install_method('pg_lo_lseek');
+               DBD::Pg::db->install_method('pg_lo_tell');
+               DBD::Pg::db->install_method('pg_lo_close');
+               DBD::Pg::db->install_method('pg_lo_unlink');
+               DBD::Pg::db->install_method('pg_lo_import');
+               DBD::Pg::db->install_method('pg_lo_export');
+
                return $drh;
 
        } ## end of driver
@@ -2033,20 +2044,20 @@
   PRIMARY_KEY flag is_primary_key
   REMARKS     attribute description
 
-=item lo_creat
+=item pg_lo_creat
 
-  $lobjId = $dbh->func($mode, 'lo_creat');
+  $lobjId = $dbh->pg_lo_creat($mode);
 
 Creates a new large object and returns the object-id. C<$mode> is a bitmask
 describing read and write access to the new object. This setting is ignored
 since Postgres version 8.1. For backwards compatibility, however, you should 
-set a valid mode anyway (see L</lo_open> for a list of valid modes).
+set a valid mode anyway (see L</pg_lo_open> for a list of valid modes).
 
 Upon failure it returns C<undef>. This function cannot be used if AutoCommit 
is enabled.
 
 =item lo_open
 
-  $lobj_fd = $dbh->func($lobjId, $mode, 'lo_open');
+  $lobj_fd = $dbh->pg_lo_open($lobjId, $mode);
 
 Opens an existing large object and returns an object-descriptor for use in
 subsequent C<lo_*> calls. C<$mode> is a bitmask describing read and write
@@ -2069,21 +2080,21 @@
 
 =item lo_write
 
-  $nbytes = $dbh->func($lobj_fd, $buffer, $len, 'lo_write');
+  $nbytes = $dbh->pg_lo_write($lobj_fd, $buffer, $len);
 
 Writes C<$len> bytes of c<$buffer> into the large object C<$lobj_fd>. Returns 
the number
 of bytes written and C<undef> upon failure. This function cannot be used if 
AutoCommit is enabled.
 
 =item lo_read
 
-  $nbytes = $dbh->func($lobj_fd, $buffer, $len, 'lo_read');
+  $nbytes = $dbh->pg_lo_read($lobj_fd, $buffer, $len);
 
 Reads C<$len> bytes into c<$buffer> from large object C<$lobj_fd>. Returns the 
number of
 bytes read and C<undef> upon failure. This function cannot be used if 
AutoCommit is enabled.
 
 =item lo_lseek
 
-  $loc = $dbh->func($lobj_fd, $offset, $whence, 'lo_lseek');
+  $loc = $dbh->pg_lo_lseek($lobj_fd, $offset, $whence);
 
 Changes the current read or write location on the large object
 C<$obj_id>. Currently C<$whence> can only be 0 (which is L_SET). Returns the 
current
@@ -2091,35 +2102,36 @@
 
 =item lo_tell
 
-  $loc = $dbh->func($lobj_fd, 'lo_tell');
+  $loc = $dbh->pg_lo_tell($lobj_fd);
 
 Returns the current read or write location on the large object C<$lobj_fd> and 
C<undef> upon failure.
 This function cannot be used if AutoCommit is enabled.
 
 =item lo_close
 
-  $lobj_fd = $dbh->func($lobj_fd, 'lo_close');
+  $lobj_fd = $dbh->pg_lo_close($lobj_fd);
 
 Closes an existing large object. Returns true upon success and false upon 
failure.
 This function cannot be used if AutoCommit is enabled.
 
 =item lo_unlink
 
-  $ret = $dbh->func($lobjId, 'lo_unlink');
+  $ret = $dbh->pg_lo_unlink($lobjId);
 
 Deletes an existing large object. Returns true upon success and false upon 
failure.
 This function cannot be used if AutoCommit is enabled.
 
 =item lo_import
 
-  $lobjId = $dbh->func($filename, 'lo_import');
+
+  $lobjId = $dbh->pg_lo_import($filename);
 
 Imports a Unix file as a large object and returns the object id of the new
 object or C<undef> upon failure.
 
 =item lo_export
 
-  $ret = $dbh->func($lobjId, $filename, 'lo_export');
+  $ret = $dbh->pg_lo_export($lobjId, $filename);
 
 Exports a large object into a Unix file. Returns false upon failure, true 
otherwise.
 

Modified: DBD-Pg/trunk/Pg.xs
==============================================================================
--- DBD-Pg/trunk/Pg.xs  (original)
+++ DBD-Pg/trunk/Pg.xs  Mon Mar 23 17:59:45 2009
@@ -384,18 +384,16 @@
                        warn("release ineffective with AutoCommit enabled");
                ST(0) = (pg_db_release(dbh, imp_dbh, name)!=0) ? &sv_yes : 
&sv_no;
 
-
 void
-lo_creat(dbh, mode)
+pg_lo_creat(dbh, mode)
        SV * dbh
        int mode
        CODE:
                const unsigned int ret = pg_db_lo_creat(dbh, mode);
                ST(0) = (ret > 0) ? sv_2mortal(newSVuv(ret)) : &sv_undef;
 
-
 void
-lo_open(dbh, lobjId, mode)
+pg_lo_open(dbh, lobjId, mode)
        SV * dbh
        unsigned int lobjId
        int mode
@@ -405,15 +403,18 @@
 
 
 void
-lo_close(dbh, fd)
+pg_lo_write(dbh, fd, buf, len)
        SV * dbh
        int fd
+       char * buf
+       size_t len
        CODE:
-               ST(0) = (pg_db_lo_close(dbh, fd) >= 0) ? &sv_yes : &sv_no;
+               const int ret = pg_db_lo_write(dbh, fd, buf, len);
+               ST(0) = (ret >= 0) ? sv_2mortal(newSViv(ret)) : &sv_undef;
 
 
 void
-lo_read(dbh, fd, buf, len)
+pg_lo_read(dbh, fd, buf, len)
        SV * dbh
        int fd
        char * buf
@@ -435,6 +436,78 @@
 
 
 void
+pg_lo_lseek(dbh, fd, offset, whence)
+       SV * dbh
+       int fd
+       int offset
+       int whence
+       CODE:
+               const int ret = pg_db_lo_lseek(dbh, fd, offset, whence);
+               ST(0) = (ret >= 0) ? sv_2mortal(newSViv(ret)) : &sv_undef;
+
+
+void
+pg_lo_tell(dbh, fd)
+       SV * dbh
+       int fd
+       CODE:
+               const int ret = pg_db_lo_tell(dbh, fd);
+               ST(0) = (ret >= 0) ? sv_2mortal(newSViv(ret)) : &sv_undef;
+
+
+void
+pg_lo_close(dbh, fd)
+       SV * dbh
+       int fd
+       CODE:
+               ST(0) = (pg_db_lo_close(dbh, fd) >= 0) ? &sv_yes : &sv_no;
+
+
+void
+pg_lo_unlink(dbh, lobjId)
+       SV * dbh
+       unsigned int lobjId
+       CODE:
+               ST(0) = (pg_db_lo_unlink(dbh, lobjId) >= 1) ? &sv_yes : &sv_no;
+
+
+void
+pg_lo_import(dbh, filename)
+       SV * dbh
+       char * filename
+       CODE:
+               const unsigned int ret = pg_db_lo_import(dbh, filename);
+               ST(0) = (ret > 0) ? sv_2mortal(newSVuv(ret)) : &sv_undef;
+
+
+void
+pg_lo_export(dbh, lobjId, filename)
+       SV * dbh
+       unsigned int lobjId
+       char * filename
+       CODE:
+               ST(0) = (pg_db_lo_export(dbh, lobjId, filename) >= 1) ? &sv_yes 
: &sv_no;
+
+
+void
+lo_creat(dbh, mode)
+       SV * dbh
+       int mode
+       CODE:
+               const unsigned int ret = pg_db_lo_creat(dbh, mode);
+               ST(0) = (ret > 0) ? sv_2mortal(newSVuv(ret)) : &sv_undef;
+
+void
+lo_open(dbh, lobjId, mode)
+       SV * dbh
+       unsigned int lobjId
+       int mode
+       CODE:
+               const int ret = pg_db_lo_open(dbh, lobjId, mode);
+               ST(0) = (ret >= 0) ? sv_2mortal(newSViv(ret)) : &sv_undef;
+
+
+void
 lo_write(dbh, fd, buf, len)
        SV * dbh
        int fd
@@ -446,6 +519,28 @@
 
 
 void
+lo_read(dbh, fd, buf, len)
+       SV * dbh
+       int fd
+       char * buf
+       size_t len
+       PREINIT:
+               SV * const bufsv = SvROK(ST(2)) ? SvRV(ST(2)) : ST(2);
+               int ret;
+       CODE:
+               sv_setpvn(bufsv,"",0); /* Make sure we can grow it safely */
+               buf = SvGROW(bufsv, len + 1);
+               ret = pg_db_lo_read(dbh, fd, buf, len);
+               if (ret > 0) {
+                       SvCUR_set(bufsv, ret);
+                       *SvEND(bufsv) = '\0';
+                       sv_setpvn(ST(2), buf, (unsigned)ret);
+                       SvSETMAGIC(ST(2));
+               }
+               ST(0) = (ret >= 0) ? sv_2mortal(newSViv(ret)) : &sv_undef;
+
+
+void
 lo_lseek(dbh, fd, offset, whence)
        SV * dbh
        int fd
@@ -466,6 +561,14 @@
 
 
 void
+lo_close(dbh, fd)
+       SV * dbh
+       int fd
+       CODE:
+               ST(0) = (pg_db_lo_close(dbh, fd) >= 0) ? &sv_yes : &sv_no;
+
+
+void
 lo_unlink(dbh, lobjId)
        SV * dbh
        unsigned int lobjId
@@ -651,6 +754,7 @@
 
 #endif
 
+
 # -- end of DBD::Pg::db
 
 

Modified: DBD-Pg/trunk/dbdimp.c
==============================================================================
--- DBD-Pg/trunk/dbdimp.c       (original)
+++ DBD-Pg/trunk/dbdimp.c       Mon Mar 23 17:59:45 2009
@@ -4115,7 +4115,7 @@
 
 /* ================================================================== */
 /* For lo_import and lo_export functions. Used to commit or rollback a 
-   transaction, if AutoCommit is on. */
+   transaction, but only if AutoCommit is on. */
 static int pg_db_end_txn (pTHX_ SV * dbh, imp_dbh_t * imp_dbh, int commit)
 {
        int status = -1;
@@ -4123,8 +4123,8 @@
        if (TSTART) TRC(DBILOGFP, "%sBegin pg_db_end_txn with %s\n",
                                        THEADER, commit ? "commit" : 
"rollback");
 
-       /* If not autocommit, start a new transaction */
        status = _result(aTHX_ imp_dbh, commit ? "commit" : "rollback");
+       imp_dbh->done_begin = DBDPG_FALSE;
        if (PGRES_COMMAND_OK != status) {
                TRACE_PQERRORMESSAGE;
                pg_error(aTHX_ dbh, status, PQerrorMessage(imp_dbh->conn));
@@ -4133,9 +4133,8 @@
                return 0;
        }
 
-       imp_dbh->done_begin = DBDPG_FALSE;
-
        if (TEND) TRC(DBILOGFP, "%sEnd pg_db_end_txn\n", THEADER);
+
        return 1;
 
 } /* end of pg_db_end_txn */
@@ -4152,7 +4151,7 @@
        if (TSTART) TRC(DBILOGFP, "%sBegin pg_db_pg_lo_creat (mode: %d)\n", 
THEADER, mode);
 
        if (DBIc_has(imp_dbh, DBIcf_AutoCommit)) {
-               croak("Cannot call lo_creat when AutoCommit is on");
+               croak("Cannot call pg_lo_creat when AutoCommit is on");
        }
 
        if (!pg_db_start_txn(aTHX_ dbh,imp_dbh)) {
@@ -4178,7 +4177,7 @@
                                        THEADER, mode, lobjId);
 
        if (DBIc_has(imp_dbh, DBIcf_AutoCommit)) {
-               croak("Cannot call lo_open when AutoCommit is on");
+               croak("Cannot call pg_lo_open when AutoCommit is on");
        }
 
        if (!pg_db_start_txn(aTHX_ dbh,imp_dbh))
@@ -4202,7 +4201,7 @@
        if (TSTART) TRC(DBILOGFP, "%sBegin pg_db_lo_close (fd: %d)\n", THEADER, 
fd);
 
        if (DBIc_has(imp_dbh, DBIcf_AutoCommit)) {
-               croak("Cannot call lo_close when AutoCommit is on");
+               croak("Cannot call pg_lo_close when AutoCommit is on");
        }
 
        if (!pg_db_start_txn(aTHX_ dbh,imp_dbh))
@@ -4227,7 +4226,7 @@
                                        THEADER, fd, len);
 
        if (DBIc_has(imp_dbh, DBIcf_AutoCommit)) {
-               croak("Cannot call lo_read when AutoCommit is on");
+               croak("Cannot call pg_lo_read when AutoCommit is on");
        }
 
        if (!pg_db_start_txn(aTHX_ dbh,imp_dbh))
@@ -4252,7 +4251,7 @@
                                        THEADER, fd, len);
 
        if (DBIc_has(imp_dbh, DBIcf_AutoCommit)) {
-               croak("Cannot call lo_write when AutoCommit is on");
+               croak("Cannot call pg_lo_write when AutoCommit is on");
        }
 
        if (!pg_db_start_txn(aTHX_ dbh,imp_dbh))
@@ -4277,7 +4276,7 @@
                                        THEADER, fd, offset, whence);
 
        if (DBIc_has(imp_dbh, DBIcf_AutoCommit)) {
-               croak("Cannot call lo_lseek when AutoCommit is on");
+               croak("Cannot call pg_lo_lseek when AutoCommit is on");
        }
 
        if (!pg_db_start_txn(aTHX_ dbh,imp_dbh))
@@ -4301,7 +4300,7 @@
        if (TSTART) TRC(DBILOGFP, "%sBegin pg_db_lo_tell (fd: %d)\n", THEADER, 
fd);
 
        if (DBIc_has(imp_dbh, DBIcf_AutoCommit)) {
-               croak("Cannot call lo_tell when AutoCommit is on");
+               croak("Cannot call pg_lo_tell when AutoCommit is on");
        }
 
        if (!pg_db_start_txn(aTHX_ dbh,imp_dbh))
@@ -4325,7 +4324,7 @@
        if (TSTART) TRC(DBILOGFP, "%sBegin pg_db_lo_unlink (objectid: %d)\n", 
THEADER, lobjId);
 
        if (DBIc_has(imp_dbh, DBIcf_AutoCommit)) {
-               croak("Cannot call lo_unlink when AutoCommit is on");
+               croak("Cannot call pg_lo_unlink when AutoCommit is on");
        }
 
        if (!pg_db_start_txn(aTHX_ dbh,imp_dbh))

Modified: DBD-Pg/trunk/t/03dbmethod.t
==============================================================================
--- DBD-Pg/trunk/t/03dbmethod.t (original)
+++ DBD-Pg/trunk/t/03dbmethod.t Mon Mar 23 17:59:45 2009
@@ -2,11 +2,13 @@
 
 ## Test of the database handle methods
 ## The following methods are *not* (explicitly) tested here:
+## "take_imp_data"  "pg_server_trace"  "pg_server_untrace"  "pg_type_info"
 ## "data_sources" (see 04misc.t)
 ## "disconnect" (see 01connect.t)
-## "take_imp_data"
-## "pg_savepoint", "pg_release", "pg_rollback_to" (see 20savepoints.t)
-## "pg_putline", "pg_getline", "pg_endcopy" (see 07copy.t)
+## "pg_savepoint"  "pg_release"  "pg_rollback_to" (see 20savepoints.t)
+## "pg_getline"  "pg_endcopy"  "pg_getcopydata"  "pg_getcopydata_async" (see 
07copy.t)
+## "pg_putline"  "pg_putcopydata"  "pg_putcopydata_async (see 07copy.t)
+## "pg_cancel"  "pg_ready"  "pg_result" (see 08async.t)
 
 use 5.006;
 use strict;
@@ -24,7 +26,7 @@
 if (! defined $dbh) {
        plan skip_all => 'Connection to database failed, cannot continue 
testing';
 }
-plan tests => 507;
+plan tests => 521;
 
 isnt ($dbh, undef, 'Connect to database for database handle method testing');
 
@@ -37,6 +39,7 @@
 
 # Quick simple "tests"
 
+
 $dbh->do(q{}); ## This used to break, so we keep it as a test...
 $SQL = q{SELECT '2529DF6AB8F79407E94445B4BC9B906714964AC8' FROM dbd_pg_test 
WHERE id=?};
 $sth = $dbh->prepare($SQL);
@@ -1290,75 +1293,83 @@
 is_deeply (\%missing, {}, $t);
 
 #
-# Test of the "lo_*" database handle methods
+# Test of the "pg_lo_*" database handle methods
 #
 
-$t='DB handle method "lo_creat" returns a valid descriptor for reading';
+$t='DB handle method "pg_lo_creat" returns a valid descriptor for reading';
 $dbh->{AutoCommit}=1; $dbh->{AutoCommit}=0; ## Catch error where not in begin
 
 my ($R,$W) = ($dbh->{pg_INV_READ}, $dbh->{pg_INV_WRITE});
 my $RW = $R|$W;
-my $object = $dbh->func($R, 'lo_creat');
+my $object;
+
+$t='DB handle method "pg_lo_creat" works with old-school dbh->func() method';
+$object = $dbh->func($W, 'pg_lo_creat');
 like ($object, qr/^\d+$/o, $t);
 isnt ($object, 0, $t);
 
-$t='DB handle method "lo_creat" returns a valid descriptor for writing';
+$t='DB handle method "pg_lo_creat" works with deprecated 
dbh->func(...lo_creat) method';
 $object = $dbh->func($W, 'lo_creat');
 like ($object, qr/^\d+$/o, $t);
 isnt ($object, 0, $t);
 
-$t='DB handle method "lo_open" returns a valid descriptor for writing';
-my $handle = $dbh->func($object, $W, 'lo_open');
+$t='DB handle method "pg_lo_creat" returns a valid descriptor for writing';
+$object = $dbh->pg_lo_creat($W);
+like ($object, qr/^\d+$/o, $t);
+isnt ($object, 0, $t);
+
+$t='DB handle method "pg_lo_open" returns a valid descriptor for writing';
+my $handle = $dbh->pg_lo_open($object, $W);
 like ($handle, qr/^\d+$/o, $t);
 isnt ($object, -1, $t);
 
-$t='DB handle method "lo_lseek" works when writing';
-$result = $dbh->func($handle, 0, 0, 'lo_lseek');
+$t='DB handle method "pg_lo_lseek" works when writing';
+$result = $dbh->pg_lo_lseek($handle, 0, 0);
 is ($result, 0, $t);
 isnt ($object, -1, $t);
 
-$t='DB handle method "lo_write" works';
+$t='DB handle method "pg_lo_write" works';
 my $buf = 'tangelo mulberry passionfruit raspberry plantain' x 500;
-$result = $dbh->func($handle, $buf, length($buf), 'lo_write');
+$result = $dbh->pg_lo_write($handle, $buf, length($buf));
 is ($result, length($buf), $t);
 cmp_ok ($object, '>', 0, $t);
 
-$t='DB handle method "lo_close" works after write';
-$result = $dbh->func($handle, 'lo_close');
+$t='DB handle method "pg_lo_close" works after write';
+$result = $dbh->pg_lo_close($handle);
 ok ($result, $t);
 
 # Reopen for reading
-$t='DB handle method "lo_open" returns a valid descriptor for reading';
-$handle = $dbh->func($object, $R, 'lo_open');
+$t='DB handle method "pg_lo_open" returns a valid descriptor for reading';
+$handle = $dbh->pg_lo_open($object, $R);
 like ($handle, qr/^\d+$/o, $t);
 cmp_ok ($handle, 'eq', 0, $t);
 
-$t='DB handle method "lo_lseek" works when reading';
-$result = $dbh->func($handle, 11, 0, 'lo_lseek');
+$t='DB handle method "pg_lo_lseek" works when reading';
+$result = $dbh->pg_lo_lseek($handle, 11, 0);
 is ($result, 11, $t);
 
-$t='DB handle method "lo_tell" works';
-$result = $dbh->func($handle, 'lo_tell');
+$t='DB handle method "pg_lo_tell" works';
+$result = $dbh->pg_lo_tell($handle);
 is ($result, 11, $t);
 
-$t='DB handle method "lo_read" read back the same data that was written';
-$dbh->func($handle, 0, 0, 'lo_lseek');
+$t='DB handle method "pg_lo_read" read back the same data that was written';
+$dbh->pg_lo_lseek($handle, 0, 0);
 my ($buf2,$data) = ('','');
-while ($dbh->func($handle, $data, 513, 'lo_read')) {
+while ($dbh->pg_lo_read($handle, $data, 513)) {
        $buf2 .= $data;
 }
 is (length($buf), length($buf2), $t);
 
-$t='DB handle method "lo_close" works after read';
-$result = $dbh->func($handle, 'lo_close');
+$t='DB handle method "pg_lo_close" works after read';
+$result = $dbh->pg_lo_close($handle);
 ok ($result, $t);
 
-$t='DB handle method "lo_unlink" works';
-$result = $dbh->func($object, 'lo_unlink');
+$t='DB handle method "pg_lo_unlink" works';
+$result = $dbh->pg_lo_unlink($object);
 is ($result, 1, $t);
 
-$t='DB handle method "lo_unlink" fails when called second time';
-$result = $dbh->func($object, 'lo_unlink');
+$t='DB handle method "pg_lo_unlink" fails when called second time';
+$result = $dbh->pg_lo_unlink($object);
 ok (!$result, $t);
 $dbh->rollback();
 
@@ -1367,34 +1378,34 @@
        eval {
                require File::Temp;
        };
-       $@ and skip ('Must have File::Temp to test lo_import and lo_export', 8);
+       $@ and skip ('Must have File::Temp to test pg_lo_import and 
pg_lo_export', 8);
 
-       $t='DB handle method "lo_import" works';
+       $t='DB handle method "pg_lo_import" works';
        my ($fh,$filename) = File::Temp::tmpnam();
        print $fh "abc\ndef";
        close $fh or warn 'Failed to close temporary file';
-       my $handle = $dbh->func($filename, 'lo_import');
+       my $handle = $dbh->pg_lo_import($filename);
        my $objid = $handle;
        ok ($handle, $t);
 
-       $t='DB handle method "lo_import" inserts correct data';
+       $t='DB handle method "pg_lo_import" inserts correct data';
        $SQL = "SELECT data FROM pg_largeobject where loid = $handle";
        $info = $dbh->selectall_arrayref($SQL)->[0][0];
        is_deeply ($info, "abc\ndef", $t);
 
-       $t='DB handle method "lo_open" works after "lo_insert"';
-       $handle = $dbh->func($handle, $R, 'lo_open');
+       $t='DB handle method "pg_lo_open" works after "pg_lo_insert"';
+       $handle = $dbh->pg_lo_open($handle, $R);
        like ($handle, qr/^\d+$/o, $t);
 
-       $t='DB handle method "lo_read" returns correct data after "lo_import"';
+       $t='DB handle method "pg_lo_read" returns correct data after 
"pg_lo_import"';
        my $data = '';
-       $result = $dbh->func($handle, $data, 100, 'lo_read');
+       $result = $dbh->pg_lo_read($handle, $data, 100);
        is ($result, 7, $t);
        is ($data, "abc\ndef", $t);
 
-       $t='DB handle method "lo_export" works';
+       $t='DB handle method "pg_lo_export" works';
        ($fh,$filename) = File::Temp::tmpnam();
-       $result = $dbh->func($objid, $filename, 'lo_export');
+       $result = $dbh->pg_lo_export($objid, $filename);
        ok (-e $filename, $t);
        seek($fh,0,1);
        seek($fh,0,0);
@@ -1404,57 +1415,58 @@
        close $fh or warn 'Could not close tempfile';
 }
 
-## Same tests, but with AutoCommit on
+## Same pg_lo_* tests, but with AutoCommit on
+
 $dbh->{AutoCommit}=1;
 
-$t='DB handle method "lo_creat" fails when AutoCommit on';
+$t='DB handle method "pg_lo_creat" fails when AutoCommit on';
 eval {
-       $dbh->func($W, 'lo_creat');
+       $dbh->pg_lo_creat($W);
 };
-like ($@, qr{lo_creat when AutoCommit is on}, $t);
+like ($@, qr{pg_lo_creat when AutoCommit is on}, $t);
 
-$t='DB handle method "lo_open" fails with AutoCommit on';
+$t='DB handle method "pg_lo_open" fails with AutoCommit on';
 eval {
-       $dbh->func($object, $W, 'lo_open');
+       $dbh->pg_lo_open($object, $W);
 };
-like ($@, qr{lo_open when AutoCommit is on}, $t);
+like ($@, qr{pg_lo_open when AutoCommit is on}, $t);
 
-$t='DB handle method "lo_read" fails with AutoCommit on';
+$t='DB handle method "pg_lo_read" fails with AutoCommit on';
 eval {
-       $dbh->func($object, $data, 0, 'lo_read');
+       $dbh->pg_lo_read($object, $data, 0);
 };
-like ($@, qr{lo_read when AutoCommit is on}, $t);
+like ($@, qr{pg_lo_read when AutoCommit is on}, $t);
 
-$t='DB handle method "lo_lseek" fails with AutoCommit on';
+$t='DB handle method "pg_lo_lseek" fails with AutoCommit on';
 eval {
-       $dbh->func($handle, 0, 0, 'lo_lseek');
+       $dbh->pg_lo_lseek($handle, 0, 0);
 };
-like ($@, qr{lo_lseek when AutoCommit is on}, $t);
+like ($@, qr{pg_lo_lseek when AutoCommit is on}, $t);
 
-$t='DB handle method "lo_write" fails with AutoCommit on';
+$t='DB handle method "pg_lo_write" fails with AutoCommit on';
 $buf = 'tangelo mulberry passionfruit raspberry plantain' x 500;
 eval {
-       $dbh->func($handle, $buf, length($buf), 'lo_write');
+       $dbh->pg_lo_write($handle, $buf, length($buf));
 };
-like ($@, qr{lo_write when AutoCommit is on}, $t);
+like ($@, qr{pg_lo_write when AutoCommit is on}, $t);
 
-$t='DB handle method "lo_close" fails with AutoCommit on';
+$t='DB handle method "pg_lo_close" fails with AutoCommit on';
 eval {
-       $dbh->func($handle, 'lo_close');
+       $dbh->pg_lo_close($handle);
 };
-like ($@, qr{lo_close when AutoCommit is on}, $t);
+like ($@, qr{pg_lo_close when AutoCommit is on}, $t);
 
-$t='DB handle method "lo_tell" fails with AutoCommit on';
+$t='DB handle method "pg_lo_tell" fails with AutoCommit on';
 eval {
-       $dbh->func($handle, 'lo_tell');
+       $dbh->pg_lo_tell($handle);
 };
-like ($@, qr{lo_tell when AutoCommit is on}, $t);
+like ($@, qr{pg_lo_tell when AutoCommit is on}, $t);
 
-$t='DB handle method "lo_unlink" fails with AutoCommit on';
+$t='DB handle method "pg_lo_unlink" fails with AutoCommit on';
 eval {
-       $dbh->func($object, 'lo_unlink');
+       $dbh->pg_lo_unlink($object);
 };
-like ($@, qr{lo_unlink when AutoCommit is on}, $t);
+like ($@, qr{pg_lo_unlink when AutoCommit is on}, $t);
 
 
 SKIP: {
@@ -1462,24 +1474,84 @@
        eval {
                require File::Temp;
        };
-       $@ and skip ('Must have File::Temp to test lo_import and lo_export', 2);
+       $@ and skip ('Must have File::Temp to test pg_lo_import and 
pg_lo_export', 5);
 
-       $t='DB handle method "lo_import" works (AutoCommit on)';
+       $t='DB handle method "pg_lo_import" works (AutoCommit on)';
        my ($fh,$filename) = File::Temp::tmpnam();
        print $fh "abc\ndef";
        close $fh or warn 'Failed to close temporary file';
-       my $handle = $dbh->func($filename, 'lo_import');
-       my $objid = $handle;
+       my $handle = $dbh->pg_lo_import($filename);
        ok ($handle, $t);
 
-       $t='DB handle method "lo_import" inserts correct data (AutoCommit on)';
-       $SQL = "SELECT data FROM pg_largeobject where loid = $handle";
-       $info = $dbh->selectall_arrayref($SQL)->[0][0];
+       $t='DB handle method "pg_lo_import" inserts correct data (AutoCommit 
on, begin_work not called)';
+       $SQL = "SELECT data FROM pg_largeobject where loid = ?";
+       $sth = $dbh->prepare($SQL);
+       $sth->execute($handle);
+       $info = $sth->fetchall_arrayref()->[0][0];
        is_deeply ($info, "abc\ndef", $t);
 
-       $t='DB handle method "lo_export" works (AutoCommit on)';
+       $t='DB handle method "pg_lo_import" works (AutoCommit on, begin_work 
called, no command)';
+       $dbh->begin_work();
+       $handle = $dbh->pg_lo_import($filename);
+       ok ($handle, $t);
+       $sth->execute($handle);
+       $info = $sth->fetchall_arrayref()->[0][0];
+       is_deeply ($info, "abc\ndef", $t);
+       $dbh->rollback();
+
+       $t='DB handle method "pg_lo_import" works (AutoCommit on, begin_work 
called, no command, rollback)';
+       $dbh->begin_work();
+       $handle = $dbh->pg_lo_import($filename);
+       ok ($handle, $t);
+       $dbh->rollback();
+       $sth->execute($handle);
+       $info = $sth->fetchall_arrayref()->[0][0];
+       is_deeply ($info, undef, $t);
+
+       $t='DB handle method "pg_lo_import" works (AutoCommit on, begin_work 
called, second command)';
+       $dbh->begin_work();
+       $dbh->do('SELECT 123');
+       $handle = $dbh->pg_lo_import($filename);
+       ok ($handle, $t);
+       $sth->execute($handle);
+       $info = $sth->fetchall_arrayref()->[0][0];
+       is_deeply ($info, "abc\ndef", $t);
+       $dbh->rollback();
+
+       $t='DB handle method "pg_lo_import" works (AutoCommit on, begin_work 
called, second command, rollback)';
+       $dbh->begin_work();
+       $dbh->do('SELECT 123');
+       $handle = $dbh->pg_lo_import($filename);
+       ok ($handle, $t);
+       $dbh->rollback();
+       $sth->execute($handle);
+       $info = $sth->fetchall_arrayref()->[0][0];
+       is_deeply ($info, undef, $t);
+
+       $t='DB handle method "pg_lo_import" works (AutoCommit not on, no 
command)';
+       $dbh->{AutoCommit} = 0;
+       $dbh->commit();
+       $handle = $dbh->pg_lo_import($filename);
+       ok ($handle, $t);
+       $sth->execute($handle);
+       $info = $sth->fetchall_arrayref()->[0][0];
+       is_deeply ($info, "abc\ndef", $t);
+
+       $t='DB handle method "pg_lo_import" works (AutoCommit not on, second 
command)';
+       $dbh->rollback();
+       $dbh->do('SELECT 123');
+       $handle = $dbh->pg_lo_import($filename);
+       ok ($handle, $t);
+       $sth->execute($handle);
+       $info = $sth->fetchall_arrayref()->[0][0];
+       is_deeply ($info, "abc\ndef", $t);
+
+       $dbh->{AutoCommit} = 1;
+
+       my $objid = $handle;
+       $t='DB handle method "pg_lo_export" works (AutoCommit on)';
        ($fh,$filename) = File::Temp::tmpnam();
-       $result = $dbh->func($objid, $filename, 'lo_export');
+       $result = $dbh->pg_lo_export($objid, $filename);
        ok (-e $filename, $t);
        seek($fh,0,1);
        seek($fh,0,0);

Reply via email to