Sfoglia il codice sorgente

- change behaviour of db_str2val, this now copy strings
- this change was necessary because in some circumstances the memory that is
returned from the database driver is used by some other means too fast,
causes crashed or wrong results later on, this bug is timing related
- this means for mysql and unixodbc that the performance will be decreased a
bit, postgres already copied the string, so here nothing change
- add a new function to DB core API, db_val2str that, usable to convert
numerical values to a string, and common things like NULL values conversion,
parameter checks
- convert mysql, postgres and unixodbc module to use this new function
- convert postgres function to use the core db_str2val function, the copying
is now done at a different place, cleanup the code somewhat
- remove unnecessary assignment if a NULL value is encountered in postgres
- TODO: fix NULL handling and double copying that is done now for unixodbc


git-svn-id: https://openser.svn.sourceforge.net/svnroot/openser/trunk@5359 689a6050-402a-0410-94f2-e92a70836424

Henning Westerholt 16 anni fa
parent
commit
f9200735c6
2 ha cambiato i file con 152 aggiunte e 27 eliminazioni
  1. 138 27
      lib/srdb1/db_val.c
  2. 14 0
      lib/srdb1/db_val.h

+ 138 - 27
lib/srdb1/db_val.c

@@ -23,6 +23,9 @@
 
 
 #include "db_ut.h"
 #include "db_ut.h"
 
 
+#include <stdio.h>
+#include <time.h>
+
 /*!
 /*!
  * \brief Convert a str to a db value, copy strings
  * \brief Convert a str to a db value, copy strings
  *
  *
@@ -102,37 +105,145 @@ int db_str2val(const db_type_t _t, db_val_t* _v, const char* _s, const int _l)
 		}
 		}
 		break;
 		break;
 
 
-		case DB_STRING:
-			LM_DBG("converting STRING [%s]\n", _s);
-			VAL_STRING(_v) = _s;
-			VAL_TYPE(_v) = DB_STRING;
+	case DB_STRING:
+		LM_DBG("converting STRING [%s]\n", _s);
+		/*
+		 * Normally we could just use the string returned from the DB library,
+		 * as its usually not immediately freed after the free_result. But as
+		 * there exists some corner cases where this string gets invalid, we
+		 * need to copy it here.
+		 */
+		VAL_STRING(_v) = pkg_malloc(_l + 1);
+		if (VAL_STRING(_v) == NULL) {
+			LM_ERR("no private memory left\n");
+			return -6;
+		}
+		LM_DBG("allocate %d bytes memory for STRING at %p", _l + 1, VAL_STRING(_v));
+		strncpy((char*)VAL_STRING(_v), _s, _l);
+		((char*)VAL_STRING(_v))[_l] = '\0';
+		VAL_TYPE(_v) = DB_STRING;
+		VAL_FREE(_v) = 1;
+		return 0;
+
+	case DB_STR:
+		LM_DBG("converting STR [%.*s]\n", _l, _s);
+		/* same problem as DB_STRING.. */
+		VAL_STR(_v).s = pkg_malloc(_l);
+		if (VAL_STR(_v).s == NULL) {
+			LM_ERR("no private memory left\n");
+			return -7;
+		}
+		LM_DBG("allocate %d bytes memory for STR at %p", _l, VAL_STR(_v).s);
+		strncpy(VAL_STR(_v).s, _s, _l);
+		VAL_STR(_v).len = _l;
+		VAL_TYPE(_v) = DB_STR;
+		VAL_FREE(_v) = 1;
+		return 0;
+
+	case DB_DATETIME:
+		LM_DBG("converting DATETIME [%s]\n", _s);
+		if (db_str2time(_s, &VAL_TIME(_v)) < 0) {
+			LM_ERR("error while converting datetime value from string\n");
+			return -8;
+		} else {
+			VAL_TYPE(_v) = DB_DATETIME;
 			return 0;
 			return 0;
+		}
+		break;
+
+	case DB_BLOB:
+		LM_DBG("converting BLOB [%.*s]\n", _l, _s);
+		/* same problem as DB_STRING.. */
+		VAL_BLOB(_v).s = pkg_malloc(_l);
+		if (VAL_BLOB(_v).s == NULL) {
+			LM_ERR("no private memory left\n");
+			return -9;
+		}
+		LM_DBG("allocate %d bytes memory for BLOB at %p", _l, VAL_BLOB(_v).s);
+		strncpy(VAL_BLOB(_v).s, _s, _l);
+		VAL_BLOB(_v).len = _l;
+		VAL_TYPE(_v) = DB_BLOB;
+		VAL_FREE(_v) = 1;
+		return 0;
+	}
+	return -10;
+}
 
 
-		case DB_STR:
-			LM_DBG("converting STR [%.*s]\n", _l, _s);
-			VAL_STR(_v).s = (char*)_s;
-			VAL_STR(_v).len = _l;
-			VAL_TYPE(_v) = DB_STR;
+
+/*!
+ * \brief Convert a numerical value to a string
+ *
+ * Convert a numerical value to a string, used when converting result from a query.
+ * Implement common functionality needed from the databases, does parameter checking.
+ * \param _c database connection
+ * \param _v source value
+ * \param _s target string
+ * \param _len target string length
+ * \return 0 on success, negative on error, 1 if value must be converted by other means
+ */
+int db_val2str(const db_con_t* _c, const db_val_t* _v, char* _s, int* _len)
+{
+	if (!_c || !_v || !_s || !_len || !*_len) {
+		LM_ERR("invalid parameter value\n");
+		return -1;
+	}
+
+	if (VAL_NULL(_v)) {
+		if (*_len < sizeof("NULL")) {
+			LM_ERR("buffer too small\n");
+			return -1;
+		}
+		*_len = snprintf(_s, *_len, "NULL");
+		return 0;
+	}
+	
+	switch(VAL_TYPE(_v)) {
+	case DB_INT:
+		if (db_int2str(VAL_INT(_v), _s, _len) < 0) {
+			LM_ERR("error while converting string to int\n");
+			return -2;
+		} else {
 			return 0;
 			return 0;
+		}
+		break;
 
 
-		case DB_DATETIME:
-			LM_DBG("converting DATETIME [%s]\n", _s);
-			if (db_str2time(_s, &VAL_TIME(_v)) < 0) {
-				LM_ERR("error while converting datetime value from string\n");
-				return -6;
-			} else {
-				VAL_TYPE(_v) = DB_DATETIME;
-				return 0;
-			}
-			break;
-
-		case DB_BLOB:
-			LM_DBG("converting BLOB [%.*s]\n", _l, _s);
-			VAL_BLOB(_v).s = (char*)_s;
-			VAL_BLOB(_v).len = _l;
-			VAL_TYPE(_v) = DB_BLOB;
+	case DB_BIGINT:
+		if (db_longlong2str(VAL_BIGINT(_v), _s, _len) < 0) {
+			LM_ERR("error while converting string to big int\n");
+			return -3;
+		} else {
 			return 0;
 			return 0;
+		}
+		break;
+
+	case DB_BITMAP:
+		if (db_int2str(VAL_BITMAP(_v), _s, _len) < 0) {
+			LM_ERR("error while converting string to int\n");
+			return -4;
+		} else {
+			return 0;
+		}
+		break;
+
+	case DB_DOUBLE:
+		if (db_double2str(VAL_DOUBLE(_v), _s, _len) < 0) {
+			LM_ERR("error while converting string to double\n");
+			return -5;
+		} else {
+			return 0;
+		}
+		break;
+
+	case DB_DATETIME:
+		if (db_time2str(VAL_TIME(_v), _s, _len) < 0) {
+			LM_ERR("failed to convert string to time_t\n");
+			return -8;
+		} else {
+			return 0;
+		}
+		break;
+
+	default:
+		return 1;
 	}
 	}
-	return -7;
 }
 }
-

+ 14 - 0
lib/srdb1/db_val.h

@@ -37,6 +37,7 @@
 #ifndef DB_VAL_H
 #ifndef DB_VAL_H
 #define DB_VAL_H
 #define DB_VAL_H
 
 
+#include "db_con.h"
 #include <time.h>
 #include <time.h>
 #include "../str.h"
 #include "../str.h"
 
 
@@ -179,4 +180,17 @@ typedef struct {
 int db_str2val(const db_type_t _t, db_val_t* _v, const char* _s, const int _l);
 int db_str2val(const db_type_t _t, db_val_t* _v, const char* _s, const int _l);
 
 
 
 
+/*!
+ * \brief Convert a numerical value to a string
+ *
+ * Convert a numerical value to a string, used when converting result from a query.
+ * Implement common functionality needed from the databases, does parameter checking.
+ * \param _c database connection
+ * \param _v source value
+ * \param _s target string
+ * \param _len target string length
+ * \return 0 on success, negative on error, 1 if value must be converted by other means
+ */
+int db_val2str(const db_con_t* _c, const db_val_t* _v, char* _s, int* _len);
+
 #endif /* DB_VAL_H */
 #endif /* DB_VAL_H */