changeset 8653:4dadcc2f6be2 HEAD

pgsql: More fixes to transaction handling.
author Timo Sirainen <tss@iki.fi>
date Sun, 18 Jan 2009 21:02:15 -0500
parents 8b3af54b4dc3
children abb1a50a266d
files src/lib-sql/driver-pgsql.c
diffstat 1 files changed, 32 insertions(+), 21 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-sql/driver-pgsql.c	Sun Jan 18 20:15:26 2009 -0500
+++ b/src/lib-sql/driver-pgsql.c	Sun Jan 18 21:02:15 2009 -0500
@@ -79,6 +79,8 @@
 	const char *error;
 
 	unsigned int opened:1;
+	unsigned int begin_succeeded:1;
+	unsigned int begin_failed:1;
 	unsigned int failed:1;
 };
 
@@ -882,24 +884,28 @@
 
 	if (ctx->failed) {
 		callback(ctx->error, context);
-		if (ctx->opened)
+		if (!ctx->begin_failed)
 			sql_exec(_ctx->db, "ROLLBACK");
 		driver_pgsql_transaction_unref(ctx);
 		return;
 	}
 
-	if (!ctx->opened) {
-		/* nothing done */
-		ctx->callback(NULL, ctx->context);
-		driver_pgsql_transaction_unref(ctx);
-		return;
-	}
-
 	ctx->callback = callback;
 	ctx->context = context;
 
-	driver_pgsql_query_full(_ctx->db, "COMMIT",
-				transaction_commit_callback, ctx, FALSE);
+	if (ctx->first_update != NULL) {
+		sql_query(_ctx->db, ctx->first_update,
+			  transaction_commit_callback, ctx);
+		i_free_and_null(ctx->first_update);
+	} else if (ctx->opened) {
+		driver_pgsql_query_full(_ctx->db, "COMMIT",
+					transaction_commit_callback, ctx,
+					FALSE);
+	} else {
+		/* nothing done */
+		ctx->callback(NULL, ctx->context);
+		driver_pgsql_transaction_unref(ctx);
+	}
 }
 
 static int
@@ -910,20 +916,21 @@
 		(struct pgsql_transaction_context *)_ctx;
 	struct sql_result *result;
 
-	if (ctx->first_update != NULL) {
-		ctx->refcount++;
-		sql_query(_ctx->db, ctx->first_update,
-			  transaction_update_callback, ctx);
-		i_free_and_null(ctx->first_update);
-	}
-
 	if (ctx->failed) {
 		*error_r = ctx->error;
-		if (ctx->opened)
+		if (!ctx->begin_failed)
 			sql_exec(_ctx->db, "ROLLBACK");
-	} else if (!ctx->opened)
+	} else if (ctx->first_update != NULL) {
+		result = sql_query_s(_ctx->db, ctx->first_update);
+		if (sql_result_next_row(result) < 0)
+			*error_r = sql_result_get_error(result);
+		else
+			*error_r = NULL;
+		i_free_and_null(ctx->first_update);
+		sql_result_free(result);
+	} else if (!ctx->opened) {
 		*error_r = NULL;
-	else {
+	} else {
 		result = sql_query_s(_ctx->db, "COMMIT");
 		if (ctx->failed)
 			*error_r = ctx->error;
@@ -944,7 +951,7 @@
 	struct pgsql_transaction_context *ctx =
 		(struct pgsql_transaction_context *)_ctx;
 
-	if (ctx->opened)
+	if (!ctx->begin_failed)
 		sql_exec(_ctx->db, "ROLLBACK");
 	driver_pgsql_transaction_unref(ctx);
 }
@@ -955,8 +962,12 @@
 	struct pgsql_transaction_context *ctx = context;
 
 	if (sql_result_next_row(result) < 0) {
+		if (!ctx->begin_succeeded)
+			ctx->begin_failed = TRUE;
 		ctx->failed = TRUE;
 		ctx->error = sql_result_get_error(result);
+	} else {
+		ctx->begin_succeeded = TRUE;
 	}
 	driver_pgsql_transaction_unref(ctx);
 }