* Convert rows from PostgreSQL to db API representation */
| 180 | * Convert rows from PostgreSQL to db API representation |
| 181 | */ |
| 182 | int db_postgres_convert_rows(const db_con_t* _h, db_res_t* _r) |
| 183 | { |
| 184 | char **row_buf, *s; |
| 185 | int row, col, len; |
| 186 | |
| 187 | if (!_h || !_r) { |
| 188 | LM_ERR("invalid parameter\n"); |
| 189 | return -1; |
| 190 | } |
| 191 | |
| 192 | if (!RES_ROW_N(_r)) { |
| 193 | LM_DBG("no rows returned from the query\n"); |
| 194 | RES_ROWS(_r) = 0; |
| 195 | return 0; |
| 196 | } |
| 197 | /* Allocate an array of pointers per column to holds the string |
| 198 | * representation */ |
| 199 | len = sizeof(char *) * RES_COL_N(_r); |
| 200 | row_buf = (char**)pkg_malloc(len); |
| 201 | if (!row_buf) { |
| 202 | LM_ERR("no private memory left\n"); |
| 203 | return -1; |
| 204 | } |
| 205 | LM_DBG("allocate for %d columns %d bytes in row buffer at %p\n", |
| 206 | RES_COL_N(_r), len, row_buf); |
| 207 | memset(row_buf, 0, len); |
| 208 | |
| 209 | if (db_allocate_rows( _r, RES_ROW_N(_r))!=0) { |
| 210 | LM_ERR("no private memory left\n"); |
| 211 | return -2; |
| 212 | } |
| 213 | |
| 214 | for(row=RES_LAST_ROW(_r); row<(RES_LAST_ROW(_r)+RES_ROW_N(_r)) ; row++) { |
| 215 | for(col = 0; col < RES_COL_N(_r); col++) { |
| 216 | /* |
| 217 | * The row data pointer returned by PQgetvalue points to |
| 218 | * storage that is part of the PGresult structure. One should |
| 219 | * not modify the data it points to, and one must explicitly |
| 220 | * copy the data into other storage if it is to be used past |
| 221 | * the lifetime of the PGresult structure itself. |
| 222 | */ |
| 223 | |
| 224 | /* |
| 225 | * There's a weird bug (or just weird behavior) in the postgres |
| 226 | * API - if the result is a BLOB (like 'text') and is with |
| 227 | * zero length, we get a pointer to nowhere, which is not |
| 228 | * null-terminated. The fix for this is to check what does the |
| 229 | * DB think about the length and use that as a correction. |
| 230 | */ |
| 231 | if (PQgetisnull(CON_RESULT(_h), row, col) == 0) { |
| 232 | /* not null value */ |
| 233 | if ( (len=PQgetlength(CON_RESULT(_h), row, col))==0 ) { |
| 234 | s=""; |
| 235 | LM_DBG("PQgetvalue(%p,%d,%d)=[], zero len\n", _h, row,col); |
| 236 | } else { |
| 237 | s = PQgetvalue(CON_RESULT(_h), row, col); |
| 238 | LM_DBG("PQgetvalue(%p,%d,%d)=[%.*s]\n", _h, row,col,len,s); |
| 239 | } |
no test coverage detected