]> granicus.if.org Git - php/commitdiff
Added:
authorWez Furlong <wez@php.net>
Sat, 9 Jul 2005 03:52:41 +0000 (03:52 +0000)
committerWez Furlong <wez@php.net>
Sat, 9 Jul 2005 03:52:41 +0000 (03:52 +0000)
proto bool PDOStatement::closeCursor()
Closes the cursor, leaving the statement ready for re-execution.

The purpose of the function is to free up the connection to the server so that
other queries may be issued, but leaving the statement in a state that it can
be re-executed.

This is implemented either as an optional driver specific method (allowing for
maximum efficiency), or as the generic PDO fallback if no driver specific
function is installed.

The PDO generic fallback is semantically the same as writing the following code
in your PHP script:

do {
while ($stmt->fetch())
;
if (!$stmt->nextRowset())
break;
} while (true);

ext/pdo/pdo_stmt.c
ext/pdo/php_pdo_driver.h
ext/pdo/tests/pdo_016.phpt
ext/pdo/tests/pdo_018.phpt
ext/pdo/tests/pdo_021.phpt

index 51770d3130d9efff5cb412eb73dc2c5818f5be55..c6e4b481a5b124419426d37412c39a15e02e09b7 100755 (executable)
@@ -1681,17 +1681,13 @@ static PHP_METHOD(PDOStatement, setFetchMode)
 
 /* {{{ proto bool PDOStatement::nextRowset()
    Advances to the next rowset in a multi-rowset statement handle. Returns true if it succeded, false otherwise */
-static PHP_METHOD(PDOStatement, nextRowset)
-{
-       pdo_stmt_t *stmt = (pdo_stmt_t*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
-       if (!stmt->methods->next_rowset) {
-               pdo_raise_impl_error(stmt->dbh, stmt, "IM001", "driver does not support multiple rowsets" TSRMLS_CC);
-               RETURN_FALSE;
+static int pdo_stmt_do_next_rowset(pdo_stmt_t *stmt TSRMLS_DC)
+{
+       if (!stmt->methods->next_rowset(stmt TSRMLS_CC)) {
+               return 0;
        }
 
-       PDO_STMT_CLEAR_ERR();
-
        /* un-describe */
        if (stmt->columns) {
                int i;
@@ -1701,11 +1697,27 @@ static PHP_METHOD(PDOStatement, nextRowset)
                        efree(cols[i].name);
                }
                efree(stmt->columns);
+               stmt->columns = NULL;
+               stmt->column_count = 0;
        }
-       stmt->columns = NULL;
 
-       if (!stmt->methods->next_rowset(stmt TSRMLS_CC)) {
-               stmt->column_count = 0;
+       pdo_stmt_describe_columns(stmt TSRMLS_CC);
+
+       return 1;
+}
+
+static PHP_METHOD(PDOStatement, nextRowset)
+{
+       pdo_stmt_t *stmt = (pdo_stmt_t*)zend_object_store_get_object(getThis() TSRMLS_CC);
+
+       if (!stmt->methods->next_rowset) {
+               pdo_raise_impl_error(stmt->dbh, stmt, "IM001", "driver does not support multiple rowsets" TSRMLS_CC);
+               RETURN_FALSE;
+       }
+
+       PDO_STMT_CLEAR_ERR();
+       
+       if (!pdo_stmt_do_next_rowset(stmt TSRMLS_CC)) {
                PDO_HANDLE_STMT_ERR();
                RETURN_FALSE;
        }
@@ -1716,6 +1728,41 @@ static PHP_METHOD(PDOStatement, nextRowset)
 }
 /* }}} */
 
+/* {{{ proto bool PDOStatement::closeCursor()
+   Closes the cursor, leaving the statement ready for re-execution. */
+static PHP_METHOD(PDOStatement, closeCursor)
+{
+       pdo_stmt_t *stmt = (pdo_stmt_t*)zend_object_store_get_object(getThis() TSRMLS_CC);
+
+       if (!stmt->methods->cursor_closer) {
+               /* emulate it by fetching and discarding rows */
+               do {
+                       while (stmt->methods->fetcher(stmt, PDO_FETCH_ORI_NEXT, 0 TSRMLS_CC))
+                               ;
+                       if (!stmt->methods->next_rowset) {
+                               break;
+                       }
+
+                       if (!pdo_stmt_do_next_rowset(stmt TSRMLS_CC)) {
+                               break;
+                       }
+                               
+               } while (1);
+               RETURN_TRUE;
+       }
+
+       PDO_STMT_CLEAR_ERR();
+
+       if (!stmt->methods->cursor_closer(stmt TSRMLS_CC)) {
+               PDO_HANDLE_STMT_ERR();
+               RETURN_FALSE;
+       }
+
+       RETURN_TRUE;
+}
+/* }}} */
+
+
 function_entry pdo_dbstmt_functions[] = {
        PHP_ME(PDOStatement, execute,           NULL,                                   ZEND_ACC_PUBLIC)
        PHP_ME(PDOStatement, fetch,                     NULL,                                   ZEND_ACC_PUBLIC)
@@ -1733,6 +1780,7 @@ function_entry pdo_dbstmt_functions[] = {
        PHP_ME(PDOStatement, getColumnMeta,     NULL,                                   ZEND_ACC_PUBLIC)
        PHP_ME(PDOStatement, setFetchMode,      NULL,                                   ZEND_ACC_PUBLIC)
        PHP_ME(PDOStatement, nextRowset,        NULL,                                   ZEND_ACC_PUBLIC)
+       PHP_ME(PDOStatement, closeCursor,       NULL,                                   ZEND_ACC_PUBLIC)
        {NULL, NULL, NULL}
 };
 
index d0259e5b3097187fd61d3f8598dea15fd80e3ee3..0f0b115ac1a8c705c2e48a1bc26d401044f9f8b7 100755 (executable)
@@ -44,7 +44,7 @@ PDO_API char *php_pdo_int64_to_str(pdo_int64_t i64 TSRMLS_DC);
 # define FALSE 0
 #endif
 
-#define PDO_DRIVER_API 20050708
+#define PDO_DRIVER_API 20050709
 
 enum pdo_param_type {
        PDO_PARAM_NULL,
@@ -367,6 +367,12 @@ typedef int (*pdo_stmt_get_column_meta_func)(pdo_stmt_t *stmt, long colno, zval
  * to the caller. */
 typedef int (*pdo_stmt_next_rowset_func)(pdo_stmt_t *stmt TSRMLS_DC);
 
+/* closes the active cursor on a statement, leaving the prepared
+ * statement ready for re-execution.  Useful to explicitly state
+ * that you are done with a given rowset, without having to explicitly
+ * fetch all the rows. */
+typedef int (*pdo_stmt_cursor_closer_func)(pdo_stmt_t *stmt TSRMLS_DC);
+
 struct pdo_stmt_methods {
        pdo_stmt_dtor_func                      dtor;
        pdo_stmt_execute_func           executer;
@@ -378,6 +384,7 @@ struct pdo_stmt_methods {
        pdo_stmt_get_attr_func          get_attribute;
        pdo_stmt_get_column_meta_func get_column_meta;
        pdo_stmt_next_rowset_func               next_rowset;
+       pdo_stmt_cursor_closer_func     cursor_closer;
 };
 
 /* }}} */
index f6f7cea17773b330ba393a88e48e7a44349ad2c4..e2faf05c46d5f18aecc7e24bbda42f03fcd4fbca 100644 (file)
@@ -18,15 +18,12 @@ $db->exec('INSERT INTO test VALUES(0, \'String0\')');
 $db->exec('INSERT INTO test VALUES(1, \'String1\')');
 $db->exec('INSERT INTO test VALUES(2, \'String2\')');
 
-if ($db->getAttribute(PDO_ATTR_DRIVER_NAME) == 'mysql') {
-       $db->setAttribute(PDO_MYSQL_ATTR_USE_BUFFERED_QUERY, 1);
-}
-
 $stmt1 = $db->prepare('SELECT COUNT(idx) FROM test');
 $stmt2 = $db->prepare('SELECT idx, txt FROM test ORDER by idx');
 
 $stmt1->execute();
 var_dump($stmt1->fetchColumn());
+$stmt1 = null;
 
 $stmt2->execute();
 $cont = $stmt2->fetchAll(PDO_FETCH_COLUMN|PDO_FETCH_UNIQUE);
@@ -61,6 +58,7 @@ foreach($cont as $idx => $txt)
                $stmt3->bindColumn('txt', $col1);
        }
        var_dump($stmt3->fetch(PDO_FETCH_BOUND));
+       $stmt3->closeCursor();
 
        var_dump($stmt4->execute());
        if ($idx == 0) {
@@ -69,6 +67,7 @@ foreach($cont as $idx => $txt)
                $stmt4->bindColumn('idx', $col2);
        }
        var_dump($stmt4->fetch(PDO_FETCH_BOUND));
+       $stmt4->closeCursor();
        var_dump(array($col2=>$col1));
 }
 
@@ -81,9 +80,11 @@ foreach($cont as $idx => $txt)
        var_dump(array($idx=>$txt));
        var_dump($stmt3->execute());
        var_dump($stmt3->fetch(PDO_FETCH_BOUND));
+       $stmt3->closeCursor();
        var_dump($col1);
        var_dump($stmt4->execute());
        var_dump($stmt4->fetch(PDO_FETCH_BOUND));
+       $stmt4->closeCursor();
        var_dump($col1);
 }
 
index b0fc07e5b5a3aee47f3279d9ba500b3806d17bd8..6c45869bd8cba755f6d2d5a8e85ee29cc0a5ed61 100644 (file)
@@ -77,10 +77,6 @@ $db->setAttribute(PDO_ATTR_ERRMODE, PDO_ERRMODE_EXCEPTION);
 var_dump($db->query('SELECT COUNT(*) FROM classtypes')->fetchColumn());
 var_dump($db->query('SELECT id, name FROM classtypes ORDER by id')->fetchAll(PDO_FETCH_COLUMN|PDO_FETCH_UNIQUE));
 
-if ($db->getAttribute(PDO_ATTR_DRIVER_NAME) == 'mysql') {
-       $db->setAttribute(PDO_MYSQL_ATTR_USE_BUFFERED_QUERY, 1);
-}
-
 $objs = array();
 $objs[0] = new stdClass;
 $objs[1] = new TestBase;
index c2ac95dbe77d932b72677b3d51bfc575431da75c..c1688c092b58ba8b48273d22a58cd8c66acf75a2 100644 (file)
@@ -36,7 +36,7 @@ $select->execute();
 $num = $select->fetchColumn();
 echo 'There are ' . $num . " rows in the table.\n";
 
-unset($stmt);
+$select->closeCursor();
 
 // Insert using named parameters
 $stmt2 = $db->prepare("INSERT INTO test VALUES(:first, :second, :third)");