summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS4
-rw-r--r--UPGRADING4
-rw-r--r--UPGRADING.INTERNALS22
-rw-r--r--ext/pdo/pdo_stmt.c162
-rw-r--r--ext/pdo/php_pdo_driver.h39
-rw-r--r--ext/pdo/tests/debug_emulated_prepares.phpt6
-rw-r--r--ext/pdo_dblib/dblib_stmt.c69
-rw-r--r--ext/pdo_firebird/firebird_driver.c1
-rw-r--r--ext/pdo_firebird/firebird_statement.c166
-rw-r--r--ext/pdo_firebird/php_pdo_firebird_int.h3
-rw-r--r--ext/pdo_mysql/mysql_statement.c42
-rw-r--r--ext/pdo_mysql/tests/pdo_mysql_stmt_blobs.phpt10
-rw-r--r--ext/pdo_mysql/tests/pdo_mysql_stmt_getcolumnmeta.phpt27
-rw-r--r--ext/pdo_oci/oci_statement.c34
-rw-r--r--ext/pdo_odbc/odbc_stmt.c102
-rw-r--r--ext/pdo_pgsql/pgsql_statement.c160
-rw-r--r--ext/pdo_pgsql/php_pdo_pgsql_int.h2
-rw-r--r--ext/pdo_pgsql/tests/bug62498.phpt36
-rw-r--r--ext/pdo_pgsql/tests/debug_emulated_prepares.phpt6
-rw-r--r--ext/pdo_sqlite/sqlite_statement.c26
-rw-r--r--ext/pdo_sqlite/tests/bug79664.phpt4
-rw-r--r--ext/pdo_sqlite/tests/debugdumpparams_001.phpt6
22 files changed, 347 insertions, 584 deletions
diff --git a/NEWS b/NEWS
index 32712a85ca..dc4862c291 100644
--- a/NEWS
+++ b/NEWS
@@ -21,6 +21,10 @@ PHP NEWS
- OpenSSL:
. Bump minimal OpenSSL version to 1.0.2. (Jakub Zelenka)
+- PDO:
+ . Fixed bug #40913 (PDO_MYSQL: PDO::PARAM_LOB does not bind to a stream for
+ fetching a BLOB). (Nikita)
+
- PSpell:
. Convert resource<pspell> to object \PSpell. (Sara)
. Convert resource<pspell config> to object \PSPellConfig. (Sara)
diff --git a/UPGRADING b/UPGRADING
index 8625303aac..9b80b702a3 100644
--- a/UPGRADING
+++ b/UPGRADING
@@ -42,6 +42,10 @@ PHP 8.1 UPGRADE NOTES
- PDO:
. PDO::ATTR_STRINGIFY_FETCHES now also stringifies values of type bool to
"0" or "1". Previously booleans were not stringified.
+ . Calling bindColumn() with PDO::PARAM_LOB (and assuming stringification is
+ not enabled) will now consistently bind a stream result, as documented.
+ Previously the result would be either a stream or a string depending on the
+ used database driver and the time the binding is performed.
- PDO MySQL:
. Integers and floats in result sets will now be returned using native PHP
diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS
index c1ddd4fad2..0f51f91cc2 100644
--- a/UPGRADING.INTERNALS
+++ b/UPGRADING.INTERNALS
@@ -25,3 +25,25 @@ PHP 8.1 INTERNALS UPGRADE NOTES
configuration. If the an algorithm doesn't make use of any
additional configuration, the argument is to be marked with
ZEND_ATTRIBUTE_UNUSED.
+
+ b. ext/pdo
+ - The "preparer" callback now accepts a zend_string* instead of
+ char* + size_t pair the query string. Similarly, the query_string and
+ active_query_string members of pdo_stmt_t are now zend_string*.
+ - The way in which drivers provide results has changed: Previously,
+ the "describer" callback populated the "pdo_type" member in the
+ pdo_column_data structure, and the "get_col" callback then had to return
+ pointers to data of appropriate type.
+
+ In PHP 8.1, the "describer" callback no longer determines the pdo_type
+ (and this member has been removed from pdo_column_data). Instead, the
+ "get_col" callback accepts a zval pointer that may be populated with a
+ value of arbitrary type. This gives drivers more flexibility in
+ determining result types (e.g. based on whether a specific integer fits
+ the PHP integer type) and avoid awkward juggling of temporary buffers.
+
+ As the "describer" no longer determines pdo_type, the "get_column_meta"
+ function is now responsible for providing this information for use by
+ getColumnMeta(). The type provided here does not need to match the type
+ returned by get_col (in fact no corresponding type might exist, e.g. for
+ floats). It should be the closest logical equivalent for the column type.
diff --git a/ext/pdo/pdo_stmt.c b/ext/pdo/pdo_stmt.c
index e1c51ef29a..18116b80fb 100644
--- a/ext/pdo/pdo_stmt.c
+++ b/ext/pdo/pdo_stmt.c
@@ -486,14 +486,8 @@ PHP_METHOD(PDOStatement, execute)
}
/* }}} */
-static inline void fetch_value(pdo_stmt_t *stmt, zval *dest, int colno, int *type_override) /* {{{ */
+static inline void fetch_value(pdo_stmt_t *stmt, zval *dest, int colno, enum pdo_param_type *type_override) /* {{{ */
{
- struct pdo_column_data *col;
- char *value = NULL;
- size_t value_len = 0;
- int caller_frees = 0;
- int type, new_type;
-
if (colno < 0) {
zend_value_error("Column index must be greater than or equal to 0");
ZVAL_NULL(dest);
@@ -506,126 +500,62 @@ static inline void fetch_value(pdo_stmt_t *stmt, zval *dest, int colno, int *typ
return;
}
- col = &stmt->columns[colno];
- type = PDO_PARAM_TYPE(col->param_type);
- new_type = type_override ? (int)PDO_PARAM_TYPE(*type_override) : type;
-
- value = NULL;
- value_len = 0;
+ ZVAL_NULL(dest);
+ stmt->methods->get_col(stmt, colno, dest, type_override);
- stmt->methods->get_col(stmt, colno, &value, &value_len, &caller_frees);
-
- switch (type) {
- case PDO_PARAM_ZVAL:
- if (value && value_len == sizeof(zval)) {
- ZVAL_COPY_VALUE(dest, (zval *)value);
-
- if (Z_TYPE_P(dest) == IS_STRING && Z_STRLEN_P(dest) == 0
- && stmt->dbh->oracle_nulls == PDO_NULL_EMPTY_STRING) {
- zval_ptr_dtor_str(dest);
- ZVAL_NULL(dest);
- }
- } else {
- ZVAL_NULL(dest);
- }
+ if (Z_TYPE_P(dest) == IS_STRING && Z_STRLEN_P(dest) == 0
+ && stmt->dbh->oracle_nulls == PDO_NULL_EMPTY_STRING) {
+ zval_ptr_dtor_str(dest);
+ ZVAL_NULL(dest);
+ }
- if (Z_TYPE_P(dest) == IS_NULL) {
- type = new_type;
- }
- break;
+ /* If stringification is requested, override with PDO_PARAM_STR. */
+ enum pdo_param_type pdo_param_str = PDO_PARAM_STR;
+ if (stmt->dbh->stringify) {
+ type_override = &pdo_param_str;
+ }
- case PDO_PARAM_INT:
- if (value && value_len == sizeof(zend_long)) {
- ZVAL_LONG(dest, *(zend_long*)value);
+ if (type_override && Z_TYPE_P(dest) != IS_NULL) {
+ switch (*type_override) {
+ case PDO_PARAM_INT:
+ convert_to_long(dest);
break;
- }
- ZVAL_NULL(dest);
- break;
-
- case PDO_PARAM_BOOL:
- if (value && value_len == sizeof(zend_bool)) {
- ZVAL_BOOL(dest, *(zend_bool*)value);
+ case PDO_PARAM_BOOL:
+ convert_to_boolean(dest);
break;
- }
- ZVAL_NULL(dest);
- break;
-
- case PDO_PARAM_LOB:
- if (value == NULL) {
- ZVAL_NULL(dest);
- } else if (value_len == 0) {
- /* Warning, empty strings need to be passed as stream */
- if (stmt->dbh->stringify || new_type == PDO_PARAM_STR) {
- zend_string *buf;
- buf = php_stream_copy_to_mem((php_stream*)value, PHP_STREAM_COPY_ALL, 0);
- if (buf == NULL) {
+ case PDO_PARAM_STR:
+ if (Z_TYPE_P(dest) == IS_FALSE) {
+ /* Return "0" rather than "", because this is what database drivers that
+ * don't have a dedicated boolean type would return. */
+ zval_ptr_dtor_nogc(dest);
+ ZVAL_INTERNED_STR(dest, ZSTR_CHAR('0'));
+ } else if (Z_TYPE_P(dest) == IS_RESOURCE) {
+ /* Convert LOB stream to string */
+ php_stream *stream;
+ php_stream_from_zval_no_verify(stream, dest);
+ zend_string *str = php_stream_copy_to_mem(stream, PHP_STREAM_COPY_ALL, 0);
+ zval_ptr_dtor_nogc(dest);
+ if (str == NULL) {
ZVAL_EMPTY_STRING(dest);
} else {
- ZVAL_STR(dest, buf);
+ ZVAL_STR(dest, str);
}
- php_stream_close((php_stream*)value);
- } else {
- php_stream_to_zval((php_stream*)value, dest);
- }
- } else if (!stmt->dbh->stringify && new_type != PDO_PARAM_STR) {
- /* they gave us a string, but LOBs are represented as streams in PDO */
- zend_string *str = zend_string_init(value, value_len, 0);
- php_stream *stream = php_stream_memory_open(TEMP_STREAM_READONLY, str);
- if (stream) {
- php_stream_to_zval(stream, dest);
} else {
- ZVAL_NULL(dest);
+ convert_to_string(dest);
}
- zend_string_release(str);
- } else {
- ZVAL_STRINGL(dest, value, value_len);
- }
- break;
-
- case PDO_PARAM_STR:
- if (value && !(value_len == 0 && stmt->dbh->oracle_nulls == PDO_NULL_EMPTY_STRING)) {
- ZVAL_STRINGL(dest, value, value_len);
- break;
- }
- default:
- ZVAL_NULL(dest);
- }
-
- if (type != new_type) {
- switch (new_type) {
- case PDO_PARAM_INT:
- convert_to_long_ex(dest);
- break;
- case PDO_PARAM_BOOL:
- convert_to_boolean_ex(dest);
- break;
- case PDO_PARAM_STR:
- convert_to_string_ex(dest);
break;
case PDO_PARAM_NULL:
- convert_to_null_ex(dest);
+ convert_to_null(dest);
break;
- default:
- ;
- }
- }
-
- if (caller_frees && value) {
- efree(value);
- }
-
- if (stmt->dbh->stringify) {
- switch (Z_TYPE_P(dest)) {
- case IS_FALSE:
- /* Return "0" rather than "", because this is what database drivers that
- * don't have a dedicated boolean type would return. */
- zval_ptr_dtor_nogc(dest);
- ZVAL_INTERNED_STR(dest, ZSTR_CHAR('0'));
+ case PDO_PARAM_LOB:
+ if (Z_TYPE_P(dest) == IS_STRING) {
+ php_stream *stream =
+ php_stream_memory_open(TEMP_STREAM_READONLY, Z_STR_P(dest));
+ zval_ptr_dtor_str(dest);
+ php_stream_to_zval(stream, dest);
+ }
break;
- case IS_TRUE:
- case IS_LONG:
- case IS_DOUBLE:
- convert_to_string(dest);
+ default:
break;
}
}
@@ -673,7 +603,7 @@ static bool do_fetch_common(pdo_stmt_t *stmt, enum pdo_fetch_orientation ori, ze
zval_ptr_dtor(Z_REFVAL(param->parameter));
/* set new value */
- fetch_value(stmt, Z_REFVAL(param->parameter), param->paramno, (int *)&param->param_type);
+ fetch_value(stmt, Z_REFVAL(param->parameter), param->paramno, &param->param_type);
/* TODO: some smart thing that avoids duplicating the value in the
* general loop below. For now, if you're binding output columns,
@@ -1761,10 +1691,6 @@ PHP_METHOD(PDOStatement, getColumnMeta)
add_assoc_str(return_value, "name", zend_string_copy(col->name));
add_assoc_long(return_value, "len", col->maxlen); /* FIXME: unsigned ? */
add_assoc_long(return_value, "precision", col->precision);
- if (col->param_type != PDO_PARAM_ZVAL) {
- /* if param_type is PDO_PARAM_ZVAL the driver has to provide correct data */
- add_assoc_long(return_value, "pdo_type", col->param_type);
- }
}
/* }}} */
diff --git a/ext/pdo/php_pdo_driver.h b/ext/pdo/php_pdo_driver.h
index da53c1a3b9..ea78eb187d 100644
--- a/ext/pdo/php_pdo_driver.h
+++ b/ext/pdo/php_pdo_driver.h
@@ -46,32 +46,14 @@ PDO_API char *php_pdo_int64_to_str(pdo_int64_t i64);
enum pdo_param_type {
PDO_PARAM_NULL,
-
- /* 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_BOOL,
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 */
+ /* get_col: Not supported (yet?) */
PDO_PARAM_STMT, /* hierarchical result set */
- /* get_col ptr should point to a zend_bool */
- PDO_PARAM_BOOL,
-
- /* get_col ptr should point to a zval*
- and the driver is responsible for adding correct type information to get_column_meta()
- */
- PDO_PARAM_ZVAL,
-
/* magic flag to denote a parameter as being input/output */
PDO_PARAM_INPUT_OUTPUT = 0x80000000,
@@ -343,13 +325,13 @@ typedef int (*pdo_stmt_fetch_func)(pdo_stmt_t *stmt,
* Driver should populate stmt->columns[colno] with appropriate info */
typedef int (*pdo_stmt_describe_col_func)(pdo_stmt_t *stmt, int colno);
-/* 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, size_t *len, int *caller_frees);
+/* Retrieves zval value of a column. If type is non-NULL, then this specifies the type which
+ * the user requested through bindColumn(). The driver does not need to check this argument,
+ * as PDO will perform any necessary conversions itself. However, it might be used to fetch
+ * a value more efficiently into the final type, or make the behavior dependent on the requested
+ * type. */
+typedef int (*pdo_stmt_get_col_data_func)(
+ pdo_stmt_t *stmt, int colno, zval *result, enum pdo_param_type *type);
/* hook for bound params */
enum pdo_param_event {
@@ -382,8 +364,8 @@ typedef int (*pdo_stmt_get_attr_func)(pdo_stmt_t *stmt, zend_long attr, zval *va
* name => the column name
* len => the length/size of the column
* precision => precision of the column
- * pdo_type => an integer, one of the PDO_PARAM_XXX values
*
+ * pdo_type => an integer, one of the PDO_PARAM_XXX values
* scale => the floating point scale
* table => the table for that column
* type => a string representation of the type, mapped to the PHP equivalent type name
@@ -541,7 +523,6 @@ struct pdo_column_data {
zend_string *name;
size_t maxlen;
zend_ulong precision;
- enum pdo_param_type param_type;
};
/* describes a bound parameter */
diff --git a/ext/pdo/tests/debug_emulated_prepares.phpt b/ext/pdo/tests/debug_emulated_prepares.phpt
index f347c7e4ea..e981f7db39 100644
--- a/ext/pdo/tests/debug_emulated_prepares.phpt
+++ b/ext/pdo/tests/debug_emulated_prepares.phpt
@@ -47,17 +47,17 @@ Key: Name: [5] :bool
paramno=-1
name=[5] ":bool"
is_param=1
-param_type=5
+param_type=1
Key: Name: [4] :int
paramno=-1
name=[4] ":int"
is_param=1
-param_type=1
+param_type=2
Key: Name: [7] :string
paramno=-1
name=[7] ":string"
is_param=1
-param_type=2
+param_type=3
Key: Name: [5] :null
paramno=-1
name=[5] ":null"
diff --git a/ext/pdo_dblib/dblib_stmt.c b/ext/pdo_dblib/dblib_stmt.c
index 0dca4c79cf..03e69a4ac0 100644
--- a/ext/pdo_dblib/dblib_stmt.c
+++ b/ext/pdo_dblib/dblib_stmt.c
@@ -251,7 +251,6 @@ static int pdo_dblib_stmt_describe(pdo_stmt_t *stmt, int colno)
}
col->maxlen = dbcollen(H->link, colno+1);
- col->param_type = PDO_PARAM_ZVAL;
return 1;
}
@@ -304,14 +303,12 @@ static int pdo_dblib_stmt_should_stringify_col(pdo_stmt_t *stmt, int coltype)
return 0;
}
-static void pdo_dblib_stmt_stringify_col(int coltype, LPBYTE data, DBINT data_len, zval **ptr)
+static void pdo_dblib_stmt_stringify_col(int coltype, LPBYTE data, DBINT data_len, zval *zv)
{
DBCHAR *tmp_data;
- DBINT tmp_data_len;
- zval *zv;
/* FIXME: We allocate more than we need here */
- tmp_data_len = 32 + (2 * (data_len));
+ DBINT tmp_data_len = 32 + (2 * (data_len));
switch (coltype) {
case SQLDATETIME:
@@ -326,7 +323,6 @@ static void pdo_dblib_stmt_stringify_col(int coltype, LPBYTE data, DBINT data_le
tmp_data = emalloc(tmp_data_len);
data_len = dbconvert(NULL, coltype, data, data_len, SQLCHAR, (LPBYTE) tmp_data, tmp_data_len);
- zv = emalloc(sizeof(zval));
if (data_len > 0) {
/* to prevent overflows, tmp_data_len is provided as a dest len for dbconvert()
* this code previously passed a dest len of -1
@@ -342,12 +338,9 @@ static void pdo_dblib_stmt_stringify_col(int coltype, LPBYTE data, DBINT data_le
}
efree(tmp_data);
-
- *ptr = zv;
}
-static int pdo_dblib_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr,
- zend_ulong *len, int *caller_frees)
+static int pdo_dblib_stmt_get_col(pdo_stmt_t *stmt, int colno, zval *zv, enum pdo_param_type *type)
{
pdo_dblib_stmt *S = (pdo_dblib_stmt*)stmt->driver_data;
@@ -357,7 +350,6 @@ static int pdo_dblib_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr,
LPBYTE data;
DBCHAR *tmp_data;
DBINT data_len, tmp_data_len;
- zval *zv = NULL;
coltype = dbcoltype(H->link, colno+1);
data = dbdata(H->link, colno+1);
@@ -365,10 +357,8 @@ static int pdo_dblib_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr,
if (data_len != 0 || data != NULL) {
if (pdo_dblib_stmt_should_stringify_col(stmt, coltype) && dbwillconvert(coltype, SQLCHAR)) {
- pdo_dblib_stmt_stringify_col(coltype, data, data_len, &zv);
- }
-
- if (!zv) {
+ pdo_dblib_stmt_stringify_col(coltype, data, data_len, zv);
+ } else {
switch (coltype) {
case SQLCHAR:
case SQLVARCHAR:
@@ -382,7 +372,6 @@ static int pdo_dblib_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr,
case SQLVARBINARY:
case SQLBINARY:
case SQLIMAGE: {
- zv = emalloc(sizeof(zval));
ZVAL_STRINGL(zv, (DBCHAR *) data, data_len);
break;
@@ -407,50 +396,31 @@ static int pdo_dblib_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr,
#endif
);
- zv = emalloc(sizeof(zval));
ZVAL_STRINGL(zv, tmp_data, dl);
efree(tmp_data);
break;
}
- case SQLFLT4: {
- zv = emalloc(sizeof(zval));
+ case SQLFLT4:
ZVAL_DOUBLE(zv, *(DBFLT4 *) data);
-
break;
- }
- case SQLFLT8: {
- zv = emalloc(sizeof(zval));
+ case SQLFLT8:
ZVAL_DOUBLE(zv, *(DBFLT8 *) data);
-
break;
- }
- case SQLINT8: {
- zv = emalloc(sizeof(zval));
+ case SQLINT8:
ZVAL_LONG(zv, *(DBBIGINT *) data);
-
break;
- }
- case SQLINT4: {
- zv = emalloc(sizeof(zval));
+ case SQLINT4:
ZVAL_LONG(zv, *(DBINT *) data);
-
break;
- }
- case SQLINT2: {
- zv = emalloc(sizeof(zval));
+ case SQLINT2:
ZVAL_LONG(zv, *(DBSMALLINT *) data);
-
break;
- }
case SQLINT1:
- case SQLBIT: {
- zv = emalloc(sizeof(zval));
+ case SQLBIT:
ZVAL_LONG(zv, *(DBTINYINT *) data);
-
break;
- }
case SQLDECIMAL:
case SQLNUMERIC:
case SQLMONEY:
@@ -458,10 +428,7 @@ static int pdo_dblib_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr,
case SQLMONEYN: {
DBFLT8 float_value;
dbconvert(NULL, coltype, data, 8, SQLFLT8, (LPBYTE) &float_value, -1);
-
- zv = emalloc(sizeof(zval));
ZVAL_DOUBLE(zv, float_value);
-
break;
}
@@ -472,12 +439,10 @@ static int pdo_dblib_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr,
tmp_data = safe_emalloc(tmp_data_len, sizeof(char), 1);
data_len = dbconvert(NULL, SQLUNIQUE, data, data_len, SQLCHAR, (LPBYTE) tmp_data, tmp_data_len);
php_strtoupper(tmp_data, data_len);
- zv = emalloc(sizeof(zval));
ZVAL_STRINGL(zv, tmp_data, data_len);
efree(tmp_data);
} else {
/* 16-byte binary representation */
- zv = emalloc(sizeof(zval));
ZVAL_STRINGL(zv, (DBCHAR *) data, 16);
}
break;
@@ -485,7 +450,7 @@ static int pdo_dblib_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr,
default: {
if (dbwillconvert(coltype, SQLCHAR)) {
- pdo_dblib_stmt_stringify_col(coltype, data, data_len, &zv);
+ pdo_dblib_stmt_stringify_col(coltype, data, data_len, zv);
}
break;
@@ -494,16 +459,6 @@ static int pdo_dblib_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr,
}
}
- if (zv != NULL) {
- *ptr = (char*)zv;
- *len = sizeof(zval);
- } else {
- *ptr = NULL;
- *len = 0;
- }
-
- *caller_frees = 1;
-
return 1;
}
diff --git a/ext/pdo_firebird/firebird_driver.c b/ext/pdo_firebird/firebird_driver.c
index 171dbef6e0..54aaefed6c 100644
--- a/ext/pdo_firebird/firebird_driver.c
+++ b/ext/pdo_firebird/firebird_driver.c
@@ -532,7 +532,6 @@ static int firebird_handle_preparer(pdo_dbh_t *dbh, zend_string *sql, /* {{{ */
S = ecalloc(1, sizeof(*S)-sizeof(XSQLDA) + XSQLDA_LENGTH(num_sqlda.sqld));
S->H = H;
S->stmt = s;
- S->fetch_buf = ecalloc(1,sizeof(char*) * num_sqlda.sqld);
S->out_sqlda.version = PDO_FB_SQLDA_VERSION;
S->out_sqlda.sqln = stmt->column_count = num_sqlda.sqld;
S->named_params = np;
diff --git a/ext/pdo_firebird/firebird_statement.c b/ext/pdo_firebird/firebird_statement.c
index e80e26a2f8..c0ce2618ac 100644
--- a/ext/pdo_firebird/firebird_statement.c
+++ b/ext/pdo_firebird/firebird_statement.c
@@ -49,7 +49,7 @@ static void free_sqlda(XSQLDA const *sqlda) /* {{{ */
static int firebird_stmt_dtor(pdo_stmt_t *stmt) /* {{{ */
{
pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
- int result = 1, i;
+ int result = 1;
/* release the statement */
if (isc_dsql_free_statement(S->H->isc_status, &S->stmt, DSQL_drop)) {
@@ -57,14 +57,6 @@ static int firebird_stmt_dtor(pdo_stmt_t *stmt) /* {{{ */
result = 0;
}
- /* clean up the fetch buffers if they have been used */
- for (i = 0; i < S->out_sqlda.sqld; ++i) {
- if (S->fetch_buf[i]) {
- efree(S->fetch_buf[i]);
- }
- }
- efree(S->fetch_buf);
-
zend_hash_destroy(S->named_params);
FREE_HASHTABLE(S->named_params);
@@ -219,8 +211,18 @@ static int firebird_stmt_describe(pdo_stmt_t *stmt, int colno) /* {{{ */
memmove(cp, var->aliasname, var->aliasname_length);
*(cp+var->aliasname_length) = '\0';
+ return 1;
+}
+/* }}} */
+
+static int firebird_stmt_get_column_meta(pdo_stmt_t *stmt, zend_long colno, zval *return_value)
+{
+ pdo_firebird_stmt *S = (pdo_firebird_stmt *) stmt->driver_data;
+ XSQLVAR *var = &S->out_sqlda.sqlvar[colno];
+
+ enum pdo_param_type param_type;
if (var->sqlscale < 0) {
- col->param_type = PDO_PARAM_STR;
+ param_type = PDO_PARAM_STR;
} else {
switch (var->sqltype & ~1) {
case SQL_SHORT:
@@ -228,31 +230,25 @@ static int firebird_stmt_describe(pdo_stmt_t *stmt, int colno) /* {{{ */
#if SIZEOF_ZEND_LONG >= 8
case SQL_INT64:
#endif
- col->param_type = PDO_PARAM_INT;
+ param_type = PDO_PARAM_INT;
break;
#ifdef SQL_BOOLEAN
case SQL_BOOLEAN:
- col->param_type = PDO_PARAM_BOOL;
+ param_type = PDO_PARAM_BOOL;
break;
#endif
default:
- col->param_type = PDO_PARAM_STR;
+ param_type = PDO_PARAM_STR;
break;
}
}
+ add_assoc_long(return_value, "pdo_type", param_type);
return 1;
}
-/* }}} */
-
-#define FETCH_BUF(buf,type,len,lenvar) ((buf) = (buf) ? (buf) : \
- emalloc((len) ? (len * sizeof(type)) : ((*(unsigned long*)lenvar) = sizeof(type))))
-
-#define CHAR_BUF_LEN 24
/* fetch a blob into a fetch buffer */
-static int firebird_fetch_blob(pdo_stmt_t *stmt, int colno, char **ptr, /* {{{ */
- zend_ulong *len, ISC_QUAD *blob_id)
+static int firebird_fetch_blob(pdo_stmt_t *stmt, int colno, zval *result, ISC_QUAD *blob_id)
{
pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
pdo_firebird_db_handle *H = S->H;
@@ -260,7 +256,8 @@ static int firebird_fetch_blob(pdo_stmt_t *stmt, int colno, char **ptr, /* {{{ *
char const bl_item = isc_info_blob_total_length;
char bl_info[20];
unsigned short i;
- int result = *len = 0;
+ int retval = 0;
+ size_t len = 0;
if (isc_open_blob(H->isc_status, &H->db, &H->tr, &blobh, blob_id)) {
RECORD_ERROR(stmt);
@@ -287,7 +284,7 @@ static int firebird_fetch_blob(pdo_stmt_t *stmt, int colno, char **ptr, /* {{{ *
item_len = (unsigned short) isc_vax_integer(&bl_info[i], 2);
if (item == isc_info_blob_total_length) {
- *len = isc_vax_integer(&bl_info[i+2], item_len);
+ len = isc_vax_integer(&bl_info[i+2], item_len);
break;
}
i += item_len+2;
@@ -295,49 +292,47 @@ static int firebird_fetch_blob(pdo_stmt_t *stmt, int colno, char **ptr, /* {{{ *
/* we've found the blob's length, now fetch! */
- if (*len) {
+ if (len) {
zend_ulong cur_len;
unsigned short seg_len;
ISC_STATUS stat;
+ zend_string *str = zend_string_alloc(len, 0);
- *ptr = S->fetch_buf[colno] = erealloc(S->fetch_buf[colno], *len+1);
-
- for (cur_len = stat = 0; (!stat || stat == isc_segment) && cur_len < *len; cur_len += seg_len) {
+ for (cur_len = stat = 0; (!stat || stat == isc_segment) && cur_len < len; cur_len += seg_len) {
- unsigned short chunk_size = (*len-cur_len) > USHRT_MAX ? USHRT_MAX
- : (unsigned short)(*len-cur_len);
+ unsigned short chunk_size = (len - cur_len) > USHRT_MAX ? USHRT_MAX
+ : (unsigned short)(len - cur_len);
- stat = isc_get_segment(H->isc_status, &blobh, &seg_len, chunk_size, &(*ptr)[cur_len]);
+ stat = isc_get_segment(H->isc_status, &blobh, &seg_len, chunk_size, ZSTR_VAL(str) + cur_len);
}
- (*ptr)[*len++] = '\0';
+ ZSTR_VAL(str)[len] = '\0';
+ ZVAL_STR(result, str);
if (H->isc_status[0] == 1 && (stat != 0 && stat != isc_segstr_eof && stat != isc_segment)) {
H->last_app_error = "Error reading from BLOB";
goto fetch_blob_end;
}
}
- result = 1;
+ retval = 1;
fetch_blob_end:
if (isc_close_blob(H->isc_status, &blobh)) {
RECORD_ERROR(stmt);
return 0;
}
- return result;
+ return retval;
}
/* }}} */
-static int firebird_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, /* {{{ */
- zend_ulong *len, int *caller_frees)
+static int firebird_stmt_get_col(
+ pdo_stmt_t *stmt, int colno, zval *result, enum pdo_param_type *type)
{
pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
XSQLVAR const *var = &S->out_sqlda.sqlvar[colno];
if (*var->sqlind == -1) {
- /* A NULL value */
- *ptr = NULL;
- *len = 0;
+ ZVAL_NULL(result);
} else {
if (var->sqlscale < 0) {
static ISC_INT64 const scales[] = { 1, 10, 100, 1000,
@@ -358,6 +353,7 @@ static int firebird_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, /* {{
LL_LIT(1000000000000000000)
};
ISC_INT64 n, f = scales[-var->sqlscale];
+ zend_string *str;
switch (var->sqltype & ~1) {
case SQL_SHORT:
@@ -372,65 +368,53 @@ static int firebird_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, /* {{
EMPTY_SWITCH_DEFAULT_CASE()
}
- *ptr = FETCH_BUF(S->fetch_buf[colno], char, CHAR_BUF_LEN, NULL);
-
if ((var->sqltype & ~1) == SQL_DOUBLE) {
- *len = slprintf(*ptr, CHAR_BUF_LEN, "%.*F", -var->sqlscale, *(double*)var->sqldata);
+ str = zend_strpprintf(0, "%.*F", -var->sqlscale, *(double*)var->sqldata);
} else if (n >= 0) {
- *len = slprintf(*ptr, CHAR_BUF_LEN, "%" LL_MASK "d.%0*" LL_MASK "d",
+ str = zend_strpprintf(0, "%" LL_MASK "d.%0*" LL_MASK "d",
n / f, -var->sqlscale, n % f);
} else if (n <= -f) {
- *len = slprintf(*ptr, CHAR_BUF_LEN, "%" LL_MASK "d.%0*" LL_MASK "d",
+ str = zend_strpprintf(0, "%" LL_MASK "d.%0*" LL_MASK "d",
n / f, -var->sqlscale, -n % f);
} else {
- *len = slprintf(*ptr, CHAR_BUF_LEN, "-0.%0*" LL_MASK "d", -var->sqlscale, -n % f);
+ str = zend_strpprintf(0, "-0.%0*" LL_MASK "d", -var->sqlscale, -n % f);
}
+ ZVAL_STR(result, str);
} else {
switch (var->sqltype & ~1) {
struct tm t;
char *fmt;
case SQL_VARYING:
- *ptr = &var->sqldata[2];
- *len = *(short*)var->sqldata;
+ ZVAL_STRINGL_FAST(result, &var->sqldata[2], *(short*)var->sqldata);
break;
case SQL_TEXT:
- *ptr = var->sqldata;
- *len = var->sqllen;
+ ZVAL_STRINGL_FAST(result, var->sqldata, var->sqllen);
break;
case SQL_SHORT:
- *len = sizeof(zend_long);
- *ptr = FETCH_BUF(S->fetch_buf[colno], zend_long, 1, NULL);
- *(zend_long *)*ptr = *(short*)var->sqldata;
+ ZVAL_LONG(result, *(short*)var->sqldata);
break;
case SQL_LONG:
- *len = sizeof(zend_long);
- *ptr = FETCH_BUF(S->fetch_buf[colno], zend_long, 1, NULL);
- *(zend_long *)*ptr = *(ISC_LONG*)var->sqldata;
+ ZVAL_LONG(result, *(ISC_LONG*)var->sqldata);
break;
case SQL_INT64:
#if SIZEOF_ZEND_LONG >= 8
- *len = sizeof(zend_long);
- *ptr = FETCH_BUF(S->fetch_buf[colno], zend_long, 1, NULL);
- *(zend_long *)*ptr = *(ISC_INT64*)var->sqldata;
+ ZVAL_LONG(result, *(ISC_INT64*)var->sqldata);
#else
- *ptr = FETCH_BUF(S->fetch_buf[colno], char, CHAR_BUF_LEN, NULL);
- *len = slprintf(*ptr, CHAR_BUF_LEN, "%" LL_MASK "d", *(ISC_INT64*)var->sqldata);
+ ZVAL_STR(result, zend_strpprintf(0, "%" LL_MASK "d", *(ISC_INT64*)var->sqldata));
#endif
break;
case SQL_FLOAT:
- *ptr = FETCH_BUF(S->fetch_buf[colno], char, CHAR_BUF_LEN, NULL);
- *len = slprintf(*ptr, CHAR_BUF_LEN, "%F", *(float*)var->sqldata);
+ /* TODO: Why is this not returned as the native type? */
+ ZVAL_STR(result, zend_strpprintf(0, "%F", *(float*)var->sqldata));
break;
case SQL_DOUBLE:
- *ptr = FETCH_BUF(S->fetch_buf[colno], char, CHAR_BUF_LEN, NULL);
- *len = slprintf(*ptr, CHAR_BUF_LEN, "%F" , *(double*)var->sqldata);
+ /* TODO: Why is this not returned as the native type? */
+ ZVAL_STR(result, zend_strpprintf(0, "%F", *(double*)var->sqldata));
break;
#ifdef SQL_BOOLEAN
case SQL_BOOLEAN:
- *len = sizeof(zend_bool);
- *ptr = FETCH_BUF(S->fetch_buf[colno], zend_bool, 1, NULL);
- *(zend_bool*)*ptr = *(FB_BOOLEAN*)var->sqldata;
+ ZVAL_BOOL(result, *(FB_BOOLEAN*)var->sqldata);
break;
#endif
case SQL_TYPE_DATE:
@@ -446,19 +430,17 @@ static int firebird_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, /* {{
fmt = S->H->timestamp_format ? S->H->timestamp_format : PDO_FB_DEF_TIMESTAMP_FMT;
}
/* convert the timestamp into a string */
- *len = 80;
- *ptr = FETCH_BUF(S->fetch_buf[colno], char, *len, NULL);
- *len = strftime(*ptr, *len, fmt, &t);
+ char buf[80];
+ size_t len = strftime(buf, sizeof(buf), fmt, &t);
+ ZVAL_STRINGL(result, buf, len);
break;
case SQL_BLOB:
- return firebird_fetch_blob(stmt,colno,ptr,len,
- (ISC_QUAD*)var->sqldata);
+ return firebird_fetch_blob(stmt, colno, result, (ISC_QUAD*)var->sqldata);
}
}
}
return 1;
}
-/* }}} */
static int firebird_bind_blob(pdo_stmt_t *stmt, ISC_QUAD *blob_id, zval *param)
{
@@ -550,9 +532,6 @@ static int firebird_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_dat
var = &sqlda->sqlvar[param->paramno];
switch (event_type) {
- char *value;
- zend_ulong value_len;
- int caller_frees;
zval *parameter;
case PDO_PARAM_EVT_ALLOC:
@@ -728,9 +707,6 @@ static int firebird_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_dat
if (param->is_param) {
break;
}
- value = NULL;
- value_len = 0;
- caller_frees = 0;
if (Z_ISREF(param->parameter)) {
parameter = Z_REFVAL(param->parameter);
} else {
@@ -738,37 +714,7 @@ static int firebird_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_dat
}
zval_ptr_dtor(parameter);
ZVAL_NULL(parameter);
-
- if (firebird_stmt_get_col(stmt, param->paramno, &value, &value_len, &caller_frees)) {
- switch (PDO_PARAM_TYPE(param->param_type)) {
- case PDO_PARAM_STR:
- if (value) {
- ZVAL_STRINGL(parameter, value, value_len);
- break;
- }
- case PDO_PARAM_INT:
- if (value) {
- ZVAL_LONG(parameter, *(zend_long*)value);
- break;
- }
- case PDO_PARAM_EVT_NORMALIZE:
- if (!param->is_param) {
- char *s = ZSTR_VAL(param->name);
- while (*s != '\0') {
- *s = toupper(*s);
- s++;
- }
- }
- break;
- default:
- ZVAL_NULL(parameter);
- }
- if (value && caller_frees) {
- efree(value);
- }
- return 1;
- }
- return 0;
+ return firebird_stmt_get_col(stmt, param->paramno, parameter, NULL);
default:
;
}
@@ -843,7 +789,7 @@ const struct pdo_stmt_methods firebird_stmt_methods = { /* {{{ */
firebird_stmt_param_hook,
firebird_stmt_set_attribute,
firebird_stmt_get_attribute,
- NULL, /* get_column_meta_func */
+ firebird_stmt_get_column_meta,
NULL, /* next_rowset_func */
firebird_stmt_cursor_closer
};
diff --git a/ext/pdo_firebird/php_pdo_firebird_int.h b/ext/pdo_firebird/php_pdo_firebird_int.h
index 70a895b4b9..f0ba0d08b4 100644
--- a/ext/pdo_firebird/php_pdo_firebird_int.h
+++ b/ext/pdo_firebird/php_pdo_firebird_int.h
@@ -113,9 +113,6 @@ typedef struct {
/* the named params that were converted to ?'s by the driver */
HashTable *named_params;
- /* allocated space to convert fields values to other types */
- char **fetch_buf;
-
/* the input SQLDA */
XSQLDA *in_sqlda;
diff --git a/ext/pdo_mysql/mysql_statement.c b/ext/pdo_mysql/mysql_statement.c
index f2ba5aa95a..e1f6c6ff95 100644
--- a/ext/pdo_mysql/mysql_statement.c
+++ b/ext/pdo_mysql/mysql_statement.c
@@ -658,18 +658,13 @@ static int pdo_mysql_stmt_describe(pdo_stmt_t *stmt, int colno) /* {{{ */
cols[i].precision = S->fields[i].decimals;
cols[i].maxlen = S->fields[i].length;
-
-#ifdef PDO_USE_MYSQLND
- cols[i].param_type = PDO_PARAM_ZVAL;
-#else
- cols[i].param_type = PDO_PARAM_STR;
-#endif
}
PDO_DBG_RETURN(1);
}
/* }}} */
-static int pdo_mysql_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, size_t *len, int *caller_frees) /* {{{ */
+static int pdo_mysql_stmt_get_col(
+ pdo_stmt_t *stmt, int colno, zval *result, enum pdo_param_type *type) /* {{{ */
{
pdo_mysql_stmt *S = (pdo_mysql_stmt*)stmt->driver_data;
@@ -685,38 +680,33 @@ static int pdo_mysql_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, size_
}
#ifdef PDO_USE_MYSQLND
if (S->stmt) {
- Z_TRY_ADDREF(S->stmt->data->result_bind[colno].zv);
- *ptr = (char*)&S->stmt->data->result_bind[colno].zv;
+ ZVAL_COPY(result, &S->stmt->data->result_bind[colno].zv);
} else {
- Z_TRY_ADDREF(S->current_row[colno]);
- *ptr = (char*)&S->current_row[colno];
+ ZVAL_COPY(result, &S->current_row[colno]);
}
- *len = sizeof(zval);
PDO_DBG_RETURN(1);
#else
if (S->stmt) {
if (S->out_null[colno]) {
- *ptr = NULL;
- *len = 0;
PDO_DBG_RETURN(1);
}
- *ptr = S->bound_result[colno].buffer;
- if (S->out_length[colno] > S->bound_result[colno].buffer_length) {
+
+ size_t length = S->out_length[colno];
+ if (length > S->bound_result[colno].buffer_length) {
/* mysql lied about the column width */
strcpy(stmt->error_code, "01004"); /* truncated */
- S->out_length[colno] = S->bound_result[colno].buffer_length;
- *len = S->out_length[colno];
- PDO_DBG_RETURN(0);
+ length = S->out_length[colno] = S->bound_result[colno].buffer_length;
}
- *len = S->out_length[colno];
+ ZVAL_STRINGL_FAST(result, S->bound_result[colno].buffer, length);
PDO_DBG_RETURN(1);
}
if (S->current_data == NULL) {
PDO_DBG_RETURN(0);
}
- *ptr = S->current_data[colno];
- *len = S->current_lengths[colno];
+ if (S->current_data[colno]) {
+ ZVAL_STRINGL_FAST(result, S->current_data[colno], S->current_lengths[colno]);
+ }
PDO_DBG_RETURN(1);
#endif
} /* }}} */
@@ -815,7 +805,7 @@ static int pdo_mysql_stmt_col_meta(pdo_stmt_t *stmt, zend_long colno, zval *retu
add_assoc_string(return_value, "native_type", str);
}
-#ifdef PDO_USE_MYSQLND
+ enum pdo_param_type param_type;
switch (F->type) {
case MYSQL_TYPE_BIT:
case MYSQL_TYPE_YEAR:
@@ -826,13 +816,13 @@ static int pdo_mysql_stmt_col_meta(pdo_stmt_t *stmt, zend_long colno, zval *retu
#if SIZEOF_ZEND_LONG==8
case MYSQL_TYPE_LONGLONG:
#endif
- add_assoc_long(return_value, "pdo_type", PDO_PARAM_INT);
+ param_type = PDO_PARAM_INT;
break;
default:
- add_assoc_long(return_value, "pdo_type", PDO_PARAM_STR);
+ param_type = PDO_PARAM_STR;
break;
}
-#endif
+ add_assoc_long(return_value, "pdo_type", param_type);
add_assoc_zval(return_value, "flags", &flags);
add_assoc_string(return_value, "table", (char *) (F->table?F->table : ""));
diff --git a/ext/pdo_mysql/tests/pdo_mysql_stmt_blobs.phpt b/ext/pdo_mysql/tests/pdo_mysql_stmt_blobs.phpt
index 9bdd03d7bd..7f45e56b6b 100644
--- a/ext/pdo_mysql/tests/pdo_mysql_stmt_blobs.phpt
+++ b/ext/pdo_mysql/tests/pdo_mysql_stmt_blobs.phpt
@@ -48,9 +48,15 @@ MySQLPDOTest::skip();
return false;
}
- if ($label !== $value) {
+ if (!is_resource($label)) {
+ printf("[%03d + 3] Returned value is not a stream resource\n", $offset);
+ return false;
+ }
+
+ $contents = stream_get_contents($label);
+ if ($contents !== $value) {
printf("[%03d + 3] Returned value seems to be wrong (%d vs. %d characters). Check manually\n",
- $offset, strlen($label), strlen($value));
+ $offset, strlen($contents), strlen($value));
return false;
}
diff --git a/ext/pdo_mysql/tests/pdo_mysql_stmt_getcolumnmeta.phpt b/ext/pdo_mysql/tests/pdo_mysql_stmt_getcolumnmeta.phpt
index b5b0275f04..0e87b118ee 100644
--- a/ext/pdo_mysql/tests/pdo_mysql_stmt_getcolumnmeta.phpt
+++ b/ext/pdo_mysql/tests/pdo_mysql_stmt_getcolumnmeta.phpt
@@ -139,23 +139,22 @@ try {
$real_as_float = (false === stristr($row['_mode'], "REAL_AS_FLOAT")) ? false : true;
$db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false);
- $is_mysqlnd = MySQLPDOTest::isPDOMySQLnd();
- test_meta($db, 20, 'BIT(8)', 1, 'BIT', ($is_mysqlnd) ? PDO::PARAM_INT : PDO::PARAM_STR);
- test_meta($db, 30, 'TINYINT', -127, 'TINY', ($is_mysqlnd) ? PDO::PARAM_INT : PDO::PARAM_STR);
- test_meta($db, 40, 'TINYINT UNSIGNED', 255, 'TINY', ($is_mysqlnd) ? PDO::PARAM_INT : PDO::PARAM_STR);
- test_meta($db, 50, 'BOOLEAN', 1, NULL, ($is_mysqlnd) ? PDO::PARAM_INT : PDO::PARAM_STR);
+ test_meta($db, 20, 'BIT(8)', 1, 'BIT', PDO::PARAM_INT);
+ test_meta($db, 30, 'TINYINT', -127, 'TINY', PDO::PARAM_INT);
+ test_meta($db, 40, 'TINYINT UNSIGNED', 255, 'TINY', PDO::PARAM_INT);
+ test_meta($db, 50, 'BOOLEAN', 1, NULL, PDO::PARAM_INT);
- test_meta($db, 60, 'SMALLINT', -32768, 'SHORT', ($is_mysqlnd) ? PDO::PARAM_INT : PDO::PARAM_STR);
- test_meta($db, 70, 'SMALLINT UNSIGNED', 65535, 'SHORT', ($is_mysqlnd) ? PDO::PARAM_INT : PDO::PARAM_STR);
+ test_meta($db, 60, 'SMALLINT', -32768, 'SHORT', PDO::PARAM_INT);
+ test_meta($db, 70, 'SMALLINT UNSIGNED', 65535, 'SHORT', PDO::PARAM_INT);
- test_meta($db, 80, 'MEDIUMINT', -8388608, 'INT24', ($is_mysqlnd) ? PDO::PARAM_INT : PDO::PARAM_STR);
- test_meta($db, 90, 'MEDIUMINT UNSIGNED', 16777215, 'INT24', ($is_mysqlnd) ? PDO::PARAM_INT : PDO::PARAM_STR);
+ test_meta($db, 80, 'MEDIUMINT', -8388608, 'INT24', PDO::PARAM_INT);
+ test_meta($db, 90, 'MEDIUMINT UNSIGNED', 16777215, 'INT24', PDO::PARAM_INT);
- test_meta($db, 100, 'INT', -2147483648, 'LONG', ($is_mysqlnd) ? PDO::PARAM_INT : PDO::PARAM_STR);
- test_meta($db, 110, 'INT UNSIGNED', 4294967295, 'LONG', ($is_mysqlnd) ? PDO::PARAM_INT : PDO::PARAM_STR);
+ test_meta($db, 100, 'INT', -2147483648, 'LONG', PDO::PARAM_INT);
+ test_meta($db, 110, 'INT UNSIGNED', 4294967295, 'LONG', PDO::PARAM_INT);
- test_meta($db, 120, 'BIGINT', '-9223372036854775808', 'LONGLONG', ($is_mysqlnd) ? ((PHP_INT_SIZE == 4) ? PDO::PARAM_STR : PDO::PARAM_INT) : PDO::PARAM_STR);
- test_meta($db, 130, 'BIGINT UNSIGNED', '18446744073709551615', 'LONGLONG', ($is_mysqlnd) ? ((PHP_INT_SIZE == 4) ? PDO::PARAM_STR : PDO::PARAM_INT) : PDO::PARAM_STR);
+ test_meta($db, 120, 'BIGINT', '-9223372036854775808', 'LONGLONG', (PHP_INT_SIZE == 4) ? PDO::PARAM_STR : PDO::PARAM_INT);
+ test_meta($db, 130, 'BIGINT UNSIGNED', '18446744073709551615', 'LONGLONG', (PHP_INT_SIZE == 4) ? PDO::PARAM_STR : PDO::PARAM_INT);
test_meta($db, 130, 'REAL', -1.01, ($real_as_float) ? 'FLOAT' : 'DOUBLE', PDO::PARAM_STR);
test_meta($db, 140, 'REAL UNSIGNED', 1.01, ($real_as_float) ? 'FLOAT' : 'DOUBLE', PDO::PARAM_STR);
@@ -186,7 +185,7 @@ try {
test_meta($db, 340, 'TIME', '14:37:00', 'TIME', PDO::PARAM_STR);
test_meta($db, 350, 'TIMESTAMP', '2008-03-23 14:38:00', 'TIMESTAMP', PDO::PARAM_STR);
test_meta($db, 360, 'DATETIME', '2008-03-23 14:38:00', 'DATETIME', PDO::PARAM_STR);
- test_meta($db, 370, 'YEAR', '2008', 'YEAR', ($is_mysqlnd) ? PDO::PARAM_INT : PDO::PARAM_STR);
+ test_meta($db, 370, 'YEAR', '2008', 'YEAR', PDO::PARAM_INT);
test_meta($db, 380, 'CHAR(1)', 'a', 'STRING', PDO::PARAM_STR);
test_meta($db, 390, 'CHAR(10)', '0123456789', 'STRING', PDO::PARAM_STR);
diff --git a/ext/pdo_oci/oci_statement.c b/ext/pdo_oci/oci_statement.c
index 0ab043f041..2a2bd58b90 100644
--- a/ext/pdo_oci/oci_statement.c
+++ b/ext/pdo_oci/oci_statement.c
@@ -555,12 +555,10 @@ static int oci_stmt_describe(pdo_stmt_t *stmt, int colno) /* {{{ */
}
S->cols[colno].datalen = 512; /* XXX should be INT_MAX and fetched by pieces */
S->cols[colno].data = emalloc(S->cols[colno].datalen + 1);
- col->param_type = PDO_PARAM_STR;
break;
case SQLT_BLOB:
case SQLT_CLOB:
- col->param_type = PDO_PARAM_LOB;
STMT_CALL(OCIDescriptorAlloc, (S->H->env, (dvoid**)&S->cols[colno].data, OCI_DTYPE_LOB, 0, NULL));
S->cols[colno].datalen = sizeof(OCILobLocator*);
dyn = TRUE;
@@ -590,9 +588,6 @@ static int oci_stmt_describe(pdo_stmt_t *stmt, int colno) /* {{{ */
S->cols[colno].data = emalloc(S->cols[colno].datalen + 1);
dtype = SQLT_CHR;
-
- /* returning data as a string */
- col->param_type = PDO_PARAM_STR;
}
STMT_CALL(OCIDefineByPos, (S->stmt, &S->cols[colno].def, S->err, colno+1,
@@ -742,7 +737,7 @@ static php_stream *oci_create_lob_stream(zval *dbh, pdo_stmt_t *stmt, OCILobLoca
return NULL;
}
-static int oci_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, size_t *len, int *caller_frees) /* {{{ */
+static int oci_stmt_get_col(pdo_stmt_t *stmt, int colno, zval *result, enum pdo_param_type *type) /* {{{ */
{
pdo_oci_stmt *S = (pdo_oci_stmt*)stmt->driver_data;
pdo_oci_column *C = &S->cols[colno];
@@ -750,30 +745,27 @@ static int oci_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, size_t *len
/* check the indicator to ensure that the data is intact */
if (C->indicator == -1) {
/* A NULL value */
- *ptr = NULL;
- *len = 0;
+ ZVAL_NULL(result);
return 1;
} else if (C->indicator == 0) {
/* it was stored perfectly */
if (C->dtype == SQLT_BLOB || C->dtype == SQLT_CLOB) {
if (C->data) {
- *ptr = (char*)oci_create_lob_stream(&stmt->database_object_handle, stmt, (OCILobLocator*)C->data);
+ php_stream *stream = oci_create_lob_stream(&stmt->database_object_handle, stmt, (OCILobLocator*)C->data);
OCILobOpen(S->H->svc, S->err, (OCILobLocator*)C->data, OCI_LOB_READONLY);
+ php_stream_to_zval(stream, result);
+ return 1;
}
- *len = (size_t) 0;
- return *ptr ? 1 : 0;
+ return 0;
}
- *ptr = C->data;
- *len = (size_t) C->fetched_len;
+ ZVAL_STRINFL_FAST(result, C->data, C->fetched_len);
return 1;
} else {
/* it was truncated */
php_error_docref(NULL, E_WARNING, "Column %d data was too large for buffer and was truncated to fit it", colno);
-
- *ptr = C->data;
- *len = (size_t) C->fetched_len;
+ ZVAL_STRINL(result, C->data, C->fetched_len);
return 1;
}
} /* }}} */
@@ -943,6 +935,16 @@ static int oci_stmt_col_meta(pdo_stmt_t *stmt, zend_long colno, zval *return_val
add_assoc_string(return_value, "native_type", "NULL");
}
+ switch (dtype) {
+ case SQLT_BLOB:
+ case SQLT_CLOB:
+ add_assoc_long(return_value, "pdo_type", PDO_PARAM_LOB);
+ break;
+ default:
+ add_assoc_long(return_value, "pdo_type", PDO_PARAM_STR);
+ break;
+ }
+
/* column can be null */
STMT_CALL_MSG(OCIAttrGet, "OCI_ATTR_IS_NULL",
(param, OCI_DTYPE_PARAM, &isnull, 0, OCI_ATTR_IS_NULL, S->err));
diff --git a/ext/pdo_odbc/odbc_stmt.c b/ext/pdo_odbc/odbc_stmt.c
index fdc427d5b0..f71d539271 100644
--- a/ext/pdo_odbc/odbc_stmt.c
+++ b/ext/pdo_odbc/odbc_stmt.c
@@ -88,31 +88,28 @@ static int pdo_odbc_utf82ucs2(pdo_stmt_t *stmt, int is_unicode, const char *buf,
return PDO_ODBC_CONV_NOT_REQUIRED;
}
-static int pdo_odbc_ucs22utf8(pdo_stmt_t *stmt, int is_unicode, const char *buf,
- zend_ulong buflen, zend_ulong *outlen)
+static int pdo_odbc_ucs22utf8(pdo_stmt_t *stmt, int is_unicode, zval *result)
{
#ifdef PHP_WIN32
- if (is_unicode && buflen) {
+ ZEND_ASSERT(Z_TYPE_P(result) == IS_STRING);
+ if (is_unicode && Z_STRLEN_P(result) != 0) {
pdo_odbc_stmt *S = (pdo_odbc_stmt*)stmt->driver_data;
DWORD ret;
- ret = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR)buf, buflen/sizeof(WCHAR), NULL, 0, NULL, NULL);
+ ret = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR) Z_STRVAL_P(result), Z_STRLEN_P(result)/sizeof(WCHAR), NULL, 0, NULL, NULL);
if (ret == 0) {
return PDO_ODBC_CONV_FAIL;
}
- if (S->convbufsize <= ret) {
- S->convbufsize = ret + 1;
- S->convbuf = erealloc(S->convbuf, S->convbufsize);
- }
-
- ret = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR)buf, buflen/sizeof(WCHAR), S->convbuf, S->convbufsize, NULL, NULL);
+ zend_string *str = zend_string_alloc(ret, 0);
+ ret = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR) Z_STRVAL_P(result), Z_STRLEN_P(result)/sizeof(WCHAR), ZSTR_VAL(str), ZSTR_LEN(str), NULL, NULL);
if (ret == 0) {
return PDO_ODBC_CONV_FAIL;
}
- *outlen = ret;
- S->convbuf[*outlen] = '\0';
+ ZSTR_VAL(str)[ret] = '\0';
+ zval_ptr_dtor_str(result);
+ ZVAL_STR(result, str);
return PDO_ODBC_CONV_OK;
}
#endif
@@ -480,38 +477,27 @@ static int odbc_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data *p
P = param->driver_data;
if (P->outbuf) {
- zend_ulong ulen;
- char *srcbuf;
- zend_ulong srclen = 0;
-
if (Z_ISREF(param->parameter)) {
parameter = Z_REFVAL(param->parameter);
} else {
parameter = &param->parameter;
}
zval_ptr_dtor(parameter);
- ZVAL_NULL(parameter);
switch (P->len) {
case SQL_NULL_DATA:
+ ZVAL_NULL(parameter);
break;
default:
- switch (pdo_odbc_ucs22utf8(stmt, P->is_unicode, P->outbuf, P->len, &ulen)) {
+ ZVAL_STRINGL(parameter, P->outbuf, P->len);
+ switch (pdo_odbc_ucs22utf8(stmt, P->is_unicode, parameter)) {
case PDO_ODBC_CONV_FAIL:
/* something fishy, but allow it to come back as binary */
case PDO_ODBC_CONV_NOT_REQUIRED:
- srcbuf = P->outbuf;
- srclen = P->len;
break;
case PDO_ODBC_CONV_OK:
- srcbuf = S->convbuf;
- srclen = ulen;
break;
}
-
- ZVAL_NEW_STR(parameter, zend_string_alloc(srclen, 0));
- memcpy(Z_STRVAL_P(parameter), srcbuf, srclen);
- Z_STRVAL_P(parameter)[Z_STRLEN_P(parameter)] = '\0';
}
}
return 1;
@@ -612,9 +598,6 @@ static int odbc_stmt_describe(pdo_stmt_t *stmt, int colno)
col->name = zend_string_init(S->cols[colno].colname, colnamelen, 0);
S->cols[colno].is_unicode = pdo_odbc_sqltype_is_unicode(S, S->cols[colno].coltype);
- /* returning data as a string */
- col->param_type = PDO_PARAM_STR;
-
/* tell ODBC to put it straight into our buffer, but only if it
* isn't "long" data, and only if we haven't already bound a long
* column. */
@@ -642,16 +625,19 @@ static int odbc_stmt_describe(pdo_stmt_t *stmt, int colno)
return 1;
}
-static int odbc_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, zend_ulong *len, int *caller_frees)
+static int odbc_stmt_get_column_meta(pdo_stmt_t *stmt, zend_long colno, zval *return_value)
+{
+ add_assoc_long(return_value, "pdo_type", PDO_PARAM_STR);
+ return 1;
+}
+
+static int odbc_stmt_get_col(pdo_stmt_t *stmt, int colno, zval *result, enum pdo_param_type *type)
{
pdo_odbc_stmt *S = (pdo_odbc_stmt*)stmt->driver_data;
pdo_odbc_column *C = &S->cols[colno];
- zend_ulong ulen;
/* if it is a column containing "long" data, perform late binding now */
if (C->is_long) {
- zend_ulong used = 0;
- char *buf;
RETCODE rc;
/* fetch it into C->data, which is allocated with a length
@@ -676,11 +662,9 @@ static int odbc_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, zend_ulong
this loop has to work whether or not SQLGetData() provides the total column length.
calling SQLDescribeCol() or other, specifically to get the column length, then doing a single read
for that size would be slower except maybe for extremely long columns.*/
- char *buf2;
-
- buf2 = emalloc(256);
- buf = estrndup(C->data, 256);
- used = 255; /* not 256; the driver NUL terminated the buffer */
+ char *buf2 = emalloc(256);
+ zend_string *str = zend_string_init(C->data, 255, 0);
+ size_t used = 255; /* not 256; the driver NUL terminated the buffer */
do {
C->fetched_len = 0;
@@ -692,12 +676,12 @@ static int odbc_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, zend_ulong
/* point 5, in section "Retrieving Data with SQLGetData" in http://msdn.microsoft.com/en-us/library/windows/desktop/ms715441(v=vs.85).aspx
states that if SQL_SUCCESS_WITH_INFO, fetched_len will be > 255 (greater than buf2's size)
(if a driver fails to follow that and wrote less than 255 bytes to buf2, this will AV or read garbage into buf) */
- buf = erealloc(buf, used + 255+1);
- memcpy(buf + used, buf2, 255);
+ str = zend_string_realloc(str, used + 255, 0);
+ memcpy(ZSTR_VAL(str) + used, buf2, 255);
used = used + 255;
} else if (rc==SQL_SUCCESS) {
- buf = erealloc(buf, used + C->fetched_len+1);
- memcpy(buf + used, buf2, C->fetched_len);
+ str = zend_string_realloc(str, used + C->fetched_len, 0);
+ memcpy(ZSTR_VAL(str) + used, buf2, C->fetched_len);
used = used + C->fetched_len;
} else {
/* includes SQL_NO_DATA */
@@ -709,11 +693,8 @@ static int odbc_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, zend_ulong
efree(buf2);
/* NULL terminate the buffer once, when finished, for use with the rest of PHP */
- buf[used] = '\0';
-
- *ptr = buf;
- *caller_frees = 1;
- *len = used;
+ ZSTR_VAL(str)[used] = '\0';
+ ZVAL_STR(result, str);
if (C->is_unicode) {
goto unicode_conv;
}
@@ -721,8 +702,6 @@ static int odbc_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, zend_ulong
}
/* something went caca */
- *ptr = NULL;
- *len = 0;
return 1;
}
@@ -730,40 +709,29 @@ in_data:
/* check the indicator to ensure that the data is intact */
if (C->fetched_len == SQL_NULL_DATA) {
/* A NULL value */
- *ptr = NULL;
- *len = 0;
+ ZVAL_NULL(result);
return 1;
} else if (C->fetched_len >= 0) {
/* it was stored perfectly */
- *ptr = C->data;
- *len = C->fetched_len;
+ ZVAL_STRINGL_FAST(result, C->data, C->fetched_len);
if (C->is_unicode) {
goto unicode_conv;
}
return 1;
} else {
/* no data? */
- *ptr = NULL;
- *len = 0;
+ ZVAL_NULL(result);
return 1;
}
- unicode_conv:
- switch (pdo_odbc_ucs22utf8(stmt, C->is_unicode, *ptr, *len, &ulen)) {
+unicode_conv:
+ switch (pdo_odbc_ucs22utf8(stmt, C->is_unicode, result)) {
case PDO_ODBC_CONV_FAIL:
/* oh well. They can have the binary version of it */
case PDO_ODBC_CONV_NOT_REQUIRED:
/* shouldn't happen... */
return 1;
-
case PDO_ODBC_CONV_OK:
- if (*caller_frees) {
- efree(*ptr);
- }
- *ptr = emalloc(ulen + 1);
- *len = ulen;
- memcpy(*ptr, S->convbuf, ulen+1);
- *caller_frees = 1;
return 1;
}
return 1;
@@ -873,8 +841,8 @@ const struct pdo_stmt_methods odbc_stmt_methods = {
odbc_stmt_get_col,
odbc_stmt_param_hook,
odbc_stmt_set_param,
- odbc_stmt_get_attr, /* get attr */
- NULL, /* get column meta */
+ odbc_stmt_get_attr,
+ odbc_stmt_get_column_meta,
odbc_stmt_next_rowset,
odbc_stmt_close_cursor
};
diff --git a/ext/pdo_pgsql/pgsql_statement.c b/ext/pdo_pgsql/pgsql_statement.c
index bf07af59a5..98ea8cb780 100644
--- a/ext/pdo_pgsql/pgsql_statement.c
+++ b/ext/pdo_pgsql/pgsql_statement.c
@@ -467,7 +467,6 @@ static int pgsql_stmt_describe(pdo_stmt_t *stmt, int colno)
{
pdo_pgsql_stmt *S = (pdo_pgsql_stmt*)stmt->driver_data;
struct pdo_column_data *cols = stmt->columns;
- struct pdo_bound_param_data *param;
char *str;
if (!S->result) {
@@ -480,122 +479,79 @@ static int pgsql_stmt_describe(pdo_stmt_t *stmt, int colno)
cols[colno].precision = PQfmod(S->result, colno);
S->cols[colno].pgsql_type = PQftype(S->result, colno);
- switch (S->cols[colno].pgsql_type) {
-
- case BOOLOID:
- cols[colno].param_type = PDO_PARAM_BOOL;
- break;
-
- case OIDOID:
- /* did the user bind the column as a LOB ? */
- if (stmt->bound_columns && (
- (param = zend_hash_index_find_ptr(stmt->bound_columns, colno)) != NULL ||
- (param = zend_hash_find_ptr(stmt->bound_columns, cols[colno].name)) != NULL)) {
-
- if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_LOB) {
- cols[colno].param_type = PDO_PARAM_LOB;
- break;
- }
- }
- cols[colno].param_type = PDO_PARAM_INT;
- break;
-
- case INT2OID:
- case INT4OID:
- cols[colno].param_type = PDO_PARAM_INT;
- break;
-
- case INT8OID:
- if (sizeof(zend_long)>=8) {
- cols[colno].param_type = PDO_PARAM_INT;
- } else {
- cols[colno].param_type = PDO_PARAM_STR;
- }
- break;
-
- case BYTEAOID:
- cols[colno].param_type = PDO_PARAM_LOB;
- break;
-
- default:
- cols[colno].param_type = PDO_PARAM_STR;
- }
-
return 1;
}
-static int pgsql_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, size_t *len, int *caller_frees )
+static int pgsql_stmt_get_col(pdo_stmt_t *stmt, int colno, zval *result, enum pdo_param_type *type)
{
pdo_pgsql_stmt *S = (pdo_pgsql_stmt*)stmt->driver_data;
- struct pdo_column_data *cols = stmt->columns;
- size_t tmp_len;
-
if (!S->result) {
return 0;
}
/* We have already increased count by 1 in pgsql_stmt_fetch() */
if (PQgetisnull(S->result, S->current_row - 1, colno)) { /* Check if we got NULL */
- *ptr = NULL;
- *len = 0;
+ ZVAL_NULL(result);
} else {
- *ptr = PQgetvalue(S->result, S->current_row - 1, colno);
- *len = PQgetlength(S->result, S->current_row - 1, colno);
-
- switch (cols[colno].param_type) {
+ char *ptr = PQgetvalue(S->result, S->current_row - 1, colno);
+ size_t len = PQgetlength(S->result, S->current_row - 1, colno);
- case PDO_PARAM_INT:
- ZEND_ATOL(S->cols[colno].intval, *ptr);
- *ptr = (char *) &(S->cols[colno].intval);
- *len = sizeof(zend_long);
+ switch (S->cols[colno].pgsql_type) {
+ case BOOLOID:
+ ZVAL_BOOL(result, *ptr == 't');
break;
- case PDO_PARAM_BOOL:
- S->cols[colno].boolval = **ptr == 't';
- *ptr = (char *) &(S->cols[colno].boolval);
- *len = sizeof(zend_bool);
+ case INT2OID:
+ case INT4OID:
+#if SIZEOF_ZEND_LONG >= 8
+ case INT8OID:
+#endif
+ {
+ zend_long intval;
+ ZEND_ATOL(intval, ptr);
+ ZVAL_LONG(result, intval);
break;
+ }
- case PDO_PARAM_LOB:
- if (S->cols[colno].pgsql_type == OIDOID) {
- /* ooo, a real large object */
- char *end_ptr;
- Oid oid = (Oid)strtoul(*ptr, &end_ptr, 10);
+ case OIDOID: {
+ char *end_ptr;
+ Oid oid = (Oid)strtoul(ptr, &end_ptr, 10);
+ if (type && *type == PDO_PARAM_LOB) {
+ /* If column was bound as LOB, return a stream. */
int loid = lo_open(S->H->server, oid, INV_READ);
if (loid >= 0) {
- *ptr = (char*)pdo_pgsql_create_lob_stream(&stmt->database_object_handle, loid, oid);
- *len = 0;
- return *ptr ? 1 : 0;
+ php_stream *stream = pdo_pgsql_create_lob_stream(&stmt->database_object_handle, loid, oid);
+ if (stream) {
+ php_stream_to_zval(stream, result);
+ return 1;
+ }
}
- *ptr = NULL;
- *len = 0;
return 0;
} else {
- char *tmp_ptr = (char *)PQunescapeBytea((unsigned char *)*ptr, &tmp_len);
- if (!tmp_ptr) {
- /* PQunescapeBytea returned an error */
- *len = 0;
- return 0;
- }
- if (!tmp_len) {
- /* Empty string, return as empty stream */
- *ptr = (char *)php_stream_memory_create(TEMP_STREAM_READONLY);
- PQfreemem(tmp_ptr);
- *len = 0;
- } else {
- *ptr = estrndup(tmp_ptr, tmp_len);
- PQfreemem(tmp_ptr);
- *len = tmp_len;
- *caller_frees = 1;
- }
+ /* Otherwise return OID as integer. */
+ ZVAL_LONG(result, oid);
}
break;
- case PDO_PARAM_NULL:
- case PDO_PARAM_STR:
- case PDO_PARAM_STMT:
- case PDO_PARAM_INPUT_OUTPUT:
- case PDO_PARAM_ZVAL:
+ }
+
+ case BYTEAOID: {
+ size_t tmp_len;
+ char *tmp_ptr = (char *)PQunescapeBytea((unsigned char *) ptr, &tmp_len);
+ if (!tmp_ptr) {
+ /* PQunescapeBytea returned an error */
+ return 0;
+ }
+
+ zend_string *str = zend_string_init(tmp_ptr, tmp_len, 0);
+ php_stream *stream = php_stream_memory_open(TEMP_STREAM_READONLY, str);
+ php_stream_to_zval(stream, result);
+ zend_string_release(str);
+ PQfreemem(tmp_ptr);
+ break;
+ }
+
default:
+ ZVAL_STRINGL_FAST(result, ptr, len);
break;
}
}
@@ -698,6 +654,26 @@ static int pgsql_stmt_get_column_meta(pdo_stmt_t *stmt, zend_long colno, zval *r
}
PQclear(res);
}
+
+ enum pdo_param_type param_type;
+ switch (S->cols[colno].pgsql_type) {
+ case BOOLOID:
+ param_type = PDO_PARAM_BOOL;
+ break;
+ case INT2OID:
+ case INT4OID:
+ case INT8OID:
+ param_type = PDO_PARAM_INT;
+ break;
+ case OIDOID:
+ case BYTEAOID:
+ param_type = PDO_PARAM_LOB;
+ break;
+ default:
+ param_type = PDO_PARAM_STR;
+ }
+ add_assoc_long(return_value, "pdo_type", param_type);
+
return 1;
}
diff --git a/ext/pdo_pgsql/php_pdo_pgsql_int.h b/ext/pdo_pgsql/php_pdo_pgsql_int.h
index 1f5ea30063..b4bc6318e7 100644
--- a/ext/pdo_pgsql/php_pdo_pgsql_int.h
+++ b/ext/pdo_pgsql/php_pdo_pgsql_int.h
@@ -48,9 +48,7 @@ typedef struct {
} pdo_pgsql_db_handle;
typedef struct {
- zend_long intval;
Oid pgsql_type;
- zend_bool boolval;
} pdo_pgsql_column;
typedef struct {
diff --git a/ext/pdo_pgsql/tests/bug62498.phpt b/ext/pdo_pgsql/tests/bug62498.phpt
index 1620e7e77a..2970278204 100644
--- a/ext/pdo_pgsql/tests/bug62498.phpt
+++ b/ext/pdo_pgsql/tests/bug62498.phpt
@@ -56,14 +56,14 @@ array(9) {
string(13) "bugtest_62498"
["native_type"]=>
string(4) "int2"
+ ["pdo_type"]=>
+ int(2)
["name"]=>
string(7) "int2col"
["len"]=>
int(2)
["precision"]=>
int(-1)
- ["pdo_type"]=>
- int(1)
}
[1]=>
array(8) {
@@ -75,14 +75,14 @@ array(9) {
string(13) "bugtest_62498"
["native_type"]=>
string(4) "int4"
+ ["pdo_type"]=>
+ int(2)
["name"]=>
string(7) "int4col"
["len"]=>
int(4)
["precision"]=>
int(-1)
- ["pdo_type"]=>
- int(1)
}
[2]=>
array(8) {
@@ -94,14 +94,14 @@ array(9) {
string(13) "bugtest_62498"
["native_type"]=>
string(4) "int8"
+ ["pdo_type"]=>
+ int(2)
["name"]=>
string(7) "int8col"
["len"]=>
int(8)
["precision"]=>
int(-1)
- ["pdo_type"]=>
- int(1)
}
[3]=>
array(8) {
@@ -113,14 +113,14 @@ array(9) {
string(13) "bugtest_62498"
["native_type"]=>
string(7) "varchar"
+ ["pdo_type"]=>
+ int(3)
["name"]=>
string(9) "stringcol"
["len"]=>
int(-1)
["precision"]=>
int(259)
- ["pdo_type"]=>
- int(2)
}
[4]=>
array(8) {
@@ -132,14 +132,14 @@ array(9) {
string(13) "bugtest_62498"
["native_type"]=>
string(4) "bool"
+ ["pdo_type"]=>
+ int(1)
["name"]=>
string(7) "boolcol"
["len"]=>
int(1)
["precision"]=>
int(-1)
- ["pdo_type"]=>
- int(5)
}
[5]=>
array(8) {
@@ -151,14 +151,14 @@ array(9) {
string(13) "bugtest_62498"
["native_type"]=>
string(4) "date"
+ ["pdo_type"]=>
+ int(3)
["name"]=>
string(7) "datecol"
["len"]=>
int(4)
["precision"]=>
int(-1)
- ["pdo_type"]=>
- int(2)
}
[6]=>
array(8) {
@@ -170,14 +170,14 @@ array(9) {
string(13) "bugtest_62498"
["native_type"]=>
string(4) "text"
+ ["pdo_type"]=>
+ int(3)
["name"]=>
string(7) "textcol"
["len"]=>
int(-1)
["precision"]=>
int(-1)
- ["pdo_type"]=>
- int(2)
}
[7]=>
array(8) {
@@ -189,14 +189,14 @@ array(9) {
string(13) "bugtest_62498"
["native_type"]=>
string(9) "timestamp"
+ ["pdo_type"]=>
+ int(3)
["name"]=>
string(5) "tscol"
["len"]=>
int(8)
["precision"]=>
int(-1)
- ["pdo_type"]=>
- int(2)
}
[8]=>
array(8) {
@@ -208,14 +208,14 @@ array(9) {
string(13) "bugtest_62498"
["native_type"]=>
string(5) "bytea"
+ ["pdo_type"]=>
+ int(4)
["name"]=>
string(8) "byteacol"
["len"]=>
int(-1)
["precision"]=>
int(-1)
- ["pdo_type"]=>
- int(3)
}
}
Done
diff --git a/ext/pdo_pgsql/tests/debug_emulated_prepares.phpt b/ext/pdo_pgsql/tests/debug_emulated_prepares.phpt
index dfbbcb4ad4..5c8f590351 100644
--- a/ext/pdo_pgsql/tests/debug_emulated_prepares.phpt
+++ b/ext/pdo_pgsql/tests/debug_emulated_prepares.phpt
@@ -31,17 +31,17 @@ Key: Name: [5] :bool
paramno=-1
name=[5] ":bool"
is_param=1
-param_type=2
+param_type=3
Key: Name: [4] :int
paramno=-1
name=[4] ":int"
is_param=1
-param_type=1
+param_type=2
Key: Name: [7] :string
paramno=-1
name=[7] ":string"
is_param=1
-param_type=2
+param_type=3
Key: Name: [5] :null
paramno=-1
name=[5] ":null"
diff --git a/ext/pdo_sqlite/sqlite_statement.c b/ext/pdo_sqlite/sqlite_statement.c
index 3769b1e049..66ec692cf8 100644
--- a/ext/pdo_sqlite/sqlite_statement.c
+++ b/ext/pdo_sqlite/sqlite_statement.c
@@ -247,21 +247,11 @@ static int pdo_sqlite_stmt_describe(pdo_stmt_t *stmt, int colno)
stmt->columns[colno].maxlen = SIZE_MAX;
stmt->columns[colno].precision = 0;
- switch (sqlite3_column_type(S->stmt, colno)) {
- case SQLITE_INTEGER:
- case SQLITE_FLOAT:
- case SQLITE3_TEXT:
- case SQLITE_BLOB:
- case SQLITE_NULL:
- default:
- stmt->columns[colno].param_type = PDO_PARAM_STR;
- break;
- }
-
return 1;
}
-static int pdo_sqlite_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, size_t *len, int *caller_frees)
+static int pdo_sqlite_stmt_get_col(
+ pdo_stmt_t *stmt, int colno, zval *result, enum pdo_param_type *type)
{
pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
if (!S->stmt) {
@@ -274,18 +264,17 @@ static int pdo_sqlite_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, size
}
switch (sqlite3_column_type(S->stmt, colno)) {
case SQLITE_NULL:
- *ptr = NULL;
- *len = 0;
+ ZVAL_NULL(result);
return 1;
case SQLITE_BLOB:
- *ptr = (char*)sqlite3_column_blob(S->stmt, colno);
- *len = sqlite3_column_bytes(S->stmt, colno);
+ ZVAL_STRINGL_FAST(result,
+ sqlite3_column_blob(S->stmt, colno), sqlite3_column_bytes(S->stmt, colno));
return 1;
default:
- *ptr = (char*)sqlite3_column_text(S->stmt, colno);
- *len = sqlite3_column_bytes(S->stmt, colno);
+ ZVAL_STRINGL_FAST(result,
+ (char *) sqlite3_column_text(S->stmt, colno), sqlite3_column_bytes(S->stmt, colno));
return 1;
}
}
@@ -341,6 +330,7 @@ static int pdo_sqlite_stmt_col_meta(pdo_stmt_t *stmt, zend_long colno, zval *ret
#endif
add_assoc_zval(return_value, "flags", &flags);
+ add_assoc_long(return_value, "pdo_type", PDO_PARAM_STR);
return SUCCESS;
}
diff --git a/ext/pdo_sqlite/tests/bug79664.phpt b/ext/pdo_sqlite/tests/bug79664.phpt
index fae39aea3e..a3648099dc 100644
--- a/ext/pdo_sqlite/tests/bug79664.phpt
+++ b/ext/pdo_sqlite/tests/bug79664.phpt
@@ -21,12 +21,12 @@ array(6) {
["flags"]=>
array(0) {
}
+ ["pdo_type"]=>
+ int(3)
["name"]=>
string(1) "1"
["len"]=>
int(-1)
["precision"]=>
int(0)
- ["pdo_type"]=>
- int(2)
}
diff --git a/ext/pdo_sqlite/tests/debugdumpparams_001.phpt b/ext/pdo_sqlite/tests/debugdumpparams_001.phpt
index 4402b5c815..88dc21ce82 100644
--- a/ext/pdo_sqlite/tests/debugdumpparams_001.phpt
+++ b/ext/pdo_sqlite/tests/debugdumpparams_001.phpt
@@ -23,15 +23,15 @@ Key: Name: [2] :a
paramno=-1
name=[2] ":a"
is_param=1
-param_type=1
+param_type=2
Key: Name: [2] :b
paramno=-1
name=[2] ":b"
is_param=1
-param_type=2
+param_type=3
Key: Position #2:
paramno=2
name=[0] ""
is_param=1
-param_type=2
+param_type=3
NULL