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