1--TEST-- 2PDO->beginTransaction() 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(); 9if (false == MySQLPDOTest::detect_transactional_mysql_engine($db)) 10 die("skip Transactional engine not found"); 11?> 12--FILE-- 13<?php 14 require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'mysql_pdo_test.inc'); 15 $db = MySQLPDOTest::factory(); 16 MySQLPDOTest::createTestTable($db, MySQLPDOTest::detect_transactional_mysql_engine($db)); 17 18 if (1 !== $db->getAttribute(PDO::ATTR_AUTOCOMMIT)) 19 printf("[001] Autocommit should be on by default\n"); 20 21 if (false == $db->beginTransaction()) 22 printf("[002] Cannot start a transaction, [%s] [%s]\n", 23 $db->errorCode(), implode(' ', $db->errorInfo())); 24 25 if (1 !== $db->getAttribute(PDO::ATTR_AUTOCOMMIT)) 26 printf("[003] Autocommit should be on by default, beginTransaction() shall not impact it\n"); 27 28 if (0 == $db->exec('DELETE FROM test')) 29 printf("[004] No rows deleted, can't be true.\n"); 30 31 /* This is the PDO way to close a connection */ 32 $db = null; 33 $db = MySQLPDOTest::factory(); 34 35 /* Autocommit was off - by definition. Commit was not issued. DELETE should have been rolled back. */ 36 if (!($stmt = $db->query('SELECT id, label FROM test ORDER BY id ASC'))) 37 printf("[005] [%s] %s\n", $db->errorCode(), implode(' ', $db->errorInfo())); 38 39 $row = $stmt->fetch(PDO::FETCH_ASSOC); 40 var_dump($row); 41 42 if (!$db->beginTransaction()) 43 printf("[006] [%s] %s\n", $db->errorCode(), implode(' ', $db->errorInfo())); 44 45 if (1 !== $db->exec(sprintf('DELETE FROM test WHERE id = %d', $row['id']))) 46 printf("[007] DELETE should have indicated 1 deleted row, [%s] %s\n", $db->errorCode(), implode(' ', $db->errorInfo())); 47 48 if (!$db->commit()) 49 printf("[008] [%s] %s\n", $db->errorCode(), implode(' ', $db->errorInfo())); 50 51 if (1 !== $db->getAttribute(PDO::ATTR_AUTOCOMMIT)) 52 printf("[009] Autocommit should be on after commit()\n"); 53 54 if (!($stmt = $db->query(sprintf('SELECT id, label FROM test WHERE id = %d', $row['id'])))) 55 printf("[010] [%s] %s\n", $db->errorCode(), implode(' ', $db->errorInfo())); 56 57 var_dump($stmt->fetch(PDO::FETCH_ASSOC)); 58 59 if (!$db->beginTransaction()) 60 printf("[011] [%s] %s\n", $db->errorCode(), implode(' ', $db->errorInfo())); 61 62 $db->exec(sprintf("INSERT INTO test(id, label) VALUES (%d, 'z')", $row['id'])); 63 64 if (!($stmt = $db->query(sprintf('SELECT id, label FROM test WHERE id = %d', $row['id'])))) 65 printf("[012] [%s] %s\n", $db->errorCode(), implode(' ', $db->errorInfo())); 66 67 $new_row1 = $stmt->fetch(PDO::FETCH_ASSOC); 68 var_dump($new_row1); 69 70 if (!$db->commit()) 71 printf("[013] [%s] %s\n", $db->errorCode(), implode(' ', $db->errorInfo())); 72 73 if (!($stmt = $db->query(sprintf('SELECT id, label FROM test WHERE id = %d', $row['id'])))) 74 printf("[014] [%s] %s\n", $db->errorCode(), implode(' ', $db->errorInfo())); 75 76 $new_row2 = $stmt->fetch(PDO::FETCH_ASSOC); 77 if ($new_row1 != $new_row2) { 78 printf("[015] Results must not differ!\n"); 79 var_dump($new_row1); 80 var_dump($new_row2); 81 } 82 83 if (!$db->beginTransaction()) 84 printf("[016] [%s] %s\n", $db->errorCode(), implode(' ', $db->errorInfo())); 85 86 if (1 !== $db->exec(sprintf('DELETE FROM test WHERE id = %d', $row['id']))) 87 printf("[017] DELETE should have indicated 1 deleted row, [%s] %s\n", $db->errorCode(), implode(' ', $db->errorInfo())); 88 89 if (!$db->rollback()) 90 printf("[018] [%s] %s\n", $db->errorCode(), implode(' ', $db->errorInfo())); 91 92 if (1 !== $db->getAttribute(PDO::ATTR_AUTOCOMMIT)) 93 printf("[019] Autocommit should be on after rollback\n"); 94 95 if (!($stmt = $db->query(sprintf('SELECT id, label FROM test WHERE id = %d', $row['id'])))) 96 printf("[020] [%s] %s\n", $db->errorCode(), implode(' ', $db->errorInfo())); 97 98 $new_row2 = $stmt->fetch(PDO::FETCH_ASSOC); 99 if ($new_row1 != $new_row2) { 100 printf("[021] Results must not differ!\n"); 101 var_dump($new_row1); 102 var_dump($new_row2); 103 } 104 105 // now, lets check the server variables 106 if (!($stmt = $db->query('SELECT @@autocommit as auto_commit'))) 107 printf("[022] [%s] %s\n", $db->errorCode(), implode(' ', $db->errorInfo())); 108 109 $tmp = $stmt->fetch(PDO::FETCH_ASSOC); 110 if ($tmp['auto_commit'] != 1) 111 printf("[023] MySQL Server should indicate autocommit mode, expecting 1, got '%s', [%d] %s\n", 112 $tmp['auto_commit'], $stmt->errorCode(), $stmt->errorInfo()); 113 114 if (!$db->beginTransaction()) 115 printf("[024] [%s] %s\n", $db->errorCode(), implode(' ', $db->errorInfo())); 116 117 if (!($stmt = $db->query('SELECT @@autocommit as auto_commit'))) 118 printf("[025] [%s] %s\n", $db->errorCode(), implode(' ', $db->errorInfo())); 119 120 $tmp = $stmt->fetch(PDO::FETCH_ASSOC); 121 if ($tmp['auto_commit'] != 0) 122 printf("[026] Autocommit mode of the MySQL Server should be off, got '%s', [%d] %s\n", 123 $tmp['auto_commit'], $stmt->errorCode(), trim(implode(' ', $stmt->errorInfo()))); 124 125 $db->commit(); 126 // Now we should be back to autocommit - we've issues a commit 127 if ($tmp['auto_commit'] != 1) 128 printf("[027] MySQL Server should indicate autocommit mode, expecting 1, got '%s', [%d] %s\n", 129 $tmp['auto_commit'], $stmt->errorCode(), $stmt->errorInfo()); 130 131 // Turn off autocommit using a server variable 132 $db->exec('SET @@autocommit = 0'); 133 if (1 === $db->getAttribute(PDO::ATTR_AUTOCOMMIT)) 134 printf("[028] I'm confused, how can autocommit be on? Didn't I say I want to manually control transactions?\n"); 135 136 if (!$db->beginTransaction()) 137 printf("[029] Cannot start a transaction, [%d] %s\n", 138 $db->errorCode(), implode(' ', $db->errorInfo())); 139 140 try { 141 if (false !== $db->beginTransaction()) { 142 printf("[030] No false and no exception - that's wrong.\n"); 143 } 144 } catch (PDOException $e) { 145 assert($e->getMessage() != ''); 146 } 147 148 // TODO: What about an engine that does not support transactions? 149 $db = MySQLPDOTest::factory(); 150 MySQLPDOTest::createTestTable($db, 'MyISAM'); 151 152 if (false == $db->beginTransaction()) 153 printf("[031] Cannot start a transaction, [%s] [%s]\n", 154 $db->errorCode(), implode(' ', $db->errorInfo())); 155 156 if (1 !== $db->getAttribute(PDO::ATTR_AUTOCOMMIT)) 157 printf("[032] Autocommit should be on my default, beginTransaction() should not change that\n"); 158 159 if (0 == $db->exec('DELETE FROM test')) 160 printf("[033] No rows deleted, can't be true.\n"); 161 162 if (!$db->commit()) 163 printf("[034] [%s] %s\n", $db->errorCode(), implode(' ', $db->errorInfo())); 164 165 if (false == $db->beginTransaction()) 166 printf("[035] Cannot start a transaction, [%s] [%s]\n", 167 $db->errorCode(), implode(' ', $db->errorInfo())); 168 169 if (0 == $db->exec("INSERT INTO test(id, label) VALUES (1, 'a')")) 170 printf("[036] Cannot insert data, [%s] [%s]\n", 171 $db->errorCode(), implode(' ', $db->errorInfo())); 172 173 // Should cause a Server warning but no error 174 if (!$db->rollback()) 175 printf("[037] [%s] %s\n", $db->errorCode(), implode(' ', $db->errorInfo())); 176 177 var_dump($db->errorCode()); 178 179 if (1 != $db->exec('DELETE FROM test')) 180 printf("[038] No rows deleted, can't be true.\n"); 181 182 print "done!"; 183?> 184--CLEAN-- 185<?php 186require dirname(__FILE__) . '/mysql_pdo_test.inc'; 187MySQLPDOTest::dropTestTable(); 188?> 189--EXPECT-- 190array(2) { 191 ["id"]=> 192 string(1) "1" 193 ["label"]=> 194 string(1) "a" 195} 196bool(false) 197array(2) { 198 ["id"]=> 199 string(1) "1" 200 ["label"]=> 201 string(1) "z" 202} 203[026] Autocommit mode of the MySQL Server should be off, got '1', [0] 00000 204[028] I'm confused, how can autocommit be on? Didn't I say I want to manually control transactions? 205string(5) "00000" 206done! 207