diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c index cb5f1e1bc3d31..78838926ff35e 100644 --- a/ext/pdo/pdo_dbh.c +++ b/ext/pdo/pdo_dbh.c @@ -1412,6 +1412,7 @@ void pdo_dbh_init(void) REGISTER_PDO_CLASS_CONST_LONG("PARAM_STR", (zend_long)PDO_PARAM_STR); REGISTER_PDO_CLASS_CONST_LONG("PARAM_LOB", (zend_long)PDO_PARAM_LOB); REGISTER_PDO_CLASS_CONST_LONG("PARAM_STMT", (zend_long)PDO_PARAM_STMT); + REGISTER_PDO_CLASS_CONST_LONG("PARAM_FLOAT", (zend_long)PDO_PARAM_FLOAT); REGISTER_PDO_CLASS_CONST_LONG("PARAM_INPUT_OUTPUT", (zend_long)PDO_PARAM_INPUT_OUTPUT); REGISTER_PDO_CLASS_CONST_LONG("PARAM_STR_NATL", (zend_long)PDO_PARAM_STR_NATL); REGISTER_PDO_CLASS_CONST_LONG("PARAM_STR_CHAR", (zend_long)PDO_PARAM_STR_CHAR); diff --git a/ext/pdo/pdo_sql_parser.c b/ext/pdo/pdo_sql_parser.c index 8545861585615..84f6f6b8e6b16 100644 --- a/ext/pdo/pdo_sql_parser.c +++ b/ext/pdo/pdo_sql_parser.c @@ -569,6 +569,12 @@ PDO_API int pdo_parse_params(pdo_stmt_t *stmt, char *inquery, size_t inquery_len plc->freeq = 0; break; + /* TODO: test coverage */ + case PDO_PARAM_FLOAT: + plc->qlen = spprintf(&plc->quoted, 0, "%.*H", (int) EG(precision), zval_get_double(parameter)); + plc->freeq = 1; + break; + case PDO_PARAM_INT: buf = zend_long_to_str(zval_get_long(parameter)); diff --git a/ext/pdo/pdo_stmt.c b/ext/pdo/pdo_stmt.c index d0e3d7a41dd4a..44a88e79721b6 100644 --- a/ext/pdo/pdo_stmt.c +++ b/ext/pdo/pdo_stmt.c @@ -554,6 +554,14 @@ static inline void fetch_value(pdo_stmt_t *stmt, zval *dest, int colno, int *typ } break; + case PDO_PARAM_FLOAT: + if (value && value_len == sizeof(double)) { + ZVAL_DOUBLE(dest, *(double*)value); + break; + } + ZVAL_NULL(dest); + break; + case PDO_PARAM_INT: if (value && value_len == sizeof(zend_long)) { ZVAL_LONG(dest, *(zend_long*)value); @@ -622,6 +630,11 @@ static inline void fetch_value(pdo_stmt_t *stmt, zval *dest, int colno, int *typ if (type != new_type) { switch (new_type) { + case PDO_PARAM_FLOAT: + /* TODO: test coverage */ + /* invoked via do_fetch_common() / if (do_bind && stmt->bound_columns) */ + convert_to_double_ex(dest); + break; case PDO_PARAM_INT: convert_to_long_ex(dest); break; diff --git a/ext/pdo/php_pdo_driver.h b/ext/pdo/php_pdo_driver.h index bcbe5b367256b..bc57bd33896b9 100644 --- a/ext/pdo/php_pdo_driver.h +++ b/ext/pdo/php_pdo_driver.h @@ -46,7 +46,7 @@ PDO_API char *php_pdo_int64_to_str(pdo_int64_t i64); # define FALSE 0 #endif -#define PDO_DRIVER_API 20170320 +#define PDO_DRIVER_API 20170501 enum pdo_param_type { PDO_PARAM_NULL, @@ -76,6 +76,9 @@ enum pdo_param_type { */ PDO_PARAM_ZVAL, + /* get_col ptr should point to a double */ + PDO_PARAM_FLOAT, + /* magic flag to denote a parameter as being input/output */ PDO_PARAM_INPUT_OUTPUT = 0x80000000, diff --git a/ext/pdo_sqlite/sqlite_statement.c b/ext/pdo_sqlite/sqlite_statement.c index 817e6294db1e3..7d1e56647a91e 100644 --- a/ext/pdo_sqlite/sqlite_statement.c +++ b/ext/pdo_sqlite/sqlite_statement.c @@ -105,6 +105,25 @@ static int pdo_sqlite_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_d pdo_sqlite_error_stmt(stmt); return 0; + case PDO_PARAM_FLOAT: + if (Z_ISREF(param->parameter)) { + parameter = Z_REFVAL(param->parameter); + } else { + parameter = ¶m->parameter; + } + if (Z_TYPE_P(parameter) == IS_NULL) { + if (sqlite3_bind_null(S->stmt, param->paramno + 1) == SQLITE_OK) { + return 1; + } + } else { + convert_to_double(parameter); + if (SQLITE_OK == sqlite3_bind_double(S->stmt, param->paramno + 1, Z_DVAL_P(parameter))) { + return 1; + } + } + pdo_sqlite_error_stmt(stmt); + return 0; + case PDO_PARAM_INT: case PDO_PARAM_BOOL: if (Z_ISREF(param->parameter)) {