On Sat, 14 Mar 2020 at 02:34, Nick Kew <n...@apache.org> wrote: > Isn't your most obvious fix simply to allocate your row > from your choice of pool before the first get_row?
That wouldn't work. Here's the start of the dbd_oracle_get_row function in the apr_dbd_oracle driver: static int dbd_oracle_get_row(apr_pool_t *pool, apr_dbd_results_t *res, apr_dbd_row_t **rowp, int rownum) { apr_dbd_row_t *row = *rowp; apr_dbd_t *sql = res->handle; int_errorcode; if (row == NULL) { row = apr_palloc(pool, sizeof(apr_dbd_row_t)); *rowp = row; row->res = res; /* Oracle starts counting at 1 according to the docs */ row->n = res->seek ? rownum : 1; row->pool = pool; } else { if (res->seek) { row->n = rownum; } else { ++row->n; } } so as well as allocating a apr_dbd_row_t if one does not exist it is also setting up some of the members. If I allocated it myself from a different pool it would not be initialised. Compare, though, with the equivalent section of the dbd_mysql_get_row function from the apr_dbd_mysql driver: if (ret == 0) { if (!*row) { *row = apr_palloc(pool, sizeof(apr_dbd_row_t)); } (*row)->row = r; (*row)->res = res; (*row)->len = mysql_fetch_lengths(res->res); } else { apr_pool_cleanup_run(res->pool, res->res, free_result); } return ret; so with that in mind I thought I'd compare what apr_dbd_get_entry does in each of those two drivers. In the Oracle driver the a sufficient fragment is: default: buf = apr_pstrndup(row->pool, val->buf.sval, val->len); break; } return (const char*) buf; } so the Oracle driver is returning a copy of the value, allocated from a pool remember from the call to apr_dbd_get_row. The equivalent from the MySQL driver: if (row->res->statement) { bind = &row->res->bind[n]; if (mysql_stmt_fetch_column(row->res->statement, bind, n, 0) != 0) { return NULL; } if (*bind->is_null) { return NULL; } else { return bind->buffer; } } else { return row->row[n]; } return NULL; so this appears to be returning a pointer into something linked to the apr_dbd_row_t which is presumably re-used for each row fetched as long as the apr_dbd_row_t remains allocated. In fact this seems much easier for the library user to control - want long lifetime values from apr_dbd_get_entry then reset the apr_dbd_row_t pointer to NULL each iteration and it will achieve that. Want to keep memory consumption down then leave the pointer alone and the memory will be re-used. So maybe the real issue is that the two drivers have interpreted what is required differently. There is nothing in the Doxygen documentation for apr_dbd_get_entry about the lifetime of the value returned. Is there guidance or a standard for driver writers elsewhere?