From: Wez Furlong Date: Sun, 6 Feb 2005 22:11:12 +0000 (+0000) Subject: add a caller_frees parameter to get_col() to allow drivers that need X-Git-Tag: RELEASE_0_2~54 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ccf0a6a5579721aac7398a486d946f985f9b0a08;p=php add a caller_frees parameter to get_col() to allow drivers that need to allocate data on demand to do so without worrying about cleaning it up. Spec out how LOB parameters are returned. --- diff --git a/ext/pdo/pdo_stmt.c b/ext/pdo/pdo_stmt.c index 83bbec7e96..b88c43ee06 100755 --- a/ext/pdo/pdo_stmt.c +++ b/ext/pdo/pdo_stmt.c @@ -33,6 +33,7 @@ #include "php_pdo_driver.h" #include "php_pdo_int.h" #include "zend_exceptions.h" +#include "php_memory_streams.h" #if COMPILE_DL_PDO /* {{{ content from zend_arg_defs.c: @@ -369,13 +370,14 @@ static inline void fetch_value(pdo_stmt_t *stmt, zval *dest, int colno TSRMLS_DC struct pdo_column_data *col; char *value = NULL; unsigned long value_len = 0; + int caller_frees = 0; col = &stmt->columns[colno]; value = NULL; value_len = 0; - stmt->methods->get_col(stmt, colno, &value, &value_len TSRMLS_CC); + stmt->methods->get_col(stmt, colno, &value, &value_len, &caller_frees TSRMLS_CC); switch (col->param_type) { case PDO_PARAM_INT: @@ -395,14 +397,47 @@ static inline void fetch_value(pdo_stmt_t *stmt, zval *dest, int colno TSRMLS_DC break; case PDO_PARAM_LOB: + if (value == NULL) { + ZVAL_NULL(dest); + } else if (value_len == 0) { + php_stream_to_zval((php_stream*)value, dest); + } else { + /* they gave us a string, but LOBs are represented as streams in PDO */ + php_stream *stm; +#ifdef TEMP_STREAM_TAKE_BUFFER + if (caller_frees) { + stm = php_stream_memory_open(TEMP_STREAM_TAKE_BUFFER, value, value_len); + if (stm) { + caller_frees = 0; + } + } else +#endif + { + stm = php_stream_memory_open(TEMP_STREAM_READONLY, value, value_len); + } + if (stm) { + php_stream_to_zval(stm, dest); + } else { + ZVAL_NULL(dest); + } + } + break; + case PDO_PARAM_STR: if (value && !(value_len == 0 && stmt->dbh->oracle_nulls)) { - ZVAL_STRINGL(dest, value, value_len, 1); + ZVAL_STRINGL(dest, value, value_len, !caller_frees); + if (caller_frees) { + caller_frees = 0; + } break; } default: ZVAL_NULL(dest); } + + if (caller_frees && value) { + efree(value); + } } static int do_fetch_common(pdo_stmt_t *stmt, enum pdo_fetch_orientation ori, diff --git a/ext/pdo/php_pdo_driver.h b/ext/pdo/php_pdo_driver.h index b054611328..4644ff8c63 100755 --- a/ext/pdo/php_pdo_driver.h +++ b/ext/pdo/php_pdo_driver.h @@ -35,14 +35,29 @@ struct pdo_bound_param_data; # define FALSE 0 #endif -#define PDO_DRIVER_API 20050205 +#define PDO_DRIVER_API 20050206 enum pdo_param_type { PDO_PARAM_NULL, - PDO_PARAM_INT, /* int as in long, the php native int type */ + + /* int as in long (the php native int type). + * If you mark a column as an int, PDO expects get_col to return + * a pointer to a long */ + PDO_PARAM_INT, + + /* get_col ptr should point to start of the string buffer */ PDO_PARAM_STR, + + /* get_col: when len is 0 ptr should point to a php_stream *, + * otherwise it should behave like a string. Indicate a NULL field + * value by setting the ptr to NULL */ PDO_PARAM_LOB, + + /* get_col: will expect the ptr to point to a new PDOStatement object handle, + * but this isn't wired up yet */ PDO_PARAM_STMT, /* hierarchical result set */ + + /* get_col ptr should point to a zend_bool */ PDO_PARAM_BOOL }; @@ -275,8 +290,10 @@ typedef int (*pdo_stmt_describe_col_func)(pdo_stmt_t *stmt, int colno TSRMLS_DC) /* retrieves pointer and size of the value for a column. * Note that PDO expects the driver to manage the lifetime of this data; * it will copy the value into a zval on behalf of the script. + * If the driver sets caller_frees, ptr should point to emalloc'd memory + * and PDO will free it as soon as it is done using it. */ -typedef int (*pdo_stmt_get_col_data_func)(pdo_stmt_t *stmt, int colno, char **ptr, unsigned long *len TSRMLS_DC); +typedef int (*pdo_stmt_get_col_data_func)(pdo_stmt_t *stmt, int colno, char **ptr, unsigned long *len, int *caller_frees TSRMLS_DC); /* hook for bound params */ enum pdo_param_event {