--- dbdimp.c.orig	Tue Mar 25 17:12:10 2003
+++ dbdimp.c	Tue Mar 25 17:45:21 2003
@@ -94,10 +94,40 @@
     DBIh_EVENT2(h, ERROR_event, DBIc_ERR(imp_xxh), DBIc_ERRSTR(imp_xxh));
     if (dbis->debug >= 2) { PerlIO_printf(DBILOGFP, "%s error %d recorded: %s\n", err, error_num, SvPV(DBIc_ERRSTR(imp_xxh),na)); }
     free(err);
 }
 
+
+int
+_dbd_begin(dbh, imp_dbh)
+    SV *dbh;
+    imp_dbh_t *imp_dbh;
+{
+    PGresult *result = NULL;
+    ExecStatusType status;
+
+    if (DBIc_has(imp_dbh, DBIcf_AutoCommit) == TRUE)
+        return 1;
+
+    if (imp_dbh->pg_need_begin == 0)
+        return 1;
+
+    imp_dbh->pg_need_begin = 0;
+
+    /* start new transaction.  AutoCommit must be FALSE, ref. ~8 lines up */
+    result = PQexec(imp_dbh->conn, "begin");
+    status = result ? PQresultStatus(result) : -1;
+    PQclear(result);
+    if (status != PGRES_COMMAND_OK) {
+        pg_error(dbh, status, "begin failed\n");
+        return 0;
+    }
+
+    return 1;
+}
+
+
 static int
 pgtype_bind_ok (dbtype)
     int dbtype;
 {
     /* basically we support types that can be returned as strings */
@@ -190,10 +220,11 @@
     }
 
     imp_dbh->init_commit = 1;			/* initialize AutoCommit */
     imp_dbh->pg_auto_escape = 1;		/* initialize pg_auto_escape */
     imp_dbh->pg_bool_tf = 0;                    /* initialize pg_bool_tf */
+    imp_dbh->pg_need_begin = 1;                 /* initialize begin state */
 
     DBIc_IMPSET_on(imp_dbh);			/* imp_dbh set up now */
     DBIc_ACTIVE_on(imp_dbh);			/* call disconnect before freeing */
     return 1;
 }
@@ -279,11 +310,11 @@
         return 0;
     }
 
     if (NULL != imp_dbh->conn) {
         PGresult* result = 0;
-        ExecStatusType commitstatus, beginstatus;
+        ExecStatusType commitstatus;
 
         /* execute commit */
         result = PQexec(imp_dbh->conn, "commit");
         commitstatus = result ? PQresultStatus(result) : -1;
         PQclear(result);
@@ -292,19 +323,12 @@
         if (commitstatus != PGRES_COMMAND_OK) {
 	    /* Only put the error message in DBH->errstr */
 	    pg_error(dbh, commitstatus, PQerrorMessage(imp_dbh->conn));
         }
 
-        /* start new transaction.  AutoCommit must be FALSE, ref. 20 lines up */
-        result = PQexec(imp_dbh->conn, "begin");
-        beginstatus = result ? PQresultStatus(result) : -1;
-        PQclear(result);
-        if (beginstatus != PGRES_COMMAND_OK) {
-	    /* Maybe add some loud barf here? Raising some very high error? */
-            pg_error(dbh, beginstatus, "begin failed\n");
-            return 0;
-        }
+        /* mark need for a begin at the start of the next command */
+        imp_dbh->pg_need_begin = 1;
 
 	/* if the initial COMMIT failed, return 0 now */
 	if (commitstatus != PGRES_COMMAND_OK) {
             return 0;
         }
@@ -330,10 +354,14 @@
 
     if (NULL != imp_dbh->conn) {
         PGresult* result = 0;
         ExecStatusType status;
         
+        /* no rollback is needed if we are not already in a transaction */
+        if (imp_dbh->pg_need_begin)
+            return 1;
+
         /* execute rollback */
         result = PQexec(imp_dbh->conn, "rollback");
         status = result ? PQresultStatus(result) : -1;
         PQclear(result);
 
@@ -341,18 +369,12 @@
         if (status != PGRES_COMMAND_OK) {
             pg_error(dbh, status, "rollback failed\n");
             return 0;
         }
 
-        /* start new transaction.  AutoCommit must be FALSE, ref. 20 lines up */
-        result = PQexec(imp_dbh->conn, "begin");
-        status = result ? PQresultStatus(result) : -1;
-        PQclear(result);
-        if (status != PGRES_COMMAND_OK) {
-            pg_error(dbh, status, "begin failed\n");
-            return 0;
-        }
+        /* mark need for a begin at the start of the next command */
+        imp_dbh->pg_need_begin = 1;
         
         return 1;
     }
 
     return 0;
@@ -372,11 +394,12 @@
     /* since most errors imply already disconnected.	*/
     DBIc_ACTIVE_off(imp_dbh);
 
     if (NULL != imp_dbh->conn) {
         /* rollback if AutoCommit = off */
-        if (DBIc_has(imp_dbh, DBIcf_AutoCommit) == FALSE) {
+        if ((imp_dbh->pg_need_begin == 0)
+           && (DBIc_has(imp_dbh, DBIcf_AutoCommit) == FALSE)) {
             PGresult* result = 0;
             ExecStatusType status;
             result = PQexec(imp_dbh->conn, "rollback");
             status = result ? PQresultStatus(result) : -1;
             PQclear(result);
@@ -448,20 +471,11 @@
                 }
             }            
             if (dbis->debug >= 2) { PerlIO_printf(DBILOGFP, "dbd_db_STORE: switch AutoCommit to on: commit\n"); }
         } else if ((oldval != FALSE && newval == FALSE) || (oldval == FALSE && newval == FALSE && imp_dbh->init_commit)) {
             if (NULL != imp_dbh->conn) {
-                /* start new transaction */
-                PGresult* result = 0;
-                ExecStatusType status;
-                result = PQexec(imp_dbh->conn, "begin");
-                status = result ? PQresultStatus(result) : -1;
-                PQclear(result);
-                if (status != PGRES_COMMAND_OK) {
-                    pg_error(dbh, status, "begin failed\n");
-                    return 0;
-                }
+                imp_dbh->pg_need_begin = 1;
             }
             if (dbis->debug >= 2) { PerlIO_printf(DBILOGFP, "dbd_db_STORE: switch AutoCommit to off: begin\n"); }
         }
         /* only needed once */
         imp_dbh->init_commit = 0;
@@ -1127,10 +1141,13 @@
     char namebuf[30];
     phs_t *phs;
     SV **svp;
 
     if (dbis->debug >= 1) { PerlIO_printf(DBILOGFP, "dbd_st_execute\n"); }
+
+    if (_dbd_begin(sth, imp_dbh) == 0)
+        return 0;
 
     /*
     here we get the statement from the statement handle where
     it has been stored when creating a blank sth during prepare
     svp = hv_fetch((HV *)SvRV(sth), "Statement", 9, FALSE);
