Explorar el Código

Merge pull request #606 from giovannimele/master

db_unixodbc: some ODBC drivers do not support ODBC replace query
Daniel-Constantin Mierla hace 9 años
padre
commit
7ffaad57ab

+ 2 - 0
modules/db_unixodbc/connection.h

@@ -63,6 +63,7 @@ struct my_con
 	SQLHDBC dbc;			/*!< Connection representation */
 	char** row;			/*!< Actual row in the result */
 	time_t timestamp;		/*!< Timestamp of last query */
+	int statement_res;		/*!< ODBC real statement result */
 };
 
 /*
@@ -74,6 +75,7 @@ struct my_con
 #define CON_TIMESTAMP(db_con)  (((struct my_con*)((db_con)->tail))->timestamp)
 #define CON_ID(db_con) 		(((struct my_con*)((db_con)->tail))->id)
 #define CON_ENV(db_con)		(((struct my_con*)((db_con)->tail))->env)
+#define CON_QUERY_RESULT(db_con) (((struct my_con*)((db_con)->tail))->statement_res)
 
 #define MAX_CONN_STR_LEN 2048
 

+ 6 - 1
modules/db_unixodbc/db_unixodbc.c

@@ -37,6 +37,7 @@
 int ping_interval = 5 * 60; /* Default is 5 minutes */
 int auto_reconnect = 1;     /* Default is enabled */
 int use_escape_common = 0;  /* Enable common escaping */
+int replace_query = 1;      /* Enable ODBC replace query */
 
 MODULE_VERSION
 
@@ -59,6 +60,7 @@ static param_export_t params[] = {
 	{"ping_interval",     INT_PARAM, &ping_interval},
 	{"auto_reconnect",    INT_PARAM, &auto_reconnect},
 	{"use_escape_common", INT_PARAM, &use_escape_common},
+	{"replace_query", INT_PARAM, &replace_query},
 	{0, 0, 0}
 };
 
@@ -95,7 +97,10 @@ int db_unixodbc_bind_api(db_func_t *dbb)
 	dbb->insert           = db_unixodbc_insert;
 	dbb->delete           = db_unixodbc_delete; 
 	dbb->update           = db_unixodbc_update;
-	dbb->replace          = db_unixodbc_replace;
+	if (replace_query)
+		dbb->replace      = db_unixodbc_replace;
+	else
+		dbb->replace      = db_unixodbc_update_or_insert;
 
 	return 0;
 }

+ 49 - 1
modules/db_unixodbc/dbase.c

@@ -160,7 +160,8 @@ static int db_unixodbc_submit_query(const db1_con_t* _h, const str* _s)
 			SQLFreeHandle(SQL_HANDLE_STMT, CON_RESULT(_h));
 		}
 	}
-
+	/* Store the ODBC query result */
+	CON_QUERY_RESULT(_h) = ret;
 	return ret;
 }
 
@@ -485,6 +486,53 @@ int db_unixodbc_replace(const db1_con_t* _h, const db_key_t* _k, const db_val_t*
 			db_unixodbc_submit_query);
 }
 
+
+/*
+ * Just like insert, but update the row if it exists otherwise insert it.
+ * For DB not supporting the replace query.
+ */
+int db_unixodbc_update_or_insert(const db1_con_t* _h, const db_key_t* _k, const db_val_t* _v,
+		const int _n, const int _un, const int _m)
+{
+	if(_un > _n)
+	{
+		LM_ERR("number of columns for unique key is too high\n");
+		return -1;
+	}
+
+	if(_un > 0)
+	{
+		/* Query error */
+		if(db_unixodbc_update(_h, _k, 0, _v, _k + _un,
+						_v + _un, _un, _n -_un)< 0)
+		{
+			LM_ERR("update failed\n");
+			return -1;
+		}
+		/* No row updated ? */
+		else if (CON_QUERY_RESULT(_h) == SQL_NO_DATA_FOUND)
+		{
+			/* Do an insert then */
+			if(db_unixodbc_insert(_h, _k, _v, _n)< 0)
+			{
+				LM_ERR("insert failed\n");
+				return -1;
+			}
+			LM_DBG("inserted new record in database table\n");
+		} else {
+			LM_DBG("updated record in database table\n");
+		}
+	} else {
+		if(db_unixodbc_insert(_h, _k, _v, _n)< 0)
+		{
+			LM_ERR("direct insert failed\n");
+			return -1;
+		}
+		LM_DBG("directly inserted new record in database table\n");
+	}
+	return 0;
+}
+
 /*
  * Store name of table that will be used by
  * subsequent database functions

+ 7 - 0
modules/db_unixodbc/dbase.h

@@ -92,6 +92,13 @@ const db_key_t* _uk, const db_val_t* _uv, const int _n, const int _un);
 int db_unixodbc_replace(const db1_con_t* handle, const db_key_t* keys, const db_val_t* vals,
 		const int n, const int _un, const int _m);
 
+/*
+ * Just like insert, but update the row if it exists or insert it if not. This function is used when
+ * the odbc replace query is not supported.
+ */
+int db_unixodbc_update_or_insert(const db1_con_t* handle, const db_key_t* keys, const db_val_t* vals,
+		const int n, const int _un, const int _m);
+
 /*
  * Store name of table that will be used by
  * subsequent database functions

+ 30 - 0
modules/db_unixodbc/doc/db_unixodbc_admin.xml

@@ -131,6 +131,25 @@ modparam("db_unixodbc", "use_escape_common", 1)
 </programlisting>
 		</example>
 	</section>
+       <section>
+                <title><varname>replace_query</varname> (int)</title>
+                <para>
+                Tells if the ODBC replace query is supported by the DB odbc driver.
+                </para>
+                <para>
+                <emphasis>
+                        Default value is <quote>1</quote> seconds.
+                </emphasis>
+                </para>
+                <example>
+                <title>Set the <quote>replace_query</quote> parameter</title>
+                <programlisting format="linespecific">
+...
+modparam("db_unixodbc", "replace_query", 0)
+...
+</programlisting>
+                </example>
+        </section>
     </section>
 
 	<section>
@@ -199,6 +218,17 @@ shell>safe_mysqld --user=mysql --socket=/var/lib/mysql/mysql.sock
 	The connector search the socket in /var/lib/mysql/mysql.sock and not 
 	in /tmp/mysql.sock
 	</para>
+
+	<para>
+	REMARK: Oracle ODBC driver doesn't support ODBC query. To disable its usage
+	and replace the replace query by an update or insert query, use the parameter:
+	</para>
+        <programlisting format="linespecific">
+....
+modparam("db_unixodbc", "replace_query", 0)
+....
+</programlisting>
+
 	</section>
 
 	</section>