1
0
Fork 0
MySQLDumper/library/Msd/Sql/Parser.php
DSB 76b02c64e7 SQl-Parser:
- changes error output if statement is unknown
- QA
2011-06-20 13:55:10 +00:00

205 Zeilen
5,3 KiB
PHP

<?php
/**
* This file is part of MySQLDumper released under the GNU/GPL 2 license
* http://www.mysqldumper.net
*
* @package MySQLDumper
* @subpackage SQL-Parser
* @version SVN: $Rev$
* @author $Author$
*/
/**
* Class to parse MySQL queries.
* This enables you to analyze and modify MySQL queries, which the user has entered.
*
* @package MySQLDumper
* @subpackage SQL-Browser
*/
class Msd_Sql_Parser implements Iterator
{
/**
* Parsed MySQL statements.
*
* @var array
*/
private $_parsedStatements = array();
/**
* Holds the summary of the parsing process.
* The summary contains the count of each statement in the query.
*
* @var array
*/
private $_parsingSummary = array();
/**
* Whether to save debug output
*
* @var bool
*/
private $_debug = false;
/**
* Debug output buffer
*
* @var string
*/
private $_debugOutput = '';
/**
* Class constructor.
* Creates a new instance of the MySQL parser and optionally assign the raw MySQL query.
*
* @param Msd_Sql_Object $sqlObject SQL-Object holding the data to be parsed
* @param bool $debug If turned on, detection of queries is logged
*/
public function __construct(Msd_Sql_Object $sqlObject, $debug = false)
{
$this->_sql = $sqlObject;
$this->_debug = $debug;
}
/**
* Parses a raw MySQL query.
* This could include more than one MySQL statement.
*
* @throws Msd_Sql_Parser_Exception
*
* @return void
*/
public function parse()
{
while ($this->_sql->hasMoreToProcess() && $this->_sql->movePointerToNextCommand() !== false) {
// check for comments or conditional comments
$commentCheck = $this->_sql->getData($this->_sql->getPointer() + 3, false);
if (substr($commentCheck, 0, 2) == '--' || substr($commentCheck, 0, 2) == '/*') {
$queryType = 'Comment';
} else {
// get first "word" of query to get the kind we have to process
$endOfFirstWord = $this->_sql->getPosition(' ', false);
$sqlQuery = $this->_sql->getData($endOfFirstWord, false);
$queryType = strtolower($sqlQuery);
}
try {
$foundStatement = $this->_parseStatement($this->_sql, ucfirst($queryType));
} catch (Msd_Sql_Parser_Exception $e) {
$this->_sql->setError($e->getMessage());
// stop parsing by setting pointer to the end
$this->_sql->setPointer($this->_sql->getLength() + 1);
}
if ($foundStatement > '') {
$this->_parsedStatements[] = $foundStatement;
// increment query type counter
if (!isset($this->_parsingSummary[$queryType])) {
$this->_parsingSummary[$queryType] = 0;
}
$this->_parsingSummary[$queryType]++;
}
}
}
/**
* Creates an instance of a statement parser class and invokes statement parsing.
*
* @throws Msd_Sql_Parser_Exception
*
* @param Msd_Sql_Object $sqlObject MySQL statement to parse
* @param string $statement Parser class to use
*
* @return array
*/
private function _parseStatement(Msd_Sql_Object $sqlObject, $statement)
{
$statementPath = '/Msd/Sql/Parser/Statement/' . $statement;
if (!file_exists(LIBRARY_PATH . $statementPath . '.php')) {
throw new Msd_Sql_Parser_Exception("Unknown statement: '" . $statement . "'");
}
$statementClass = 'Msd_Sql_Parser_Statement_' . $statement;
$parserObject = new $statementClass();
return $parserObject->parse($sqlObject);
}
/**
* Returns the array with the parsed statements.
*
* @return array
*/
public function getParsedStatements()
{
return $this->_parsedStatements;
}
/**
* Returns the parsing summary.
*
* @return array
*/
public function getSummary()
{
return $this->_parsingSummary;
}
/**
* Rewind (reset) the internal pointer position af the parsed statements array.
*
* @return mixed
*/
public function rewind()
{
return reset($this->_parsedStatements);
}
/**
* Return the current value af the parsed statements array.
*
* @return mixed
*/
public function current()
{
return current($this->_parsedStatements);
}
/**
* Return the current key af the parsed statements array.
*
* @return mixed
*/
public function key()
{
return key($this->_parsedStatements);
}
/**
* Move the internal pointer af the parsed statements array to the next position.
*
* @return mixed
*/
public function next()
{
return next($this->_parsedStatements);
}
/**
* Validates the internal pointer position af the parsed statements array.
*
* @return bool
*/
public function valid()
{
return key($this->_parsedStatements) !== null;
}
/**
* Get debug output buffer
*
* @return array
*/
public function getDebugOutput()
{
return $this->_debugOutput;
}
}