El 02/06/14 12:31, Alex Villacís Lasso escribió:
El 31/05/14 01:30, Daniel-Constantin Mierla escribió:
On 30/05/14 22:02, Alex Villacís Lasso wrote:
[...] The xml document retrieval is failing again. Now it is because retrieval
is truncating the MEDIUMTEXT field at 1024 characters:
Adjust the value of parameter:
http://kamailio.org/docs/modules/stable/modules/xcap_server.html#idm7128
Cheers,
Daniel
Did not work. Same symptoms as before.
I see that the file modules/db_unixodbc/connection.h defines a strn structure
with a hardcoded limit of STRN_LEN=1024 bytes per field.
_______________________________________________
SIP Express Router (SER) and Kamailio (OpenSER) - sr-users mailing list
sr-users@lists.sip-router.org
http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-users
I have solved this issue. In order to make it work with unixodbc, I need to apply the attached patch. This patch removes the hardcoded 1024-byte limit for field data that exists in current kamailio-4.1.3. What the patch does is replace the embedded array
in the 'struct strn' with a pointer and a field for allocated size. The patch also introduces three functions for manipulation of the modified 'struct strn'. When the SQLGetData function returns SQL_SUCCESS_WITH_INFO, the SQLSTATE is queried for the "data
truncated" method. Then the rest of the data is fetched in a loop.
Please review this patch for inclusion. The actual detection of the truncation
could need some work.
Also, the ODBC implementation could trip on true binary data (containing
embedded binary zeroes) because it is not binary-safe. Are there scenarios in
which the rest of Kamailio might need to retrieve or store data with a
binary-safe implementation?
diff -ur kamailio-4.1.3-bak/modules/db_unixodbc/connection.c kamailio-4.1.3/modules/db_unixodbc/connection.c
--- kamailio-4.1.3-bak/modules/db_unixodbc/connection.c 2014-06-03 12:01:21.612730787 -0500
+++ kamailio-4.1.3/modules/db_unixodbc/connection.c 2014-06-03 12:03:22.394730696 -0500
@@ -223,3 +223,107 @@
}
while( ret == SQL_SUCCESS );
}
+
+/*
+ * Allocate a new row of cells, without any data
+ */
+strn * db_unixodbc_new_cellrow(size_t ncols)
+{
+ strn * temp_row;
+
+ temp_row = (strn *)pkg_malloc(ncols * sizeof(strn));
+ if (temp_row) memset(temp_row, 0, ncols * sizeof(strn));
+ return temp_row;
+}
+
+/*
+ * Free row of cells and all associated memory
+ */
+void db_unixodbc_free_cellrow(size_t ncols, strn * row)
+{
+ size_t i;
+
+ for (i = 0; i < ncols; i++) {
+ if (row[i].s != NULL) pkg_free(row[i].s);
+ }
+ pkg_free(row);
+}
+
+/*
+ * Load ODBC cell data into a single cell
+ */
+void db_unixodbc_load_cell(const db1_con_t* _h, int colindex, strn * cell)
+{
+ SQLRETURN ret = 0;
+
+ do {
+ SQLLEN indicator;
+ int chunklen;
+ char * s; /* Pointer to available area for next chunk */
+ char * ns;
+
+ if (cell->buflen > 0) {
+ ns = (char *)pkg_realloc(cell->s, cell->buflen + STRN_LEN);
+ if (ns == NULL) {
+ LM_ERR("no memory left\n");
+ return;
+ }
+ cell->s = ns;
+
+ /* Overwrite the previous null terminator */
+ s = cell->s + cell->buflen - 1;
+ chunklen = STRN_LEN + 1;
+ } else {
+ ns = (char *)pkg_malloc(STRN_LEN);
+ if (ns == NULL) {
+ LM_ERR("no memory left\n");
+ return;
+ }
+ cell->s = ns;
+ s = cell->s;
+ chunklen = STRN_LEN;
+ }
+ cell->buflen += STRN_LEN;
+
+ ret = SQLGetData(CON_RESULT(_h), colindex, SQL_C_CHAR,
+ s, chunklen, &indicator);
+ if (ret == SQL_SUCCESS) {
+ if (indicator == SQL_NULL_DATA) strcpy(cell->s, "NULL");
+ } else if (ret == SQL_SUCCESS_WITH_INFO) {
+ SQLINTEGER i = 0;
+ SQLINTEGER native;
+ SQLCHAR state[ 7 ];
+ SQLCHAR text[256];
+ SQLSMALLINT len;
+ SQLRETURN ret2;
+
+ /* Check whether field data was truncated */
+ do
+ {
+ ret2 = SQLGetDiagRec(SQL_HANDLE_STMT, CON_RESULT(_h), ++i, state, &native, text,
+ sizeof(text), &len );
+ if (SQL_SUCCEEDED(ret2)) {
+ if (!strcmp("00000", state)) break;
+ if (strcmp("01004", state) != 0) {
+ /* Not a string truncation */
+ LM_ERR("SQLGetData failed unixodbc: =%s:%ld:%ld:%s\n", state, (long)i,
+ (long)native, text);
+ return;
+ }
+ } else if (ret2 == SQL_NO_DATA) {
+ break;
+ } else {
+ /* Failed to get diagnostics */
+ LM_ERR("SQLGetData failed, failed to get diagnostics (ret2=%d i=%d)\n",
+ ret2, i);
+ return;
+ }
+ }
+ while( ret2 == SQL_SUCCESS );
+ } else {
+ LM_ERR("SQLGetData failed\n");
+ }
+ } while (ret == SQL_SUCCESS_WITH_INFO);
+}
+
+
diff -ur kamailio-4.1.3-bak/modules/db_unixodbc/connection.h kamailio-4.1.3/modules/db_unixodbc/connection.h
--- kamailio-4.1.3-bak/modules/db_unixodbc/connection.h 2014-06-03 12:01:21.612730787 -0500
+++ kamailio-4.1.3/modules/db_unixodbc/connection.h 2014-06-03 12:00:42.893730815 -0500
@@ -47,7 +47,8 @@
typedef struct strn
{
- char s[STRN_LEN];
+ unsigned int buflen;
+ char *s;
} strn;
@@ -90,4 +91,19 @@
void db_unixodbc_extract_error(const char *fn, const SQLHANDLE handle, const SQLSMALLINT type, char* stret);
+/*
+ * Allocate a new row of cells, without any data
+ */
+strn * db_unixodbc_new_cellrow(size_t ncols);
+
+/*
+ * Free row of cells and all associated memory
+ */
+void db_unixodbc_free_cellrow(size_t ncols, strn * row);
+
+/*
+ * Load ODBC cell data into a single cell
+ */
+void db_unixodbc_load_cell(const db1_con_t* _h, int colindex, strn * cell);
+
#endif /* MY_CON_H */
diff -ur kamailio-4.1.3-bak/modules/db_unixodbc/dbase.c kamailio-4.1.3/modules/db_unixodbc/dbase.c
--- kamailio-4.1.3-bak/modules/db_unixodbc/dbase.c 2014-06-03 12:01:21.616730787 -0500
+++ kamailio-4.1.3/modules/db_unixodbc/dbase.c 2014-06-03 12:00:42.899730815 -0500
@@ -321,18 +321,10 @@
SQLNumResultCols(CON_RESULT(_h), (SQLSMALLINT *)&columns);
- /* Allocate a temporary row */
- temp_row = (strn*)pkg_malloc( columns*sizeof(strn) );
- if(!temp_row) {
- LM_ERR("no private memory left\n");
- return -1;
- }
-
/* Now fetch nrows at most */
len = sizeof(db_row_t) * nrows;
RES_ROWS(*_r) = (struct db_row*)pkg_malloc(len);
if (!RES_ROWS(*_r)) {
- pkg_free(temp_row);
LM_ERR("no memory left\n");
return -5;
}
@@ -340,20 +332,20 @@
LM_DBG("Now fetching %i rows at most\n", nrows);
while(SQL_SUCCEEDED(ret = SQLFetch(CON_RESULT(_h)))) {
+ /* Allocate a temporary row */
+ temp_row = db_unixodbc_new_cellrow(columns);
+ if (!temp_row) {
+ LM_ERR("no private memory left\n");
+ pkg_free(RES_ROWS(*_r));
+ pkg_free(*_r);
+ *_r = 0;
+ return -1;
+ }
+
LM_DBG("fetching %d columns for row %d...\n",columns, row_n);
for(i=0; i < columns; i++) {
- SQLLEN indicator;
LM_DBG("fetching column %d\n",i);
-
- ret = SQLGetData(CON_RESULT(_h), i+1, SQL_C_CHAR,
- temp_row[i].s, STRN_LEN, &indicator);
-
- if (SQL_SUCCEEDED(ret)) {
- if (indicator == SQL_NULL_DATA)
- strcpy(temp_row[i].s, "NULL");
- } else {
- LM_ERR("SQLGetData failed\n");
- }
+ db_unixodbc_load_cell(_h, i+1, temp_row + i);
}
LM_DBG("got temp_row at %p\n", temp_row);
@@ -361,22 +353,23 @@
if (db_unixodbc_list_insert(&rowstart, &rows, columns, temp_row) < 0) {
LM_ERR("SQL result row insert failed\n");
pkg_free(RES_ROWS(*_r));
- pkg_free(temp_row);
- temp_row= NULL;
+ db_unixodbc_free_cellrow(columns, temp_row);
pkg_free(*_r);
*_r = 0;
return -5;
}
+ /* Free temporary row data */
+ LM_DBG("freeing temp_row at %p\n", temp_row);
+ db_unixodbc_free_cellrow(columns, temp_row);
+ temp_row = NULL;
+
row_n++;
if (row_n == nrows) {
break;
}
}
- /* Free temporary row data */
- LM_DBG("freeing temp_row at %p\n", temp_row);
- pkg_free(temp_row);
CON_ROW(_h) = NULL;
RES_ROW_N(*_r) = row_n;
diff -ur kamailio-4.1.3-bak/modules/db_unixodbc/res.c kamailio-4.1.3/modules/db_unixodbc/res.c
--- kamailio-4.1.3-bak/modules/db_unixodbc/res.c 2014-06-03 12:01:21.619730786 -0500
+++ kamailio-4.1.3/modules/db_unixodbc/res.c 2014-06-03 12:00:42.904730814 -0500
@@ -178,38 +178,31 @@
}
SQLNumResultCols(CON_RESULT(_h), (SQLSMALLINT *)&columns);
- temp_row = (strn*)pkg_malloc( columns*sizeof(strn) );
- if(!temp_row) {
- LM_ERR("no private memory left\n");
- return -1;
- }
while(SQL_SUCCEEDED(ret = SQLFetch(CON_RESULT(_h))))
{
+ temp_row = db_unixodbc_new_cellrow(columns);
+ if (!temp_row) {
+ LM_ERR("no private memory left\n");
+ return -1;
+ }
+
for(i=0; i < columns; i++)
{
- SQLLEN indicator;
- ret = SQLGetData(CON_RESULT(_h), i+1, SQL_C_CHAR,
- temp_row[i].s, STRN_LEN, &indicator);
- if (SQL_SUCCEEDED(ret)) {
- if (indicator == SQL_NULL_DATA)
- strcpy(temp_row[i].s, "NULL");
- }
- else {
- LM_ERR("SQLGetData failed\n");
- }
+ db_unixodbc_load_cell(_h, i+1, temp_row + i);
}
if (db_unixodbc_list_insert(&rowstart, &rows, columns, temp_row) < 0) {
LM_ERR("insert failed\n");
- pkg_free(temp_row);
- temp_row= NULL;
+ db_unixodbc_free_cellrow(columns, temp_row);
return -5;
}
RES_ROW_N(_r)++;
+
+ /* free temporary row data */
+ db_unixodbc_free_cellrow(columns, temp_row);
+ temp_row = NULL;
}
- /* free temporary row data */
- pkg_free(temp_row);
CON_ROW(_h) = NULL;
if (!RES_ROW_N(_r)) {
_______________________________________________
SIP Express Router (SER) and Kamailio (OpenSER) - sr-users mailing list
sr-users@lists.sip-router.org
http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-users