[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