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