Skip to content

Commit fcfa7fd

Browse files
committed
Fixed bug #66878
Keep track of whether we have fully consumed all result sets, either using nextRowset() calls or closeCursor() and skip the attempt to consume remaining results sets during destruction in that case. Especiall if closeCursor() has been used, we really shouldn't have this sort of cross-statement inference.
1 parent ef342b0 commit fcfa7fd

File tree

4 files changed

+47
-1
lines changed

4 files changed

+47
-1
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ PHP NEWS
4343
statements). (Nikita)
4444
. Fixed bug #78152 (PDO::exec() - Bad error handling with multiple commands).
4545
(Nikita)
46+
. Fixed bug #66878 (Multiple rowsets not returned unless PDO statement object
47+
is unset()). (Nikita)
4648

4749
- Phar:
4850
. Fixed bug #73809 (Phar Zip parse crash - mmap fail). (cmb)

ext/pdo_mysql/mysql_statement.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ static int pdo_mysql_stmt_dtor(pdo_stmt_t *stmt) /* {{{ */
8484
}
8585
#endif
8686

87-
if (!Z_ISUNDEF(stmt->database_object_handle)
87+
if (!S->done && !Z_ISUNDEF(stmt->database_object_handle)
8888
&& IS_OBJ_VALID(EG(objects_store).object_buckets[Z_OBJ_HANDLE(stmt->database_object_handle)])
8989
&& (!(OBJ_FLAGS(Z_OBJ(stmt->database_object_handle)) & IS_OBJ_FREE_CALLED))) {
9090
while (mysql_more_results(S->H->server)) {
@@ -326,6 +326,7 @@ static int pdo_mysql_stmt_execute(pdo_stmt_t *stmt) /* {{{ */
326326
PDO_DBG_ENTER("pdo_mysql_stmt_execute");
327327
PDO_DBG_INF_FMT("stmt=%p", S->stmt);
328328

329+
S->done = 0;
329330
if (S->stmt) {
330331
PDO_DBG_RETURN(pdo_mysql_stmt_execute_prepared(stmt));
331332
}
@@ -365,6 +366,7 @@ static int pdo_mysql_stmt_next_rowset(pdo_stmt_t *stmt) /* {{{ */
365366
if (!H->emulate_prepare) {
366367
if (mysqlnd_stmt_next_result(S->stmt)) {
367368
pdo_mysql_error_stmt(stmt);
369+
S->done = 1;
368370
PDO_DBG_RETURN(0);
369371
}
370372

@@ -374,6 +376,7 @@ static int pdo_mysql_stmt_next_rowset(pdo_stmt_t *stmt) /* {{{ */
374376

375377
if (mysql_next_result(H->server)) {
376378
pdo_mysql_error_stmt(stmt);
379+
S->done = 1;
377380
PDO_DBG_RETURN(0);
378381
} else {
379382
PDO_DBG_RETURN(pdo_mysql_fill_stmt_from_result(stmt));
@@ -842,6 +845,8 @@ static int pdo_mysql_stmt_cursor_closer(pdo_stmt_t *stmt) /* {{{ */
842845

843846
PDO_DBG_ENTER("pdo_mysql_stmt_cursor_closer");
844847
PDO_DBG_INF_FMT("stmt=%p", S->stmt);
848+
849+
S->done = 1;
845850
if (S->result) {
846851
mysql_free_result(S->result);
847852
S->result = NULL;

ext/pdo_mysql/php_pdo_mysql_int.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,9 @@ typedef struct {
142142
zend_ulong *out_length;
143143
unsigned int params_given;
144144
unsigned max_length:1;
145+
/* Whether all result sets have been fully consumed.
146+
* If this flag is not set, they need to be consumed during destruction. */
147+
unsigned done:1;
145148
} pdo_mysql_stmt;
146149

147150
extern const pdo_driver_t pdo_mysql_driver;

ext/pdo_mysql/tests/bug66878.phpt

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
--TEST--
2+
Bug #66878: Multiple rowsets not returned unless PDO statement object is unset()
3+
--SKIPIF--
4+
<?php
5+
require_once(__DIR__ . DIRECTORY_SEPARATOR . 'skipif.inc');
6+
require_once(__DIR__ . DIRECTORY_SEPARATOR . 'mysql_pdo_test.inc');
7+
MySQLPDOTest::skip();
8+
?>
9+
--FILE--
10+
<?php
11+
require_once(__DIR__ . DIRECTORY_SEPARATOR . 'mysql_pdo_test.inc');
12+
13+
$pdo = MySQLPDOTest::factory();
14+
15+
$sql = 'SELECT 123; SELECT 42; SELECT 999';
16+
17+
$stmt = $pdo->query($sql);
18+
var_dump($stmt->nextRowset());
19+
var_dump($stmt->nextRowset());
20+
var_dump($stmt->nextRowset());
21+
$stmt->closeCursor();
22+
23+
$stmt = $pdo->query($sql);
24+
var_dump($stmt->nextRowset());
25+
var_dump($stmt->nextRowset());
26+
var_dump($stmt->nextRowset());
27+
$stmt->closeCursor();
28+
29+
?>
30+
--EXPECT--
31+
bool(true)
32+
bool(true)
33+
bool(false)
34+
bool(true)
35+
bool(true)
36+
bool(false)

0 commit comments

Comments
 (0)