1--TEST-- 2MySQL PDOStatement->closeCursor() 3--EXTENSIONS-- 4pdo_mysql 5--SKIPIF-- 6<?php 7require_once __DIR__ . '/inc/mysql_pdo_test.inc'; 8MySQLPDOTest::skip(); 9?> 10--FILE-- 11<?php 12 /* TODO the results look wrong, why do we get 2014 with buffered AND unbuffered queries */ 13 require_once __DIR__ . '/inc/mysql_pdo_test.inc'; 14 $db = MySQLPDOTest::factory(); 15 16 $table = 'pdo_mysql_stmt_closecursor'; 17 18 function pdo_mysql_stmt_closecursor($db) { 19 global $table; 20 21 // This one should fail. I let it fail to prove that closeCursor() makes a difference. 22 // If no error messages gets printed do not know if proper usage of closeCursor() makes any 23 // difference or not. That's why we need to cause an error here. 24 $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false); 25 $stmt1 = $db->query("SELECT id, label FROM {$table} ORDER BY id ASC"); 26 // query() shall fail! 27 $stmt2 = $db->query("SELECT id, label FROM {$table} ORDER BY id ASC"); 28 $stmt1->closeCursor(); 29 30 // This is proper usage of closeCursor(). It shall prevent any further error messages. 31 if (MySQLPDOTest::isPDOMySQLnd()) { 32 $stmt1 = $db->query("SELECT id, label FROM {$table} ORDER BY id ASC"); 33 } else { 34 // see pdo_mysql_stmt_unbuffered_2050.phpt for an explanation 35 unset($stmt1); 36 $stmt1 = $db->query("SELECT id, label FROM {$table} ORDER BY id ASC"); 37 } 38 // fetch only the first rows and let closeCursor() clean up 39 $row1 = $stmt1->fetch(PDO::FETCH_ASSOC); 40 $stmt1->closeCursor(); 41 42 $stmt2 = $db->prepare("UPDATE {$table} SET label = ? WHERE id = ?"); 43 $stmt2->bindValue(1, "z"); 44 45 $stmt2->bindValue(2, $row1['id']); 46 $stmt2->execute(); 47 $stmt2->closeCursor(); 48 49 $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true); 50 // check if changing the fetch mode from unbuffered to buffered will 51 // cause any harm to a statement created prior to the change 52 $stmt1->execute(); 53 $row2 = $stmt1->fetch(PDO::FETCH_ASSOC); 54 $stmt1->closeCursor(); 55 if (!isset($row2['label']) || ('z' !== $row2['label'])) 56 printf("Expecting array(id => 1, label => z) got %s\n", var_export($row2, true)); 57 unset($stmt1); 58 59 $stmt1 = $db->query("SELECT id, label FROM {$table} ORDER BY id ASC"); 60 // should work 61 $stmt2 = $db->query("SELECT id, label FROM {$table} ORDER BY id ASC"); 62 $stmt1->closeCursor(); 63 64 $stmt1 = $db->query("SELECT id, label FROM {$table} ORDER BY id ASC"); 65 // fetch only the first rows and let closeCursor() clean up 66 $row3 = $stmt1->fetch(PDO::FETCH_ASSOC); 67 $stmt1->closeCursor(); 68 assert($row3 == $row2); 69 70 $stmt2 = $db->prepare("UPDATE {$table} SET label = ? WHERE id = ?"); 71 $stmt2->bindValue(1, "a"); 72 $stmt2->bindValue(2, $row1['id']); 73 $stmt2->execute(); 74 $stmt2->closeCursor(); 75 76 $stmt1->execute(); 77 $row4 = $stmt1->fetch(PDO::FETCH_ASSOC); 78 $stmt1->closeCursor(); 79 assert($row4 == $row1); 80 81 $offset = 0; 82 $stmt = $db->prepare("SELECT id, label FROM {$table} WHERE id > ? ORDER BY id ASC LIMIT 2"); 83 $in = 0; 84 if (!$stmt->bindParam(1, $in)) 85 printf("[%03d + 1] Cannot bind parameter, %s %s\n", $offset, 86 $stmt->errorCode(), var_export($stmt->errorInfo(), true)); 87 88 $stmt->execute(); 89 $id = $label = null; 90 91 if (!$stmt->bindColumn(1, $id, PDO::PARAM_INT)) 92 printf("[%03d + 2] Cannot bind integer column, %s %s\n", $offset, 93 $stmt->errorCode(), var_export($stmt->errorInfo(), true)); 94 95 if (!$stmt->bindColumn(2, $label, PDO::PARAM_STR)) 96 printf("[%03d + 3] Cannot bind string column, %s %s\n", $offset, 97 $stmt->errorCode(), var_export($stmt->errorInfo(), true)); 98 99 while ($stmt->fetch(PDO::FETCH_BOUND)) 100 printf("in = %d -> id = %s (%s) / label = %s (%s)\n", 101 $in, 102 var_export($id, true), gettype($id), 103 var_export($label, true), gettype($label)); 104 105 $stmt->closeCursor(); 106 $stmt->execute(); 107 108 } 109 110 111 try { 112 printf("Testing emulated PS...\n"); 113 $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 1); 114 if (1 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) 115 printf("[002] Unable to turn on emulated prepared statements\n"); 116 117 printf("Buffered...\n"); 118 $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true); 119 MySQLPDOTest::createTestTable($table, $db); 120 pdo_mysql_stmt_closecursor($db); 121 122 printf("Unbuffered...\n"); 123 $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false); 124 MySQLPDOTest::createTestTable($table, $db); 125 pdo_mysql_stmt_closecursor($db); 126 127 printf("Testing native PS...\n"); 128 $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 0); 129 if (0 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) 130 printf("[002] Unable to turn off emulated prepared statements\n"); 131 132 printf("Buffered...\n"); 133 MySQLPDOTest::createTestTable($table, $db); 134 $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true); 135 pdo_mysql_stmt_closecursor($db); 136 137 printf("Unbuffered...\n"); 138 MySQLPDOTest::createTestTable($table, $db); 139 $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false); 140 pdo_mysql_stmt_closecursor($db); 141 142 } catch (PDOException $e) { 143 printf("[001] %s [%s] %s\n", 144 $e->getMessage(), $db->errorCode(), implode(' ', $db->errorInfo())); 145 } 146 147 print "done!"; 148?> 149--CLEAN-- 150<?php 151require_once __DIR__ . '/inc/mysql_pdo_test.inc'; 152$db = MySQLPDOTest::factory(); 153$db->exec('DROP TABLE IF EXISTS pdo_mysql_stmt_closecursor'); 154?> 155--EXPECTF-- 156Testing emulated PS... 157Buffered... 158 159Warning: PDO::query(): SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other unbuffered queries are active. Consider using PDOStatement::fetchAll(). Alternatively, if your code is only ever going to run against mysql, you may enable query buffering by setting the PDO::MYSQL_ATTR_USE_BUFFERED_QUERY attribute. in %s on line %d 160in = 0 -> id = 1 (integer) / label = 'a' (string) 161in = 0 -> id = 2 (integer) / label = 'b' (string) 162Unbuffered... 163 164Warning: PDO::query(): SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other unbuffered queries are active. Consider using PDOStatement::fetchAll(). Alternatively, if your code is only ever going to run against mysql, you may enable query buffering by setting the PDO::MYSQL_ATTR_USE_BUFFERED_QUERY attribute. in %s on line %d 165in = 0 -> id = 1 (integer) / label = 'a' (string) 166in = 0 -> id = 2 (integer) / label = 'b' (string) 167Testing native PS... 168Buffered... 169 170Warning: PDO::query(): SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other unbuffered queries are active. Consider using PDOStatement::fetchAll(). Alternatively, if your code is only ever going to run against mysql, you may enable query buffering by setting the PDO::MYSQL_ATTR_USE_BUFFERED_QUERY attribute. in %s on line %d 171in = 0 -> id = 1 (integer) / label = 'a' (string) 172in = 0 -> id = 2 (integer) / label = 'b' (string) 173Unbuffered... 174 175Warning: PDO::query(): SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other unbuffered queries are active. Consider using PDOStatement::fetchAll(). Alternatively, if your code is only ever going to run against mysql, you may enable query buffering by setting the PDO::MYSQL_ATTR_USE_BUFFERED_QUERY attribute. in %s on line %d 176in = 0 -> id = 1 (integer) / label = 'a' (string) 177in = 0 -> id = 2 (integer) / label = 'b' (string) 178done! 179