[sr-dev] git:master: modules/db_postgres: Added implementation of (start|end|abort) _transaction DB APIs

Peter Dunkley peter.dunkley at crocodile-rcs.com
Tue Apr 24 11:59:12 CEST 2012


Module: sip-router
Branch: master
Commit: d544b24a6c844b06edd5da9ee1be9d6f2aafcb8d
URL:    http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=d544b24a6c844b06edd5da9ee1be9d6f2aafcb8d

Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
Committer: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
Date:   Tue Apr 24 10:53:24 2012 +0100

modules/db_postgres: Added implementation of (start|end|abort)_transaction DB APIs

---

 modules/db_postgres/km_db_postgres.c |    3 +
 modules/db_postgres/km_dbase.c       |  101 ++++++++++++++++++++++++++++++++++
 modules/db_postgres/km_dbase.h       |   15 +++++
 modules/db_postgres/km_pg_con.h      |    2 +
 4 files changed, 121 insertions(+), 0 deletions(-)

diff --git a/modules/db_postgres/km_db_postgres.c b/modules/db_postgres/km_db_postgres.c
index f56a2ff..34edca7 100644
--- a/modules/db_postgres/km_db_postgres.c
+++ b/modules/db_postgres/km_db_postgres.c
@@ -96,6 +96,9 @@ int db_postgres_bind_api(db_func_t *dbb)
 	dbb->update           = db_postgres_update;
 	dbb->replace          = db_postgres_replace;
 	dbb->affected_rows    = db_postgres_affected_rows;
+	dbb->start_transaction= db_postgres_start_transaction;
+	dbb->end_transaction  = db_postgres_end_transaction;
+	dbb->abort_transaction= db_postgres_abort_transaction;
 
 	return 0;
 }
diff --git a/modules/db_postgres/km_dbase.c b/modules/db_postgres/km_dbase.c
index 5e79d52..101cc8e 100644
--- a/modules/db_postgres/km_dbase.c
+++ b/modules/db_postgres/km_dbase.c
@@ -624,6 +624,107 @@ int db_postgres_affected_rows(const db1_con_t* _h)
 	return CON_AFFECTED(_h);
 }
 
+/**
+ * Starts a single transaction that will consist of one or more queries (SQL BEGIN)
+ * \param _h database handle
+ * \return 0 on success, negative on failure
+ */
+int db_postgres_start_transaction(db1_con_t* _h)
+{
+	db1_res_t *res = NULL;
+	str query_str = str_init("BEGIN");
+	
+	if (!_h) {
+		LM_ERR("invalid parameter value\n");
+		return -1;
+	}
+
+	if (CON_TRANSACTION(_h) == 1) {
+		LM_ERR("transaction already started\n");
+		return -1;
+	}
+
+	if (db_postgres_raw_query(_h, &query_str, &res) < 0)
+	{
+		LM_ERR("executing raw_query\n");
+		return -1;
+	}
+
+	if (res) db_postgres_free_result(_h, res);
+
+	CON_TRANSACTION(_h) = 1;
+	return 0;
+}
+
+/**
+ * Ends a transaction and commits the changes (SQL COMMIT)
+ * \param _h database handle
+ * \return 0 on success, negative on failure
+ */
+int db_postgres_end_transaction(db1_con_t* _h)
+{
+	db1_res_t *res = NULL;
+	str query_str = str_init("COMMIT");
+	
+	if (!_h) {
+		LM_ERR("invalid parameter value\n");
+		return -1;
+	}
+
+	if (CON_TRANSACTION(_h) == 0) {
+		LM_ERR("transaction not in progress\n");
+		return -1;
+	}
+
+	if (db_postgres_raw_query(_h, &query_str, &res) < 0)
+	{
+		LM_ERR("executing raw_query\n");
+		return -1;
+	}
+
+	if (res) db_postgres_free_result(_h, res);
+
+	/* Only _end_ the transaction after the raw_query.  That way, if the
+ 	   raw_query fails, and the calling module does an abort_transaction()
+	   to clean-up, a ROLLBACK will be sent to the DB. */
+	CON_TRANSACTION(_h) = 0;
+	return 0;
+}
+
+/**
+ * Ends a transaction and rollsback the changes (SQL ROLLBACK)
+ * \param _h database handle
+ * \return 1 if there was something to rollback, 0 if not, negative on failure
+ */
+int db_postgres_abort_transaction(db1_con_t* _h)
+{
+	db1_res_t *res = NULL;
+	str query_str = str_init("ROLLBACK");
+	
+	if (!_h) {
+		LM_ERR("invalid parameter value\n");
+		return -1;
+	}
+
+	if (CON_TRANSACTION(_h) == 0) {
+		LM_DBG("nothing to rollback\n");
+		return 0;
+	}
+
+	/* Whether the rollback succeeds or not we need to _end_ the
+ 	   transaction now or all future starts will fail */
+	CON_TRANSACTION(_h) = 0;
+
+	if (db_postgres_raw_query(_h, &query_str, &res) < 0)
+	{
+		LM_ERR("executing raw_query\n");
+		return -1;
+	}
+
+	if (res) db_postgres_free_result(_h, res);
+
+	return 1;
+}
 
 /*!
  * Store name of table that will be used by subsequent database functions
diff --git a/modules/db_postgres/km_dbase.h b/modules/db_postgres/km_dbase.h
index 60c824b..4598139 100644
--- a/modules/db_postgres/km_dbase.h
+++ b/modules/db_postgres/km_dbase.h
@@ -113,6 +113,21 @@ int db_postgres_fetch_result(const db1_con_t* _h, db1_res_t** _r, const int nrow
 int db_postgres_affected_rows(const db1_con_t* _h);
 
 /*
+ * SQL BEGIN
+ */
+int db_postgres_start_transaction(db1_con_t* _h);
+
+/*
+ * SQL COMMIT
+ */
+int db_postgres_end_transaction(db1_con_t* _h);
+
+/*
+ * SQL ROLLBACK
+ */
+int db_postgres_abort_transaction(db1_con_t* _h);
+
+/*
  * Store name of table that will be used by
  * subsequent database functions
  */
diff --git a/modules/db_postgres/km_pg_con.h b/modules/db_postgres/km_pg_con.h
index b0f92c6..bfc2638 100644
--- a/modules/db_postgres/km_pg_con.h
+++ b/modules/db_postgres/km_pg_con.h
@@ -54,6 +54,7 @@ struct pg_con {
 	char**  row;		/*!< Actual row in the result */
 	time_t timestamp;	/*!< Timestamp of last query */
 	int affected_rows;	/*!< Number of rows affected by the last statement */
+	int transaction;	/*!< indicates whether a multi-query transaction is currently open */
 };
 
 #define CON_SQLURL(db_con)     (((struct pg_con*)((db_con)->tail))->sqlurl)
@@ -64,6 +65,7 @@ struct pg_con {
 #define CON_TIMESTAMP(db_con)  (((struct pg_con*)((db_con)->tail))->timestamp)
 #define CON_ID(db_con) 	       (((struct pg_con*)((db_con)->tail))->id)
 #define CON_AFFECTED(db_con)   (((struct pg_con*)((db_con)->tail))->affected_rows)
+#define CON_TRANSACTION(db_con) (((struct pg_con*)((db_con)->tail))->transaction)
 
 /*
  * Create a new connection structure,




More information about the sr-dev mailing list