[SR-Dev] git:janakj/postgres: - fix postgres NULL value behaviour: as in postgres a NULL value is

Jan Janak jan at iptel.org
Wed Feb 18 01:26:22 CET 2009


Module: sip-router
Branch: janakj/postgres
Commit: 26a598b38bb3d9018145e44b54c8ae09145f8616
URL:    http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=26a598b38bb3d9018145e44b54c8ae09145f8616

Author: Henning Westerholt <henning.westerholt at 1und1.de>
Committer: Henning Westerholt <henning.westerholt at 1und1.de>
Date:   Thu Nov 13 16:35:55 2008 +0000

- fix postgres NULL value behaviour: as in postgres a NULL value is
  represented from an empty string (just as a empty value), we need
  to check it with PQgetisnull
- as further processing steps assume that we use the mysql behaviour,
  were a NULL value is represented from a NULL string, we need to
  simulate this here
- better would be to get rid of this row_buf completely, and to use
  just some function parameter to signalize NULLs to the later steps
- synchronize db_postgres_val2str behaviour to the mysql and unixodbc
  modules, fail also in the NULL case when the buffer is to small
- reported from Matteo Piazza, matteo dot piazza at trentinonetwork dot it


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

---

 modules/db_postgres/km_res.c |   41 ++++++++++++++++++++++++++++-------------
 modules/db_postgres/km_val.c |    8 ++++++++
 2 files changed, 36 insertions(+), 13 deletions(-)

diff --git a/modules/db_postgres/km_res.c b/modules/db_postgres/km_res.c
index e493439..4207405 100644
--- a/modules/db_postgres/km_res.c
+++ b/modules/db_postgres/km_res.c
@@ -235,15 +235,21 @@ int db_postgres_convert_rows(const db_con_t* _h, db_res_t* _r)
 
 	for(row = RES_LAST_ROW(_r); row < (RES_LAST_ROW(_r) + RES_ROW_N(_r)); row++) {
 		for(col = 0; col < RES_COL_N(_r); col++) {
-				/*
-				 * The row data pointer returned by PQgetvalue points to storage
-				 * that is part of the PGresult structure. One should not modify
-				 * the data it points to, and one must explicitly copy the data
-				 * into other storage if it is to be used past the lifetime of
-				 * the PGresult structure itself.
-				 */
-				s = PQgetvalue(CON_RESULT(_h), row, col);
-				LM_DBG("PQgetvalue(%p,%d,%d)=[%s]\n", _h, row, col, s);
+			/*
+			 * The row data pointer returned by PQgetvalue points to storage
+			 * that is part of the PGresult structure. One should not modify
+			 * the data it points to, and one must explicitly copy the data
+			 * into other storage if it is to be used past the lifetime of
+			 * the PGresult structure itself.
+			 */
+			s = PQgetvalue(CON_RESULT(_h), row, col);
+			LM_DBG("PQgetvalue(%p,%d,%d)=[%s]\n", _h, row, col, s);
+			/*
+			 * A empty string can be a NULL value, or just an empty string.
+			 * This differs from the mysql behaviour, that further processing
+			 * steps expect. So we need to simulate this here unfortunally.
+			 */
+			if (PQgetisnull(CON_RESULT(_h), row, col) == 0) {
 				len = strlen(s);
 				row_buf[col] = pkg_malloc(len+1);
 				if (!row_buf[col]) {
@@ -252,10 +258,12 @@ int db_postgres_convert_rows(const db_con_t* _h, db_res_t* _r)
 				}
 				memset(row_buf[col], 0, len+1);
 				LM_DBG("allocated %d bytes for row_buf[%d] at %p\n", len, col, row_buf[col]);
-
 				strncpy(row_buf[col], s, len);
 				LM_DBG("[%d][%d] Column[%.*s]=[%s]\n",
 					row, col, RES_NAMES(_r)[col]->len, RES_NAMES(_r)[col]->s, row_buf[col]);
+			} else {
+				s = NULL;
+			}
 		}
 
 		/* ASSERT: row_buf contains an entire row in strings */
@@ -296,7 +304,8 @@ int db_postgres_convert_rows(const db_con_t* _h, db_res_t* _r)
 					break;
 				default:
 					LM_DBG("freeing row_buf[%d] at %p\n", col, row_buf[col]);
-					pkg_free(row_buf[col]);
+					/* because it can contain NULL */
+					if(row_buf[col]) pkg_free(row_buf[col]); 
 			}
 			/*
 			 * The following housekeeping may not be technically required, but it
@@ -329,7 +338,7 @@ int db_postgres_convert_rows(const db_con_t* _h, db_res_t* _r)
 int db_postgres_convert_row(const db_con_t* _h, db_res_t* _r, db_row_t* _row,
 		char **row_buf)
 {
-	int col, len;
+	int col, len, col_len;
 
 	if (!_h || !_r || !_row)  {
 		LM_ERR("invalid parameter value\n");
@@ -356,9 +365,15 @@ int db_postgres_convert_row(const db_con_t* _h, db_res_t* _r, db_row_t* _row,
 
 	/* For each column in the row */
 	for(col = 0; col < ROW_N(_row); col++) {
+		/* because it can contain NULL */
+		if (!row_buf[col]) {
+			col_len = 0;
+		} else {
+			col_len = strlen(row_buf[col]);
+		}
 		/* Convert the string representation into the value representation */
 		if (db_postgres_str2val(RES_TYPES(_r)[col], &(ROW_VALUES(_row)[col]),
-		row_buf[col], strlen(row_buf[col])) < 0) {
+		row_buf[col], col_len) < 0) {
 			LM_ERR("failed to convert value\n");
 			LM_DBG("free row at %pn", _row);
 			db_free_row(_row);
diff --git a/modules/db_postgres/km_val.c b/modules/db_postgres/km_val.c
index 8024d52..d5a3115 100644
--- a/modules/db_postgres/km_val.c
+++ b/modules/db_postgres/km_val.c
@@ -66,6 +66,10 @@ int db_postgres_str2val(const db_type_t _t, db_val_t* _v, const char* _s, const
 		LM_ERR("invalid parameter value\n");
 	}
 
+	/*
+	 * We implemented the mysql behaviour in the db_postgres_convert_rows function,
+	 * so a NULL string is a NULL value, otherwise its an empty value
+	 */
 	if (!_s) {
 		memset(_v, 0, sizeof(db_val_t));
 		/* Initialize the string pointers to a dummy empty
@@ -195,6 +199,10 @@ int db_postgres_val2str(const db_con_t* _con, const db_val_t* _v, char* _s, int*
 	}
 
 	if (VAL_NULL(_v)) {
+		if (*_len < sizeof("NULL")) {
+			LM_ERR("buffer too small\n");
+			return -1;
+		}
 		*_len = snprintf(_s, *_len, "NULL");
 		return 0;
 	}




More information about the sr-dev mailing list