SQl-Parser:
- changes and fixes for parsing statements - QA SQl-Browser / SQL-Box: - added semicolon to table select box
Dieser Commit ist enthalten in:
Ursprung
2a46539fe5
Commit
e95ab08945
13 geänderte Dateien mit 98 neuen und 56 gelöschten Zeilen
|
@ -394,12 +394,11 @@ class SqlController extends Zend_Controller_Action
|
||||||
if ($sqlObject->hasErrors()) {
|
if ($sqlObject->hasErrors()) {
|
||||||
$this->view->errorMessage = implode('<br />', $sqlObject->getErrors());
|
$this->view->errorMessage = implode('<br />', $sqlObject->getErrors());
|
||||||
}
|
}
|
||||||
//echo $parser->getDebugOutput();
|
|
||||||
$statements = $parser->getParsedStatements();
|
$statements = $parser->getParsedStatements();
|
||||||
foreach ($statements as $statement) {
|
foreach ($statements as $statement) {
|
||||||
echo "<br>- ".$statement;
|
//echo "<br>Extracted statement: ".$statement;
|
||||||
try {
|
try {
|
||||||
$res = array(); //$this->_db->query($statement, Msd_Db::ARRAY_ASSOC);
|
$res = $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();
|
||||||
|
|
|
@ -43,7 +43,7 @@ if (isset($this->errorMessage)) {
|
||||||
function setShowTableQuery()
|
function setShowTableQuery()
|
||||||
{
|
{
|
||||||
query = $('#selectTable').attr('value');
|
query = $('#selectTable').attr('value');
|
||||||
query = 'SELECT * FROM `' + query + '`';
|
query = 'SELECT * FROM `' + query + '`;';
|
||||||
$('#sqltextarea').val(query);
|
$('#sqltextarea').val(query);
|
||||||
$('#myForm').submit();
|
$('#myForm').submit();
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,11 +45,10 @@ class Msd_Html
|
||||||
* filter select boxes (e.g. sqlserver/show.variables).
|
* filter select boxes (e.g. sqlserver/show.variables).
|
||||||
*
|
*
|
||||||
* @param array $array Array to scan for prefixes
|
* @param array $array Array to scan for prefixes
|
||||||
* @param boolean $addNoneOption Whether to add a first entry '---'
|
|
||||||
*
|
*
|
||||||
* @return $prefix_array array The array conatining the unique prefixes
|
* @return array The array conatining the unique prefixes
|
||||||
*/
|
*/
|
||||||
public static function getPrefixArray($array, $addNoneOption = true)
|
public static function getPrefixArray($array)
|
||||||
{
|
{
|
||||||
$prefixes = array();
|
$prefixes = array();
|
||||||
$keys = array_keys($array);
|
$keys = array_keys($array);
|
||||||
|
|
|
@ -115,33 +115,48 @@ class Msd_Sql_Object
|
||||||
{
|
{
|
||||||
$pointer = $this->getPointer();
|
$pointer = $this->getPointer();
|
||||||
$dataSize = strlen($this->_data);
|
$dataSize = strlen($this->_data);
|
||||||
$skip = array(';', ' ', "\n", "\r");
|
$skip = array(' ', "\n", "\r", "\t");
|
||||||
|
if ($this->_state !== 'Comment') {
|
||||||
|
$skip[] = "\n";
|
||||||
|
}
|
||||||
if (in_array($this->_data[$pointer], $skip)) {
|
if (in_array($this->_data[$pointer], $skip)) {
|
||||||
while ($pointer < $dataSize && in_array($this->_data[$pointer], $skip)) {
|
while ($pointer < $dataSize && in_array($this->_data[$pointer], $skip)) {
|
||||||
$pointer++;
|
$pointer++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$this->setPointer($pointer);
|
$this->setPointer($pointer);
|
||||||
if ($pointer == $this->getLength()) {
|
if ($pointer >= $this->getLength()) {
|
||||||
$pointer = false;
|
$pointer = false;
|
||||||
}
|
}
|
||||||
return $pointer;
|
return $pointer;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Move pointer forward by $positions positions.
|
||||||
|
*
|
||||||
|
* @param integer $positions Move pointer forward by $positions
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function movePointerForward($positions)
|
||||||
|
{
|
||||||
|
$this->setPointer($this->getPointer() + $positions);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get some characters of data.
|
* Get data from actual pointer to given position.
|
||||||
*
|
*
|
||||||
* @param int $nrOfCharacters Number of characters to get
|
* @param int $endPosition End position of pointer
|
||||||
|
* @param bool $movePointer Move pointer behind fetched data
|
||||||
*
|
*
|
||||||
* @return string Sql data from the pointer position to end or to the nr of chars to fetch
|
* @return string Sql data from the pointer position to end or to the nr of chars to fetch
|
||||||
*/
|
*/
|
||||||
public function getData($nrOfCharacters = null)
|
public function getData($endPosition, $movePointer = true)
|
||||||
{
|
{
|
||||||
if ($nrOfCharacters > 0) {
|
$data = substr($this->_data, $this->_pointer, ($endPosition - $this->_pointer));
|
||||||
return substr($this->_data, $this->_pointer, $nrOfCharacters);
|
if ($movePointer === true) {
|
||||||
} else {
|
$this->setPointer($endPosition +1);
|
||||||
return substr($this->_data, $this->_pointer);
|
|
||||||
}
|
}
|
||||||
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -195,11 +210,19 @@ class Msd_Sql_Object
|
||||||
$pointer = $this->getPointer();
|
$pointer = $this->getPointer();
|
||||||
$offset = $pointer;
|
$offset = $pointer;
|
||||||
$notFound = true;
|
$notFound = true;
|
||||||
$nextHit = 0;
|
$nextHit = false;
|
||||||
$length = $this->getLength() - 1;
|
$length = $this->getLength() - 1; // zero-based
|
||||||
while ($notFound && $offset < $length) {
|
while ($notFound && $offset < $length) {
|
||||||
$nextHit = strpos($this->_data, $match, $offset);
|
$nextHit = strpos($this->_data, $match, $offset);
|
||||||
|
//echo "<br>getPosition: Search for '".$match."' P: ".$offset."-> Hit at :".$nextHit;
|
||||||
if ($nextHit === false) {
|
if ($nextHit === false) {
|
||||||
|
// check special case for comments
|
||||||
|
if ($this->getState() == 'Comment' && strpos($this->_data, "\n", $pointer) === false) {
|
||||||
|
// there is no next line - return statement "as is"
|
||||||
|
$this->setPointer($this->getLength());
|
||||||
|
return $this->getLength();
|
||||||
|
}
|
||||||
|
// we haven't found the correct end of the query - inform user
|
||||||
$lang = Msd_Language::getInstance()->getTranslator();
|
$lang = Msd_Language::getInstance()->getTranslator();
|
||||||
$msg = sprintf(
|
$msg = sprintf(
|
||||||
$lang->_('L_SQL_INCOMPLETE_STATEMENT_DETECTED'),
|
$lang->_('L_SQL_INCOMPLETE_STATEMENT_DETECTED'),
|
||||||
|
@ -211,25 +234,51 @@ class Msd_Sql_Object
|
||||||
$this->setPointer($this->getLength());
|
$this->setPointer($this->getLength());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// now check if we found an escaped occurance
|
|
||||||
$string = substr($this->_data, $pointer, $nextHit);
|
$data = $this->getData($nextHit, false);
|
||||||
$string = str_replace('\\\\', '', trim($string));
|
if (!$this->isEscaped($data)) {
|
||||||
$quotes = substr_count($string, '\'');
|
|
||||||
$escapedQuotes = substr_count($string, '\\\'');
|
|
||||||
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) {
|
if ($includeMatch) {
|
||||||
$nextHit += strlen($match);
|
$nextHit += strlen($match)-1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// keep on looking, this was escaped
|
// keep on looking, this one was escaped
|
||||||
$offset = $pointer + $nextHit;
|
$offset = $nextHit+1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $nextHit;
|
return $nextHit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get data upto the next new line
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getDataUntilNewLine()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if hit is escaped.
|
||||||
|
*
|
||||||
|
* @param string $string String to analyse
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function isEscaped($string)
|
||||||
|
{
|
||||||
|
$string = str_replace('\\\\', '', $string);
|
||||||
|
$quotes = substr_count($string, '\'');
|
||||||
|
$escapedQuotes = substr_count($string, '\\\'');
|
||||||
|
if (($quotes - $escapedQuotes) % 2 == 0) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set an error message
|
* Set an error message
|
||||||
*
|
*
|
||||||
|
|
|
@ -82,30 +82,31 @@ class Msd_Sql_Parser implements Iterator
|
||||||
{
|
{
|
||||||
$statementCounter = 0;
|
$statementCounter = 0;
|
||||||
while ($this->_sql->hasMoreToProcess() && $this->_sql->movePointerToNextCommand()!==false) {
|
while ($this->_sql->hasMoreToProcess() && $this->_sql->movePointerToNextCommand()!==false) {
|
||||||
$startPosition = $this->_sql->getPointer();
|
// check for comments or conditional comments
|
||||||
|
$commentCheck = $this->_sql->getData($this->_sql->getPointer() + 3, false);
|
||||||
|
if (substr($commentCheck,0 , 2) == '--' || substr($commentCheck, 0, 2) == '/*') {
|
||||||
|
$statement = 'Comment';
|
||||||
|
} else {
|
||||||
|
//$this->_sql->movePointerToNextCommand();
|
||||||
// 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(' ', false);
|
$endOfFirstWord = $this->_sql->getPosition(' ', false);
|
||||||
// get substring from actual position to found position
|
$sqlQuery = $this->_sql->getData($endOfFirstWord, false);
|
||||||
$sqlQuery = $this->_sql->getData($endOfFirstWord - $startPosition);
|
|
||||||
$statement = strtolower($sqlQuery);
|
$statement = strtolower($sqlQuery);
|
||||||
// check for comments or conditional comments
|
|
||||||
$commentCheck = substr($sqlQuery, 0, 2);
|
|
||||||
if (isset($this->_sqlComments[$commentCheck]) || substr($statement, 0, 3) == '/*!') {
|
|
||||||
$statement = 'Comment';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$foundStatement = $this->_parseStatement($this->_sql, ucfirst($statement));
|
$foundStatement = $this->_parseStatement($this->_sql, ucfirst($statement));
|
||||||
} 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());
|
||||||
echo "<br>Error: ".$e->getMessage();
|
|
||||||
}
|
}
|
||||||
if ($this->_debug) {
|
if ($this->_debug) {
|
||||||
$this->_debugOutput .= '<br />Extracted statement: '.$foundStatement;
|
$this->_debugOutput .= '<br />Extracted statement: '.$foundStatement;
|
||||||
}
|
}
|
||||||
|
if ($foundStatement > '') {
|
||||||
$this->_parsedStatements[] = $foundStatement;
|
$this->_parsedStatements[] = $foundStatement;
|
||||||
$statementCounter++;
|
$statementCounter++;
|
||||||
|
}
|
||||||
// increment query type counter
|
// increment query type counter
|
||||||
if (!isset($this->_parsingSummary[$statement])) {
|
if (!isset($this->_parsingSummary[$statement])) {
|
||||||
$this->_parsingSummary[$statement] = 0;
|
$this->_parsingSummary[$statement] = 0;
|
||||||
|
|
|
@ -30,7 +30,6 @@ 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);
|
|
||||||
return $statement;
|
return $statement;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,18 +21,20 @@ class Msd_Sql_Parser_Statement_Comment implements Msd_Sql_Parser_Interface
|
||||||
/**
|
/**
|
||||||
* Parse the statement.
|
* Parse the statement.
|
||||||
*
|
*
|
||||||
* @param Msd_Sql_Object $statement MySQL comment.
|
* @param Msd_Sql_Object $sql MySQL comment.
|
||||||
*
|
*
|
||||||
* @return void
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function parse(Msd_Sql_Object $sql)
|
public function parse(Msd_Sql_Object $sql)
|
||||||
{
|
{
|
||||||
$sql->setState('Comment');
|
$sql->setState('Comment');
|
||||||
$firstChars = $sql->getData(3);
|
$firstChars = $sql->getData($sql->getPointer() + 3, false);
|
||||||
|
$includeMatch = true;
|
||||||
$returnStatement = false;
|
$returnStatement = false;
|
||||||
if (substr($firstChars, 0, 2) == '--' || substr($firstChars, 0, 1) == '#') {
|
if (substr($firstChars, 0, 2) == '--' || substr($firstChars, 0, 1) == '#') {
|
||||||
// one line comment -> match new line
|
// one line comment -> match new line
|
||||||
$match = "\n";
|
$match = "\n";
|
||||||
|
$includeMatch = false;
|
||||||
} else {
|
} else {
|
||||||
if ($firstChars == '/*!') {
|
if ($firstChars == '/*!') {
|
||||||
// conditionial statement
|
// conditionial statement
|
||||||
|
@ -43,13 +45,12 @@ class Msd_Sql_Parser_Statement_Comment implements Msd_Sql_Parser_Interface
|
||||||
$match = '*/';
|
$match = '*/';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$endOfStatement = $sql->getPosition($match);
|
$endOfStatement = $sql->getPosition($match, $includeMatch);
|
||||||
$statement = $sql->getData($endOfStatement);
|
$statement = $sql->getData($endOfStatement);
|
||||||
$sql->setPointer($endOfStatement);
|
|
||||||
if ($returnStatement === true) {
|
if ($returnStatement === true) {
|
||||||
return $statement;
|
return $statement;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,6 @@ 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);
|
|
||||||
return $statement;
|
return $statement;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,6 @@ 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);
|
|
||||||
return $statement;
|
return $statement;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,6 @@ 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);
|
|
||||||
return $statement;
|
return $statement;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,6 @@ 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);
|
|
||||||
return $statement;
|
return $statement;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,6 @@ class Msd_Sql_Parser_Statement_Select implements Msd_Sql_Parser_Interface
|
||||||
$sql->setState('Select');
|
$sql->setState('Select');
|
||||||
$endOfStatement = $sql->getPosition(';');
|
$endOfStatement = $sql->getPosition(';');
|
||||||
$statement = $sql->getData($endOfStatement);
|
$statement = $sql->getData($endOfStatement);
|
||||||
$sql->setPointer($endOfStatement);
|
|
||||||
return $statement;
|
return $statement;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,6 @@ 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);
|
|
||||||
return $statement;
|
return $statement;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Laden …
In neuem Issue referenzieren