diff --git a/ext/pdo_dblib/dblib_driver.c b/ext/pdo_dblib/dblib_driver.c index efc8dc119782c..e8c010c5630ff 100644 --- a/ext/pdo_dblib/dblib_driver.c +++ b/ext/pdo_dblib/dblib_driver.c @@ -287,6 +287,9 @@ static int dblib_set_attr(pdo_dbh_t *dbh, zend_long attr, zval *val) case PDO_DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER: H->stringify_uniqueidentifier = zval_get_long(val); return 1; + case PDO_DBLIB_ATTR_SKIP_EMPTY_ROWSETS: + H->skip_empty_rowsets = zval_is_true(val); + return 1; default: return 0; } @@ -314,6 +317,10 @@ static int dblib_get_attribute(pdo_dbh_t *dbh, zend_long attr, zval *return_valu ZVAL_STRING(return_value, dbversion()); break; + case PDO_DBLIB_ATTR_SKIP_EMPTY_ROWSETS: + ZVAL_BOOL(return_value, H->skip_empty_rowsets); + break; + default: return 0; } @@ -387,6 +394,7 @@ static int pdo_dblib_handle_factory(pdo_dbh_t *dbh, zval *driver_options) H->err.sqlstate = dbh->error_code; H->assume_national_character_set_strings = 0; H->stringify_uniqueidentifier = 0; + H->skip_empty_rowsets = 0; if (!H->login) { goto cleanup; @@ -409,6 +417,7 @@ static int pdo_dblib_handle_factory(pdo_dbh_t *dbh, zval *driver_options) H->assume_national_character_set_strings = pdo_attr_lval(driver_options, PDO_ATTR_DEFAULT_STR_PARAM, 0) == PDO_PARAM_STR_NATL ? 1 : 0; H->stringify_uniqueidentifier = pdo_attr_lval(driver_options, PDO_DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER, 0); + H->skip_empty_rowsets = pdo_attr_lval(driver_options, PDO_DBLIB_ATTR_SKIP_EMPTY_ROWSETS, 0); } DBERRHANDLE(H->login, (EHANDLEFUNC) pdo_dblib_error_handler); diff --git a/ext/pdo_dblib/dblib_stmt.c b/ext/pdo_dblib/dblib_stmt.c index 6c8427da6b138..2bf7e24fbfd06 100644 --- a/ext/pdo_dblib/dblib_stmt.c +++ b/ext/pdo_dblib/dblib_stmt.c @@ -125,7 +125,12 @@ static int pdo_dblib_stmt_next_rowset_no_cancel(pdo_stmt_t *stmt) pdo_dblib_db_handle *H = S->H; RETCODE ret; - ret = dbresults(H->link); + int num_fields; + do { + ret = dbresults(H->link); + num_fields = dbnumcols(H->link); + } while (H->skip_empty_rowsets && num_fields <= 0 && ret == SUCCEED); + if (FAIL == ret) { pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "PDO_DBLIB: dbresults() returned FAIL"); @@ -136,8 +141,12 @@ static int pdo_dblib_stmt_next_rowset_no_cancel(pdo_stmt_t *stmt) return 0; } + if (H->skip_empty_rowsets && num_fields <= 0) { + return 0; + } + stmt->row_count = DBCOUNT(H->link); - stmt->column_count = dbnumcols(H->link); + stmt->column_count = num_fields; return 1; } diff --git a/ext/pdo_dblib/pdo_dblib.c b/ext/pdo_dblib/pdo_dblib.c index 1732cd75f9d50..d6a0eda07b47f 100644 --- a/ext/pdo_dblib/pdo_dblib.c +++ b/ext/pdo_dblib/pdo_dblib.c @@ -195,6 +195,7 @@ PHP_MINIT_FUNCTION(pdo_dblib) REGISTER_PDO_CLASS_CONST_LONG("DBLIB_ATTR_QUERY_TIMEOUT", (long) PDO_DBLIB_ATTR_QUERY_TIMEOUT); REGISTER_PDO_CLASS_CONST_LONG("DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER", (long) PDO_DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER); REGISTER_PDO_CLASS_CONST_LONG("DBLIB_ATTR_VERSION", (long) PDO_DBLIB_ATTR_VERSION); + REGISTER_PDO_CLASS_CONST_LONG("DBLIB_ATTR_SKIP_EMPTY_ROWSETS", (long) PDO_DBLIB_ATTR_SKIP_EMPTY_ROWSETS); if (FAIL == dbinit()) { return FAILURE; diff --git a/ext/pdo_dblib/php_pdo_dblib_int.h b/ext/pdo_dblib/php_pdo_dblib_int.h index c40697680f316..1b59dd3a38164 100644 --- a/ext/pdo_dblib/php_pdo_dblib_int.h +++ b/ext/pdo_dblib/php_pdo_dblib_int.h @@ -118,6 +118,7 @@ typedef struct { pdo_dblib_err err; unsigned assume_national_character_set_strings:1; unsigned stringify_uniqueidentifier:1; + unsigned skip_empty_rowsets:1; } pdo_dblib_db_handle; typedef struct { @@ -150,6 +151,7 @@ enum { PDO_DBLIB_ATTR_QUERY_TIMEOUT, PDO_DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER, PDO_DBLIB_ATTR_VERSION, + PDO_DBLIB_ATTR_SKIP_EMPTY_ROWSETS, }; #endif diff --git a/ext/pdo_dblib/tests/bug_69592.phpt b/ext/pdo_dblib/tests/bug_69592.phpt new file mode 100644 index 0000000000000..99b099575b3a0 --- /dev/null +++ b/ext/pdo_dblib/tests/bug_69592.phpt @@ -0,0 +1,60 @@ +--TEST-- +PDO_DBLIB: PDO::DBLIB_ATTR_SKIP_EMPTY_ROWSETS for skip junk resultsets on SET NOCOUNT expression +--SKIPIF-- + +--FILE-- +getAttribute(PDO::DBLIB_ATTR_SKIP_EMPTY_ROWSETS)); // disabled by default + +$stmt = $db->query($sql); +var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); // expected: array(result => 0), actual: array() +var_dump($stmt->nextRowset()); // expected: bool(false), actual: bool(true) +var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); // expected: array(), actual: array(result => 0) +$stmt->closeCursor(); + + +$db->setAttribute(PDO::DBLIB_ATTR_SKIP_EMPTY_ROWSETS, true); +var_dump($db->getAttribute(PDO::DBLIB_ATTR_SKIP_EMPTY_ROWSETS)); + +$stmt = $db->query($sql); +var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); // expected: array(result => 0), actual: array() +var_dump($stmt->nextRowset()); // expected: bool(false), actual: bool(true) +var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); // expected: array(), actual: array(result => 0) +$stmt->closeCursor(); +var_dump($db->getAttribute(PDO::DBLIB_ATTR_SKIP_EMPTY_ROWSETS)); + +?> +--EXPECT-- +bool(false) +array(0) { +} +bool(true) +array(1) { + [0]=> + array(1) { + ["result"]=> + int(0) + } +} +bool(true) +array(1) { + [0]=> + array(1) { + ["result"]=> + int(0) + } +} +bool(false) +array(0) { +} +bool(true)