]> granicus.if.org Git - php/commitdiff
Implemented request #69592: allow 0-column rowsets to be skipped automatically
authorfandrieu <fandrieu@gmail.com>
Tue, 17 Oct 2017 18:16:38 +0000 (14:16 -0400)
committerAdam Baratz <adambaratz@php.net>
Tue, 17 Oct 2017 18:16:38 +0000 (14:16 -0400)
This adds a new attribute PDO::DBLIB_ATTR_SKIP_EMPTY_ROWSETS to enable automatic
skipping of empty rowsets.

This happens with some SQL commands (like PRINT or SET): a rowset with 0 columns
is returned by the driver.

With this option enabled, 0 columns rowsets are automatically skipped, mirroring
the behavior of the deprecated mssql extension.

Credits go to MiRacLe-RPZ for developping and promoting this patch.

NEWS
ext/pdo_dblib/dblib_driver.c
ext/pdo_dblib/dblib_stmt.c
ext/pdo_dblib/pdo_dblib.c
ext/pdo_dblib/php_pdo_dblib_int.h
ext/pdo_dblib/tests/bug_69592.phpt [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index 3f9cff1e5fbb8b2031fa0c3fa01ab7fbe21aec23..2ab64b2f56b702b4255a098208016a0ab7f5a522 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -58,6 +58,10 @@ PHP                                                                        NEWS
   . Removed support for ODBCRouter. (Kalle)
   . Removed support for Birdstep. (Kalle)
 
+- PDO_DBlib:
+  . Implemented request #69592 (allow 0-column rowsets to be skipped
+    automatically). (fandrieu)
+
 - PDO_OCI:
   . Fixed bug #74631 (PDO_PCO with PHP-FPM: OCI environment initialized
     before PHP-FPM sets it up). (Ingmar Runge)
index efc8dc119782cc94a3ed7f62da732f1bff489a4f..e8c010c5630ff2e6849e24d6541ac65b94994596 100644 (file)
@@ -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);
index 6c8427da6b138d9b36fe8a1e9d532d6a844efe3d..469bd790de6225b394ae7f7e11d2ef9b552251b4 100644 (file)
@@ -124,20 +124,29 @@ static int pdo_dblib_stmt_next_rowset_no_cancel(pdo_stmt_t *stmt)
        pdo_dblib_stmt *S = (pdo_dblib_stmt*)stmt->driver_data;
        pdo_dblib_db_handle *H = S->H;
        RETCODE ret;
+       int num_fields;
+
+       do {
+               ret = dbresults(H->link);
+               num_fields = dbnumcols(H->link);
+       } while (H->skip_empty_rowsets && num_fields <= 0 && ret == SUCCEED);
 
-       ret = dbresults(H->link);
 
        if (FAIL == ret) {
                pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "PDO_DBLIB: dbresults() returned FAIL");
                return 0;
        }
 
-       if(NO_MORE_RESULTS == ret) {
+       if (NO_MORE_RESULTS == ret) {
+               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;
 }
index 1732cd75f9d5032b15f4b6ea6b234683165bdde6..d6a0eda07b47f4e83c97fb5274c8926fca831668 100644 (file)
@@ -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;
index c40697680f3162185427e8efba006d9f45cb5b15..1b59dd3a38164b039c7008df5b9fa94d572d2aa7 100644 (file)
@@ -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 (file)
index 0000000..9893661
--- /dev/null
@@ -0,0 +1,60 @@
+--TEST--
+PDO_DBLIB: PDO::DBLIB_ATTR_SKIP_EMPTY_ROWSETS for skip junk resultsets on SET NOCOUNT expression
+--SKIPIF--
+<?php
+if (!extension_loaded('pdo_dblib')) die('skip not loaded');
+require dirname(__FILE__) . '/config.inc';
+?>
+--FILE--
+<?php
+require dirname(__FILE__) . '/config.inc';
+
+$sql = '
+    SET NOCOUNT ON
+    SELECT 0 AS [result]
+';
+
+var_dump($db->getAttribute(PDO::DBLIB_ATTR_SKIP_EMPTY_ROWSETS));
+
+$stmt = $db->query($sql);
+var_dump($stmt->fetchAll(PDO::FETCH_ASSOC));
+var_dump($stmt->nextRowset());
+var_dump($stmt->fetchAll(PDO::FETCH_ASSOC));
+$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));
+var_dump($stmt->nextRowset());
+var_dump($stmt->fetchAll(PDO::FETCH_ASSOC));
+$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)