Module: sip-router
Branch: janakj/postgres
Commit: be78aade192c328f6c5e567334340ccb24a94484
URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=be78aad…
Author: Henning Westerholt <henning.westerholt(a)1und1.de>
Committer: Henning Westerholt <henning.westerholt(a)1und1.de>
Date: Fri Oct 17 08:01:23 2008 +0000
- docs extension: explain fetch_result functionality better to prevent errors
because of wrong usage, found from Juha Heinanen
git-svn-id: https://openser.svn.sourceforge.net/svnroot/openser/trunk@5088 689a6050-402a-0410-94f2-e92a70836424
---
modules/db_postgres/km_dbase.c | 10 +++++++++-
1 files changed, 9 insertions(+), 1 deletions(-)
diff --git a/modules/db_postgres/km_dbase.c b/modules/db_postgres/km_dbase.c
index 38bc36f..4ef3343 100644
--- a/modules/db_postgres/km_dbase.c
+++ b/modules/db_postgres/km_dbase.c
@@ -161,7 +161,15 @@ static int db_postgres_submit_query(const db_con_t* _con, const str* _s)
/*!
- * \brief Gets a partial result set
+ * \brief Gets a partial result set, fetch rows from a result
+ *
+ * Gets a partial result set, fetch a number of rows from a database result.
+ * This function initialize the given result structure on the first run, and
+ * fetches the nrows number of rows. On subsequenting runs, it uses the
+ * existing result and fetches more rows, until it reaches the end of the
+ * result set. Because of this the result needs to be null in the first
+ * invocation of the function. If the number of wanted rows is zero, the
+ * function returns anything with a result of zero.
* \param _con database connection
* \param _res result set
* \param nrows number of fetches rows
Module: sip-router
Branch: janakj/postgres
Commit: 26a598b38bb3d9018145e44b54c8ae09145f8616
URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=26a598b…
Author: Henning Westerholt <henning.westerholt(a)1und1.de>
Committer: Henning Westerholt <henning.westerholt(a)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;
}
Module: sip-router
Branch: janakj/postgres
Commit: f09596d32a99108f6c34f5fa3641be3dd6470b24
URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=f09596d…
Author: Henning Westerholt <henning.westerholt(a)1und1.de>
Committer: Henning Westerholt <henning.westerholt(a)1und1.de>
Date: Mon Nov 24 17:38:46 2008 +0000
- fix memory leak in db_postgres module related to BLOBs (also caused an
abort in a assertion when DBG_QM_MALLOC memory manager is used)
- PQunescapeBytea is used for BLOBs, this allocates new memory, which could
not freed from us later in pkg_free in the DB core
- thus we need to allocate new memory for this datatype, copy the string and
free the postgres result after that
- small comment fix
git-svn-id: https://openser.svn.sourceforge.net/svnroot/openser/trunk@5250 689a6050-402a-0410-94f2-e92a70836424
---
modules/db_postgres/km_val.c | 30 ++++++++++++++++++++++--------
1 files changed, 22 insertions(+), 8 deletions(-)
diff --git a/modules/db_postgres/km_val.c b/modules/db_postgres/km_val.c
index d5a3115..9b7d12b 100644
--- a/modules/db_postgres/km_val.c
+++ b/modules/db_postgres/km_val.c
@@ -61,6 +61,7 @@
int db_postgres_str2val(const db_type_t _t, db_val_t* _v, const char* _s, const int _l)
{
static str dummy_string = {"", 0};
+ char *tmp_s;
if (!_v) {
LM_ERR("invalid parameter value\n");
@@ -159,19 +160,32 @@ int db_postgres_str2val(const db_type_t _t, db_val_t* _v, const char* _s, const
case DB_BLOB:
LM_DBG("converting BLOB [%.*s]\n", _l, _s);
- /* PQunescapeBytea: Converts a string representation of binary data
- * into binary data - the reverse of PQescapeBytea.
- * This is needed when retrieving bytea data in text format,
- * but not when retrieving it in binary format.
+ /*
+ * The string is stored in new allocated memory, which we could
+ * not free later thus we need to copy it to some new memory here.
*/
- VAL_BLOB(_v).s = (char*)PQunescapeBytea((unsigned char*)_s,
- (size_t*)(void*)&(VAL_BLOB(_v).len) );
+ tmp_s = (char*)PQunescapeBytea((unsigned char*)_s, (size_t*)(void*)&(VAL_BLOB(_v).len));
+ if(tmp_s==NULL) {
+ LM_ERR("PQunescapeBytea failed\n");
+ return -7;
+ }
+ VAL_BLOB(_v).s = pkg_malloc(VAL_BLOB(_v).len);
+ if (VAL_BLOB(_v).s == NULL) {
+ LM_ERR("no private memory left\n");
+ PQfreemem(tmp_s);
+ return -8;
+ }
+ LM_DBG("allocate %d bytes memory for BLOB at %p", VAL_BLOB(_v).len, VAL_BLOB(_v).s);
+ memcpy(VAL_BLOB(_v).s, tmp_s, VAL_BLOB(_v).len);
+ PQfreemem(tmp_s);
+
VAL_TYPE(_v) = DB_BLOB;
VAL_FREE(_v) = 1;
+
LM_DBG("got blob len %d\n", _l);
return 0;
}
- return -7;
+ return -9;
}
@@ -314,7 +328,7 @@ int db_postgres_val2str(const db_con_t* _con, const db_val_t* _v, char* _s, int*
(size_t)l, (size_t*)&tmp_len);
if(tmp_s==NULL)
{
- LM_ERR("PQescapeBytea failed\n");
+ LM_ERR("PQescapeByteaConn failed\n");
return -9;
}
if (tmp_len > *_len) {