wez Fri Jul 8 23:52:41 2005 EDT Modified files: /php-src/ext/pdo pdo_stmt.c php_pdo_driver.h /php-src/ext/pdo/tests pdo_016.phpt pdo_018.phpt pdo_021.phpt Log: Added: 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); http://cvs.php.net/diff.php/php-src/ext/pdo/pdo_stmt.c?r1=1.107&r2=1.108&ty=u Index: php-src/ext/pdo/pdo_stmt.c diff -u php-src/ext/pdo/pdo_stmt.c:1.107 php-src/ext/pdo/pdo_stmt.c:1.108 --- php-src/ext/pdo/pdo_stmt.c:1.107 Fri Jul 8 13:00:28 2005 +++ php-src/ext/pdo/pdo_stmt.c Fri Jul 8 23:52:39 2005 @@ -18,7 +18,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: pdo_stmt.c,v 1.107 2005/07/08 17:00:28 wez Exp $ */ +/* $Id: pdo_stmt.c,v 1.108 2005/07/09 03:52:39 wez Exp $ */ /* The PDO Statement Handle Class */ @@ -1681,17 +1681,13 @@ /* {{{ 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 @@ 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 @@ } /* }}} */ +/* {{{ 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 @@ 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} }; http://cvs.php.net/diff.php/php-src/ext/pdo/php_pdo_driver.h?r1=1.63&r2=1.64&ty=u Index: php-src/ext/pdo/php_pdo_driver.h diff -u php-src/ext/pdo/php_pdo_driver.h:1.63 php-src/ext/pdo/php_pdo_driver.h:1.64 --- php-src/ext/pdo/php_pdo_driver.h:1.63 Fri Jul 8 15:28:52 2005 +++ php-src/ext/pdo/php_pdo_driver.h Fri Jul 8 23:52:39 2005 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_pdo_driver.h,v 1.63 2005/07/08 19:28:52 wez Exp $ */ +/* $Id: php_pdo_driver.h,v 1.64 2005/07/09 03:52:39 wez Exp $ */ #ifndef PHP_PDO_DRIVER_H #define PHP_PDO_DRIVER_H @@ -44,7 +44,7 @@ # 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 @@ * 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 @@ 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; }; /* }}} */ http://cvs.php.net/diff.php/php-src/ext/pdo/tests/pdo_016.phpt?r1=1.7&r2=1.8&ty=u Index: php-src/ext/pdo/tests/pdo_016.phpt diff -u php-src/ext/pdo/tests/pdo_016.phpt:1.7 php-src/ext/pdo/tests/pdo_016.phpt:1.8 --- php-src/ext/pdo/tests/pdo_016.phpt:1.7 Thu Jul 7 14:49:58 2005 +++ php-src/ext/pdo/tests/pdo_016.phpt Fri Jul 8 23:52:41 2005 @@ -18,15 +18,12 @@ $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 @@ $stmt3->bindColumn('txt', $col1); } var_dump($stmt3->fetch(PDO_FETCH_BOUND)); + $stmt3->closeCursor(); var_dump($stmt4->execute()); if ($idx == 0) { @@ -69,6 +67,7 @@ $stmt4->bindColumn('idx', $col2); } var_dump($stmt4->fetch(PDO_FETCH_BOUND)); + $stmt4->closeCursor(); var_dump(array($col2=>$col1)); } @@ -81,9 +80,11 @@ 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); } http://cvs.php.net/diff.php/php-src/ext/pdo/tests/pdo_018.phpt?r1=1.8&r2=1.9&ty=u Index: php-src/ext/pdo/tests/pdo_018.phpt diff -u php-src/ext/pdo/tests/pdo_018.phpt:1.8 php-src/ext/pdo/tests/pdo_018.phpt:1.9 --- php-src/ext/pdo/tests/pdo_018.phpt:1.8 Fri Jul 8 11:21:43 2005 +++ php-src/ext/pdo/tests/pdo_018.phpt Fri Jul 8 23:52:41 2005 @@ -77,10 +77,6 @@ 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; http://cvs.php.net/diff.php/php-src/ext/pdo/tests/pdo_021.phpt?r1=1.7&r2=1.8&ty=u Index: php-src/ext/pdo/tests/pdo_021.phpt diff -u php-src/ext/pdo/tests/pdo_021.phpt:1.7 php-src/ext/pdo/tests/pdo_021.phpt:1.8 --- php-src/ext/pdo/tests/pdo_021.phpt:1.7 Thu Jul 7 14:49:58 2005 +++ php-src/ext/pdo/tests/pdo_021.phpt Fri Jul 8 23:52:41 2005 @@ -36,7 +36,7 @@ $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)");
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php