SQl-Parser:
- optionally set pointer behind matches - added detection for incomplete statements SQl-Browser / SQL-Box: - output error message if query is incomplete
Dieser Commit ist enthalten in:
Ursprung
6efd866311
Commit
2a46539fe5
10 geänderte Dateien mit 108 neuen und 15 gelöschten Zeilen
|
@ -391,11 +391,15 @@ class SqlController extends Zend_Controller_Action
|
||||||
$sqlObject = new Msd_Sql_Object($query);
|
$sqlObject = new Msd_Sql_Object($query);
|
||||||
$parser = new Msd_Sql_Parser($sqlObject, true);
|
$parser = new Msd_Sql_Parser($sqlObject, true);
|
||||||
$parser->parse();
|
$parser->parse();
|
||||||
|
if ($sqlObject->hasErrors()) {
|
||||||
|
$this->view->errorMessage = implode('<br />', $sqlObject->getErrors());
|
||||||
|
}
|
||||||
//echo $parser->getDebugOutput();
|
//echo $parser->getDebugOutput();
|
||||||
$statements = $parser->getParsedStatements();
|
$statements = $parser->getParsedStatements();
|
||||||
foreach ($statements as $statement) {
|
foreach ($statements as $statement) {
|
||||||
|
echo "<br>- ".$statement;
|
||||||
try {
|
try {
|
||||||
$res = $this->_db->query($statement, Msd_Db::ARRAY_ASSOC);
|
$res = array(); //$this->_db->query($statement, Msd_Db::ARRAY_ASSOC);
|
||||||
$this->view->resultset = $res;
|
$this->view->resultset = $res;
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
$this->view->errorMessage = $e->getMessage();
|
$this->view->errorMessage = $e->getMessage();
|
||||||
|
|
|
@ -40,6 +40,13 @@ class Msd_Sql_Object
|
||||||
*/
|
*/
|
||||||
private $_state = '';
|
private $_state = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds parsing errors.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $_errors = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*
|
*
|
||||||
|
@ -178,11 +185,12 @@ class Msd_Sql_Object
|
||||||
*
|
*
|
||||||
* Begins to search at the actual postion of the pointer.
|
* Begins to search at the actual postion of the pointer.
|
||||||
*
|
*
|
||||||
* @param string $match
|
* @param string $match The string to find
|
||||||
|
* @param bool $includeMatch Whether to add length of $match to position
|
||||||
*
|
*
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
public function getPosition($match = ';')
|
public function getPosition($match = ';', $includeMatch = true)
|
||||||
{
|
{
|
||||||
$pointer = $this->getPointer();
|
$pointer = $this->getPointer();
|
||||||
$offset = $pointer;
|
$offset = $pointer;
|
||||||
|
@ -192,7 +200,16 @@ class Msd_Sql_Object
|
||||||
while ($notFound && $offset < $length) {
|
while ($notFound && $offset < $length) {
|
||||||
$nextHit = strpos($this->_data, $match, $offset);
|
$nextHit = strpos($this->_data, $match, $offset);
|
||||||
if ($nextHit === false) {
|
if ($nextHit === false) {
|
||||||
return $this->getLength() - $pointer;
|
$lang = Msd_Language::getInstance()->getTranslator();
|
||||||
|
$msg = sprintf(
|
||||||
|
$lang->_('L_SQL_INCOMPLETE_STATEMENT_DETECTED'),
|
||||||
|
$this->getState(),
|
||||||
|
$match,
|
||||||
|
$this->getData(200)
|
||||||
|
);
|
||||||
|
$this->setError($msg);
|
||||||
|
$this->setPointer($this->getLength());
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
// now check if we found an escaped occurance
|
// now check if we found an escaped occurance
|
||||||
$string = substr($this->_data, $pointer, $nextHit);
|
$string = substr($this->_data, $pointer, $nextHit);
|
||||||
|
@ -202,6 +219,9 @@ class Msd_Sql_Object
|
||||||
if (($quotes - $escapedQuotes) % 2 == 0) {
|
if (($quotes - $escapedQuotes) % 2 == 0) {
|
||||||
// hit was not escaped - we found the match
|
// hit was not escaped - we found the match
|
||||||
$notFound = false;
|
$notFound = false;
|
||||||
|
if ($includeMatch) {
|
||||||
|
$nextHit += strlen($match);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// keep on looking, this was escaped
|
// keep on looking, this was escaped
|
||||||
$offset = $pointer + $nextHit;
|
$offset = $pointer + $nextHit;
|
||||||
|
@ -209,4 +229,50 @@ class Msd_Sql_Object
|
||||||
}
|
}
|
||||||
return $nextHit;
|
return $nextHit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set an error message
|
||||||
|
*
|
||||||
|
* @param string $msg The error message
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setError($msg)
|
||||||
|
{
|
||||||
|
$this->_errors[] = $msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get error messages
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getErrors()
|
||||||
|
{
|
||||||
|
return $this->_errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if errors occured.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function hasErrors()
|
||||||
|
{
|
||||||
|
$ret = false;
|
||||||
|
if (sizeof($this->_errors) > 0) {
|
||||||
|
$ret = true;
|
||||||
|
}
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get actual parsing state
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getState()
|
||||||
|
{
|
||||||
|
return $this->_state;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,7 +84,7 @@ class Msd_Sql_Parser implements Iterator
|
||||||
while ($this->_sql->hasMoreToProcess() && $this->_sql->movePointerToNextCommand()!==false) {
|
while ($this->_sql->hasMoreToProcess() && $this->_sql->movePointerToNextCommand()!==false) {
|
||||||
$startPosition = $this->_sql->getPointer();
|
$startPosition = $this->_sql->getPointer();
|
||||||
// get first "word" of query to extract the kind we have to process
|
// get first "word" of query to extract the kind we have to process
|
||||||
$endOfFirstWord = $this->_sql->getPosition(' ');
|
$endOfFirstWord = $this->_sql->getPosition(' ', false);
|
||||||
// get substring from actual position to found position
|
// get substring from actual position to found position
|
||||||
$sqlQuery = $this->_sql->getData($endOfFirstWord - $startPosition);
|
$sqlQuery = $this->_sql->getData($endOfFirstWord - $startPosition);
|
||||||
$statement = strtolower($sqlQuery);
|
$statement = strtolower($sqlQuery);
|
||||||
|
@ -99,7 +99,7 @@ class Msd_Sql_Parser implements Iterator
|
||||||
} catch (Msd_Sql_Parser_Exception $e) {
|
} catch (Msd_Sql_Parser_Exception $e) {
|
||||||
// stop parsing by setting pointer to the end
|
// stop parsing by setting pointer to the end
|
||||||
$this->_sql->setPointer($this->_sql->getLength()-1);
|
$this->_sql->setPointer($this->_sql->getLength()-1);
|
||||||
//echo "<br>Error: ".$e->getMessage();
|
echo "<br>Error: ".$e->getMessage();
|
||||||
}
|
}
|
||||||
if ($this->_debug) {
|
if ($this->_debug) {
|
||||||
$this->_debugOutput .= '<br />Extracted statement: '.$foundStatement;
|
$this->_debugOutput .= '<br />Extracted statement: '.$foundStatement;
|
||||||
|
@ -128,7 +128,7 @@ class Msd_Sql_Parser implements Iterator
|
||||||
{
|
{
|
||||||
$statementPath = '/Msd/Sql/Parser/Statement/' . $statement;
|
$statementPath = '/Msd/Sql/Parser/Statement/' . $statement;
|
||||||
if (!file_exists(LIBRARY_PATH . $statementPath . '.php')) {
|
if (!file_exists(LIBRARY_PATH . $statementPath . '.php')) {
|
||||||
throw new Msd_Sql_Parser_Exception("Can't find statement class for statement: " . $statement);
|
throw new Msd_Sql_Parser_Exception("Can't find statement class for statement: '" . $statement ."'");
|
||||||
}
|
}
|
||||||
$statementClass = 'Msd_Sql_Parser_Statement_' . $statement;
|
$statementClass = 'Msd_Sql_Parser_Statement_' . $statement;
|
||||||
$parserObject = new $statementClass();
|
$parserObject = new $statementClass();
|
||||||
|
|
|
@ -30,7 +30,7 @@ class Msd_Sql_Parser_Statement_Alter implements Msd_Sql_Parser_Interface
|
||||||
$sql->setState('Alter');
|
$sql->setState('Alter');
|
||||||
$endOfStatement = $sql->getPosition(';');
|
$endOfStatement = $sql->getPosition(';');
|
||||||
$statement = $sql->getData($endOfStatement);
|
$statement = $sql->getData($endOfStatement);
|
||||||
$sql->setPointer($endOfStatement+1);
|
$sql->setPointer($endOfStatement);
|
||||||
return $statement;
|
return $statement;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,8 +25,31 @@ class Msd_Sql_Parser_Statement_Comment implements Msd_Sql_Parser_Interface
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function parse(Msd_Sql_Object$statement)
|
public function parse(Msd_Sql_Object $sql)
|
||||||
{
|
{
|
||||||
|
$sql->setState('Comment');
|
||||||
|
$firstChars = $sql->getData(3);
|
||||||
|
$returnStatement = false;
|
||||||
|
if (substr($firstChars, 0, 2) == '--' || substr($firstChars, 0, 1) == '#') {
|
||||||
|
// one line comment -> match new line
|
||||||
|
$match = "\n";
|
||||||
|
} else {
|
||||||
|
if ($firstChars == '/*!') {
|
||||||
|
// conditionial statement
|
||||||
|
$match = '*/;';
|
||||||
|
$returnStatement = true;
|
||||||
|
} else {
|
||||||
|
// multi line comment
|
||||||
|
$match = '*/';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$endOfStatement = $sql->getPosition($match);
|
||||||
|
$statement = $sql->getData($endOfStatement);
|
||||||
|
$sql->setPointer($endOfStatement);
|
||||||
|
if ($returnStatement === true) {
|
||||||
return $statement;
|
return $statement;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ class Msd_Sql_Parser_Statement_Create implements Msd_Sql_Parser_Interface
|
||||||
$sql->setState('Create');
|
$sql->setState('Create');
|
||||||
$endOfStatement = $sql->getPosition(';');
|
$endOfStatement = $sql->getPosition(';');
|
||||||
$statement = $sql->getData($endOfStatement);
|
$statement = $sql->getData($endOfStatement);
|
||||||
$sql->setPointer($endOfStatement+1);
|
$sql->setPointer($endOfStatement);
|
||||||
return $statement;
|
return $statement;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ class Msd_Sql_Parser_Statement_Drop implements Msd_Sql_Parser_Interface
|
||||||
$sql->setState('Drop');
|
$sql->setState('Drop');
|
||||||
$endOfStatement = $sql->getPosition(';');
|
$endOfStatement = $sql->getPosition(';');
|
||||||
$statement = $sql->getData($endOfStatement);
|
$statement = $sql->getData($endOfStatement);
|
||||||
$sql->setPointer($endOfStatement+1);
|
$sql->setPointer($endOfStatement);
|
||||||
return $statement;
|
return $statement;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ class Msd_Sql_Parser_Statement_Insert implements Msd_Sql_Parser_Interface
|
||||||
$sql->setState('Insert');
|
$sql->setState('Insert');
|
||||||
$endOfStatement = $sql->getPosition(';');
|
$endOfStatement = $sql->getPosition(';');
|
||||||
$statement = $sql->getData($endOfStatement);
|
$statement = $sql->getData($endOfStatement);
|
||||||
$sql->setPointer($endOfStatement+1);
|
$sql->setPointer($endOfStatement);
|
||||||
return $statement;
|
return $statement;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ class Msd_Sql_Parser_Statement_Lock implements Msd_Sql_Parser_Interface
|
||||||
$sql->setState('Lock');
|
$sql->setState('Lock');
|
||||||
$endOfStatement = $sql->getPosition(';');
|
$endOfStatement = $sql->getPosition(';');
|
||||||
$statement = $sql->getData($endOfStatement);
|
$statement = $sql->getData($endOfStatement);
|
||||||
$sql->setPointer($endOfStatement+1);
|
$sql->setPointer($endOfStatement);
|
||||||
return $statement;
|
return $statement;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ class Msd_Sql_Parser_Statement_Unlock implements Msd_Sql_Parser_Interface
|
||||||
$sql->setState('Unlock');
|
$sql->setState('Unlock');
|
||||||
$endOfStatement = $sql->getPosition(';');
|
$endOfStatement = $sql->getPosition(';');
|
||||||
$statement = $sql->getData($endOfStatement);
|
$statement = $sql->getData($endOfStatement);
|
||||||
$sql->setPointer($endOfStatement+1);
|
$sql->setPointer($endOfStatement);
|
||||||
return $statement;
|
return $statement;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Laden …
In neuem Issue referenzieren