/** * Handles request for ROLLBACK. * * @param string $sql_query SQL query(s) * * @return void */ function PMA_handleRollbackRequest($sql_query) { $sql_delimiter = $_REQUEST['sql_delimiter']; $queries = explode($sql_delimiter, $sql_query); $error = false; $error_msg = __('Only INSERT, UPDATE, DELETE and REPLACE ' . 'SQL queries containing transactional engine tables can be rolled back.'); foreach ($queries as $sql_query) { if (empty($sql_query)) { continue; } // Check each query for ROLLBACK support. if (!PMA_checkIfRollbackPossible($sql_query)) { $global_error = $GLOBALS['dbi']->getError(); if ($global_error) { $error = $global_error; } else { $error = $error_msg; } break; } } if ($error) { unset($_REQUEST['rollback_query']); $response = PMA_Response::getInstance(); $message = PMA_Message::rawError($error); $response->addJSON('message', $message); exit; } else { // If everything fine, START a transaction. $GLOBALS['dbi']->query('START TRANSACTION'); } }
/** * Test for PMA_checkIfRollbackPossible * * @return void */ function testPMACheckIfRollbackPossible() { $GLOBALS['db'] = 'PMA'; //mock DBI $dbi = $this->getMockBuilder('PMA\\libraries\\DatabaseInterface')->disableOriginalConstructor()->getMock(); // List of Transactional Engines. $transactional_engines = array('INNODB', 'FALCON', 'NDB', 'INFINIDB', 'TOKUDB', 'XTRADB', 'SEQUENCE', 'BDB'); $check_query = 'SELECT `ENGINE` FROM `information_schema`.`tables` ' . 'WHERE `table_name` = "%s" ' . 'AND `table_schema` = "%s" ' . 'AND UPPER(`engine`) IN ("' . implode('", "', $transactional_engines) . '")'; $check_table_query = 'SELECT * FROM `%s`.`%s` ' . 'LIMIT 1'; $dbi->expects($this->at(0))->method('tryQuery')->with(sprintf($check_table_query, 'PMA', 'table_1'))->will($this->returnValue(array('table'))); $dbi->expects($this->at(1))->method('tryQuery')->with(sprintf($check_query, 'table_1', 'PMA'))->will($this->returnValue(true)); $dbi->expects($this->at(2))->method('numRows')->will($this->returnValue(1)); $dbi->expects($this->at(3))->method('tryQuery')->with(sprintf($check_table_query, 'PMA', 'table_2'))->will($this->returnValue(array('table'))); $dbi->expects($this->at(4))->method('tryQuery')->with(sprintf($check_query, 'table_2', 'PMA'))->will($this->returnValue(true)); $dbi->expects($this->at(5))->method('numRows')->will($this->returnValue(1)); $GLOBALS['dbi'] = $dbi; $sql_query = 'UPDATE `table_1` AS t1, `table_2` t2 ' . 'SET `table_1`.`id` = `table_2`.`id` ' . 'WHERE 1'; $this->assertEquals(true, PMA_checkIfRollbackPossible($sql_query)); }