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