diff --git a/ext/pdo_dblib/dblib_driver.c b/ext/pdo_dblib/dblib_driver.c index 4303379adf928..06bd3ce3a60b5 100644 --- a/ext/pdo_dblib/dblib_driver.c +++ b/ext/pdo_dblib/dblib_driver.c @@ -244,6 +244,33 @@ char *dblib_handle_last_id(pdo_dbh_t *dbh, const char *name, unsigned int *len T return id; } +static int dblib_handle_set_attr(pdo_dbh_t *dbh, long attr, zval *val TSRMLS_DC) +{ + pdo_dblib_db_handle *H = (pdo_dblib_db_handle *)dbh->driver_data; + switch (attr) { + case PDO_DBLIB_ATTR_SKIP_EMPTY_ROWSETS: + H->skip_empty_rowsets = zval_is_true(val); + return 1; + default: + return 0; + } +} + +static int pdo_dblib_get_attribute(pdo_dbh_t *dbh, long attr, zval *return_value TSRMLS_DC) +{ + pdo_dblib_db_handle *H = (pdo_dblib_db_handle *)dbh->driver_data; + + switch (attr) { + case PDO_DBLIB_ATTR_SKIP_EMPTY_ROWSETS: + ZVAL_BOOL(return_value, H->skip_empty_rowsets); + break; + default: + return 0; + } + + return 1; +} + static struct pdo_dbh_methods dblib_methods = { dblib_handle_closer, dblib_handle_preparer, @@ -252,10 +279,10 @@ static struct pdo_dbh_methods dblib_methods = { dblib_handle_begin, /* begin */ dblib_handle_commit, /* commit */ dblib_handle_rollback, /* rollback */ - NULL, /*set attr */ + dblib_handle_set_attr, /*set attr */ dblib_handle_last_id, /* last insert id */ dblib_fetch_error, /* fetch error */ - NULL, /* get attr */ + pdo_dblib_get_attribute, /* get attr */ NULL, /* check liveness */ NULL, /* get driver methods */ NULL, /* request shutdown */ diff --git a/ext/pdo_dblib/dblib_stmt.c b/ext/pdo_dblib/dblib_stmt.c index 263ae6dcb8fdc..3c445051c09b3 100644 --- a/ext/pdo_dblib/dblib_stmt.c +++ b/ext/pdo_dblib/dblib_stmt.c @@ -126,8 +126,16 @@ static int pdo_dblib_stmt_next_rowset(pdo_stmt_t *stmt TSRMLS_DC) pdo_dblib_stmt *S = (pdo_dblib_stmt*)stmt->driver_data; 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 (H->skip_empty_rowsets && num_fields <= 0) { + return 0; + } if (FAIL == ret) { pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "PDO_DBLIB: dbresults() returned FAIL" TSRMLS_CC); @@ -139,7 +147,7 @@ static int pdo_dblib_stmt_next_rowset(pdo_stmt_t *stmt TSRMLS_DC) } 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 55ce016e54e1e..0a61680f1d936 100644 --- a/ext/pdo_dblib/pdo_dblib.c +++ b/ext/pdo_dblib/pdo_dblib.c @@ -188,6 +188,7 @@ PHP_RSHUTDOWN_FUNCTION(pdo_dblib) PHP_MINIT_FUNCTION(pdo_dblib) { + REGISTER_PDO_CLASS_CONST_LONG("DBLIB_ATTR_SKIP_EMPTY_ROWSETS", 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 925315a14a89a..22c62f68982a1 100644 --- a/ext/pdo_dblib/php_pdo_dblib_int.h +++ b/ext/pdo_dblib/php_pdo_dblib_int.h @@ -111,7 +111,7 @@ typedef struct { typedef struct { LOGINREC *login; DBPROCESS *link; - + unsigned skip_empty_rowsets:1; pdo_dblib_err err; } pdo_dblib_db_handle; @@ -125,6 +125,9 @@ typedef struct { int value; } pdo_dblib_keyval; +enum { + PDO_DBLIB_ATTR_SKIP_EMPTY_ROWSETS = PDO_ATTR_DRIVER_SPECIFIC, +}; ZEND_BEGIN_MODULE_GLOBALS(dblib) pdo_dblib_err err; diff --git a/ext/pdo_dblib/tests/bug_69592.phpt b/ext/pdo_dblib/tests/bug_69592.phpt new file mode 100644 index 0000000000000..ad5133f27998a --- /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"]=> + string(1) "0" + } +} +bool(true) +array(1) { + [0]=> + array(1) { + ["result"]=> + string(1) "0" + } +} +bool(false) +array(0) { +} +bool(true)