diff --git a/application/controllers/SqlController.php b/application/controllers/SqlController.php
index 7d85945..52d18ef 100644
--- a/application/controllers/SqlController.php
+++ b/application/controllers/SqlController.php
@@ -388,9 +388,10 @@ class SqlController extends Zend_Controller_Action
$query = trim($query);
if ($query > '') {
$this->_db->selectDb($config->get('dynamic.dbActual'));
- $parser = new Msd_Sql_Parser($query, true);
+ $sqlObject = new Msd_Sql_Object($query);
+ $parser = new Msd_Sql_Parser($sqlObject, true);
$parser->parse();
- print_r($parser->getDebugOutput());
+ //echo $parser->getDebugOutput();
$statements = $parser->getParsedStatements();
foreach ($statements as $statement) {
try {
diff --git a/library/Msd/Sql/Object.php b/library/Msd/Sql/Object.php
new file mode 100644
index 0000000..bf606db
--- /dev/null
+++ b/library/Msd/Sql/Object.php
@@ -0,0 +1,208 @@
+_data = $sqlData;
+ }
+
+ /**
+ * Sets data of object
+ *
+ * @param string $sqlData The queries
+ *
+ * @return void
+ */
+ public function setData($sqlData = '')
+ {
+ $this->_data = $sqlData;
+ }
+
+ /**
+ * Append data to already given data.
+ *
+ * @param string $sqlData The sql-string to be appended
+ *
+ * @return void
+ */
+ private function appendData($sqlData)
+ {
+ $this->_data .= $sqlData;
+ }
+
+ /**
+ * Get the actual position of the pointer.
+ *
+ * @return int Pointer position
+ */
+ public function getPointer()
+ {
+ return $this->_pointer;
+ }
+
+ /**
+ * Set the actual position of the pointer.
+ *
+ * @param int $position Position of pointer
+ *
+ * @return void
+ */
+ public function setPointer($position)
+ {
+ $this->_pointer = $position;
+ }
+
+ /**
+ * Move pointer to the beginning of the next command.
+ *
+ * Skip all spaces and line-breaks until a character is found that might be the beginning
+ * of a new sql command.
+ *
+ * @return int New pointer position
+ */
+ public function movePointerToNextCommand()
+ {
+ $pointer = $this->getPointer();
+ $dataSize = strlen($this->_data);
+ $skip = array(';', ' ', "\n", "\r");
+ while ($pointer < $dataSize && in_array($this->_data[$pointer], $skip)) {
+ $pointer++;
+ }
+ $this->setPointer($pointer);
+ return $pointer;
+ }
+
+ /**
+ * Get some characters of data.
+ *
+ * @param int $nrOfCharacters Number of characters to get
+ *
+ * @return string Sql data from the pointer position to end or to the nr of chars to fetch
+ */
+ public function getData($nrOfCharacters = null)
+ {
+ if ($nrOfCharacters > 0) {
+ return substr($this->_data, $this->_pointer, $nrOfCharacters);
+ } else {
+ return substr($this->_data, $this->_pointer);
+ }
+ }
+
+ /**
+ * Get length of data string.
+ *
+ * @return int Length of data string
+ */
+ public function getLength()
+ {
+ return strlen($this->_data);
+ }
+
+ /**
+ * Check if pointer has reached the end of the data string.
+ *
+ * @return bool
+ */
+ public function hasMoreToProcess()
+ {
+ if ($this->_pointer < $this->getLength()) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Set the parser state.
+ *
+ * @param string $state The parsing state we are actually in.
+ *
+ * @return void
+ */
+ public function setState($state)
+ {
+ $this->_state = $state;
+ }
+
+ /**
+ * Find the next unescaped occurance of $match.
+ *
+ * Begins to search at the actual postion of the pointer.
+ *
+ * @param string $match
+ *
+ * @return int
+ */
+ public function getPosition($match = ';')
+ {
+ $pointer = $this->getPointer();
+ $offset = $pointer;
+ $notFound = true;
+ $length = $this->getLength()-1;
+ while ($notFound && $offset < $length) {
+ //echo "
Checking: ". substr($this->_data, $offset);
+ $nextHit = strpos($this->_data, $match, $offset);
+ //echo "
Next hit is :".intval($nextHit);
+ if ($nextHit === false) {
+ $nextHit = $this->getLength() - $pointer;
+ }
+ // now check if we found an escaped occurance
+ $string = substr($this->_data, $pointer, $nextHit);
+ $string=str_replace('\\\\','',trim($string));
+ $quotes=substr_count($string,'\'');
+ $escaped_quotes=substr_count($string,'\\\'');
+ if (($quotes-$escaped_quotes) % 2 == 0) {
+ // hit was not escaped - we found the match
+ $notFound = false;
+ } else {
+ // keep on looking, this was escaped
+ $offset = $pointer + $nextHit +1;
+ }
+ }
+ return $nextHit;
+ }
+}
diff --git a/library/Msd/Sql/Parser.php b/library/Msd/Sql/Parser.php
index 9fedf96..e36089d 100644
--- a/library/Msd/Sql/Parser.php
+++ b/library/Msd/Sql/Parser.php
@@ -4,12 +4,11 @@
* http://www.mysqldumper.net
*
* @package MySQLDumper
- * @subpackage SQL-Browser
+ * @subpackage SQL-Parser
* @version SVN: $Rev$
* @author $Author$
*/
-require_once "Msd/Sql/Parser/Interface.php";
/**
* Class to parse MySQL queries.
* This enables you to analyze and modify MySQL queries, which the user has entered.
@@ -69,14 +68,12 @@ class Msd_Sql_Parser implements Iterator
* Class constructor.
* Creates a new instance of the MySQL parser and optionally assign the raw MySQL query.
*
- * @param string $sqlQuery Raw MySQL query to parse
- * @param bool $debug If turned on, detection of queries is logged
+ * @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($sqlQuery = null, $debug = false)
+ public function __construct(Msd_Sql_Object $sqlObject, $debug = false)
{
- if ($sqlQuery !== null) {
- $this->_rawQuery = $sqlQuery;
- }
+ $this->_sql = $sqlObject;
$this->_debug = $debug;
}
@@ -86,61 +83,32 @@ class Msd_Sql_Parser implements Iterator
*
* @throws Msd_Sql_Parser_Exception
*
- * @param string $sqlQuery Raw MySQL query to parse
- *
* @return void
*/
- public function parse($sqlQuery = null)
+ public function parse()
{
- if ($sqlQuery === null) {
- if ($this->_rawQuery === null) {
- throw new Msd_Sql_Parser_Exception('You must specify a MySQL query for parsing!');
- }
- $sqlQuery = $this->_rawQuery;
- }
-
- $sqlQuery = trim($sqlQuery);
-
+ // get first characters to extract the kind of query we have to process
$statementCounter = 0;
- $startPos = 0;
- $queryLength = strlen($sqlQuery);
- while ($startPos < $queryLength) {
- $statementCounter++;
- // move pointer to the next character we can interprete
- while ($startPos < $queryLength && in_array($sqlQuery[$startPos], array(' ', "\n", "\r"))) {
- $startPos++;
- }
+ while ($this->_sql->hasMoreToProcess()) {
+ $this->_sql->movePointerToNextCommand();
+ $endOfCommand = $this->_sql->getPosition(' ');
+ $sqlQuery = $this->_sql->getData($endOfCommand);
+ //echo "
Query beginn: ".$sqlQuery;
- $firstSpace = strpos($sqlQuery, ' ', $startPos);
- $statement = trim(strtolower(substr($sqlQuery, $startPos, $firstSpace - $startPos)));
- $lengthCheck = strlen($statement);
- if ($lengthCheck == 0) {
- break;
- }
- if ($lengthCheck == 1 || $statement{1} == ';' || $statement{1} == "\n") {
- $startPos = $startPos + 1;
- continue;
- }
+ $parts = explode(' ', $sqlQuery);
+ $statement = strtolower($parts[0]);
// check for comments or conditional comments
- $commentCheck = substr($statement, 0, 2);
+ $commentCheck = substr($sqlQuery, 0, 2);
if (isset($this->_sqlComments[$commentCheck]) || substr($statement, 0, 3) == '/*!') {
- $commentEnd = $this->_sqlComments[$commentCheck];
- $endPos = strpos($sqlQuery, $commentEnd, $startPos) + strlen($commentEnd);
- $comment = substr($sqlQuery, $startPos, $endPos - $startPos);
- $this->_parseStatement($comment, 'Msd_Sql_Parser_Statement_Comment');
- $startPos = $endPos+1;
- continue;
+ $statement = 'Comment';
}
- $parserClass = 'Msd_Sql_Parser_Statement_' . ucwords($statement);
- $endPos = $this->_getStatementEndPos($sqlQuery, $startPos);
- $completeStatement = trim(substr($sqlQuery, $startPos, $endPos - $startPos));
- $startPos = $endPos + 1;
- $foundStatement = $this->_parseStatement($completeStatement, $parserClass);
+ $foundStatement = $this->_parseStatement($this->_sql, ucwords($statement));
if ($this->_debug) {
$this->_debugOutput .= '
Extracted statement: '.$foundStatement;
}
$this->_parsedStatements[] = $foundStatement;
+ $statementCounter++;
// increment query type counter
if (!isset($this->_parsingSummary[$statement])) {
$this->_parsingSummary[$statement] = 0;
@@ -149,57 +117,26 @@ class Msd_Sql_Parser implements Iterator
}
}
- /**
- * Searches the end of a MySQL statement and returns its position.
- *
- * @param string $sqlQuery The complete MySQL query
- * @param int $startPos Index, where to start the search.
- *
- * @return int End position of the statement
- */
- private function _getStatementEndPos($sqlQuery, $startPos = 0)
- {
- $nextString = strpos($sqlQuery, "'", $startPos);
- $nextSemicolon = strpos($sqlQuery, ';', $startPos);
- if ($nextString === false) {
- if ($nextSemicolon === false) {
- return strlen($sqlQuery);
- }
-
- return $nextSemicolon+1;
- }
-
- while ($nextString < $nextSemicolon) {
- $nextString = strpos($sqlQuery, "'", $nextString + 1);
- $nextSemicolon = strpos($sqlQuery, ';', $nextString + 1);
- $nextString = strpos($sqlQuery, "'", $nextString + 1);
- if ($nextString === false) {
- break;
- }
- }
-
- return $nextSemicolon;
- }
-
/**
* Creates an instance of a statement parser class and invokes statement parsing.
*
* @throws Msd_Sql_Parser_Exception
*
- * @param string $statement MySQL statement to parse
- * @param string $parserClass Parser class to use
+ * @param Msd_Sql_Object $sqlObject MySQL statement to parse
+ * @param string $statement Parser class to use
*
* @return array
*/
- private function _parseStatement($statement, $parserClass)
+ private function _parseStatement(Msd_Sql_Object $sqlObject, $statement)
{
- try {
- $parserObject = new $parserClass;
- } catch (Exception $e) {
- throw new Msd_Sql_Parser_Exception("Can't suitable parser for the statement!");
+ $statementPath = '/Msd/Sql/Parser/Statement/' . $statement;
+ if ($statement !== 'Select') die("Not implemented yet: ".$statement);
+ if (!file_exists(LIBRARY_PATH . $statementPath . '.php')) {
+ throw new Msd_Sql_Parser_Exception("Can't find statement class for statement: " . $statement);
}
-
- return $parserObject->parse($statement);
+ $statementClass = 'Msd_Sql_Parser_Statement_' . $statement;
+ $parserObject = new $statementClass;
+ return $parserObject->parse($sqlObject);
}
/**
diff --git a/library/Msd/Sql/Parser/Exception.php b/library/Msd/Sql/Parser/Exception.php
index 62e25bc..c392511 100644
--- a/library/Msd/Sql/Parser/Exception.php
+++ b/library/Msd/Sql/Parser/Exception.php
@@ -4,12 +4,11 @@
* http://www.mysqldumper.net
*
* @package MySQLDumper
- * @subpackage SQL-Browser
+ * @subpackage SQL-Parser
* @version SVN: $Rev$
* @author $Author$
*/
-require_once 'Msd/Exception.php';
/**
* Exception class for all SQL-Parser exceptions.
*
diff --git a/library/Msd/Sql/Parser/Interface.php b/library/Msd/Sql/Parser/Interface.php
index b3eda03..b74d0fb 100644
--- a/library/Msd/Sql/Parser/Interface.php
+++ b/library/Msd/Sql/Parser/Interface.php
@@ -4,7 +4,7 @@
* http://www.mysqldumper.net
*
* @package MySQLDumper
- * @subpackage SQL-Browser
+ * @subpackage SQL-Parser
* @version SVN: $Rev$
* @author $Author$
*/
@@ -13,7 +13,7 @@
* Interface definition for MySQL statement parsers.
*
* @package MySQLDumper
- * @subpackage SQL-Browser
+ * @subpackage SQL-Parser
*/
interface Msd_Sql_Parser_Interface
{
@@ -22,9 +22,9 @@ interface Msd_Sql_Parser_Interface
*
* @abstract
*
- * @param string $statement MySQL statement.
+ * @param Msd_Sql_Object $sqlObject MySQL statement object.
*
* @return void
*/
- public function parse($statement);
+ public function parse(Msd_Sql_Object $sqlObject);
}
\ No newline at end of file
diff --git a/library/Msd/Sql/Parser/Statement/Comment.php b/library/Msd/Sql/Parser/Statement/Comment.php
index 9d56d3b..7b19fb5 100644
--- a/library/Msd/Sql/Parser/Statement/Comment.php
+++ b/library/Msd/Sql/Parser/Statement/Comment.php
@@ -4,7 +4,7 @@
* http://www.mysqldumper.net
*
* @package MySQLDumper
- * @subpackage SQL-Browser
+ * @subpackage SQL-Parser
* @version SVN: $Rev$
* @author $Author$
*/
diff --git a/library/Msd/Sql/Parser/Statement/Create.php b/library/Msd/Sql/Parser/Statement/Create.php
index 7ac296c..bea533b 100644
--- a/library/Msd/Sql/Parser/Statement/Create.php
+++ b/library/Msd/Sql/Parser/Statement/Create.php
@@ -4,7 +4,7 @@
* http://www.mysqldumper.net
*
* @package MySQLDumper
- * @subpackage SQL-Browser
+ * @subpackage SQL-Parser
* @version SVN: $Rev$
* @author $Author$
*/
diff --git a/library/Msd/Sql/Parser/Statement/Drop.php b/library/Msd/Sql/Parser/Statement/Drop.php
index d1bb8a0..58444ce 100644
--- a/library/Msd/Sql/Parser/Statement/Drop.php
+++ b/library/Msd/Sql/Parser/Statement/Drop.php
@@ -4,7 +4,7 @@
* http://www.mysqldumper.net
*
* @package MySQLDumper
- * @subpackage SQL-Browser
+ * @subpackage SQL-Parser
* @version SVN: $Rev$
* @author $Author$
*/
diff --git a/library/Msd/Sql/Parser/Statement/Insert.php b/library/Msd/Sql/Parser/Statement/Insert.php
index b27e06b..0799890 100644
--- a/library/Msd/Sql/Parser/Statement/Insert.php
+++ b/library/Msd/Sql/Parser/Statement/Insert.php
@@ -4,7 +4,7 @@
* http://www.mysqldumper.net
*
* @package MySQLDumper
- * @subpackage SQL-Browser
+ * @subpackage SQL-Parser
* @version SVN: $Rev$
* @author $Author$
*/
diff --git a/library/Msd/Sql/Parser/Statement/Select.php b/library/Msd/Sql/Parser/Statement/Select.php
index ba38217..c9d6a60 100644
--- a/library/Msd/Sql/Parser/Statement/Select.php
+++ b/library/Msd/Sql/Parser/Statement/Select.php
@@ -4,7 +4,7 @@
* http://www.mysqldumper.net
*
* @package MySQLDumper
- * @subpackage SQL-Browser
+ * @subpackage SQL-Parser
* @version SVN: $Rev$
* @author $Author$
*/
@@ -25,8 +25,12 @@ class Msd_Sql_Parser_Statement_Select implements Msd_Sql_Parser_Interface
*
* @return void
*/
- public function parse($statement)
+ public function parse(Msd_Sql_Object $sql)
{
+ $sql->setState('Select');
+ $endOfStatement = $sql->getPosition(';');
+ $statement = $sql->getData($endOfStatement);
+ $sql->setPointer($endOfStatement+1);
return $statement;
}
}
diff --git a/library/Msd/Sql/Parser/Statement/Unlock.php b/library/Msd/Sql/Parser/Statement/Unlock.php
index fc9cc6a..986b48b 100644
--- a/library/Msd/Sql/Parser/Statement/Unlock.php
+++ b/library/Msd/Sql/Parser/Statement/Unlock.php
@@ -4,7 +4,7 @@
* http://www.mysqldumper.net
*
* @package MySQLDumper
- * @subpackage SQL-Browser
+ * @subpackage SQL-Parser
* @version SVN: $Rev$
* @author $Author$
*/
diff --git a/public/index.php b/public/index.php
index 7ce874c..4644fe3 100644
--- a/public/index.php
+++ b/public/index.php
@@ -9,6 +9,12 @@ defined('APPLICATION_PATH') || define(
)
);
+defined('LIBRARY_PATH') || define(
+ 'LIBRARY_PATH', realpath(
+ dirname(__FILE__) . DS . '..' . DS . 'library'
+ )
+);
+
// Define application environment
if (!defined('APPLICATION_ENV')) {
$appEnvironment = getenv('APPLICATION_ENV');