浏览代码

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

Peter Dunkley 13 年之前
父节点
当前提交
d544b24a6c
共有 4 个文件被更改,包括 121 次插入0 次删除
  1. 3 0
      modules/db_postgres/km_db_postgres.c
  2. 101 0
      modules/db_postgres/km_dbase.c
  3. 15 0
      modules/db_postgres/km_dbase.h
  4. 2 0
      modules/db_postgres/km_pg_con.h

+ 3 - 0
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;
 }

+ 101 - 0
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

+ 15 - 0
modules/db_postgres/km_dbase.h

@@ -112,6 +112,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

+ 2 - 0
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,