Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
a5ff4c47c7
@ -553,7 +553,12 @@ var PMA_consoleInput = {
|
||||
mode: 'text/x-sql',
|
||||
lineWrapping: true,
|
||||
extraKeys: {"Ctrl-Space": "autocomplete"},
|
||||
hintOptions: {"completeSingle": false, "completeOnSingleClick": true}
|
||||
hintOptions: {"completeSingle": false, "completeOnSingleClick": true},
|
||||
gutters: ["CodeMirror-lint-markers"],
|
||||
lint: {
|
||||
"getAnnotations": CodeMirror.sqlLint,
|
||||
"async": true,
|
||||
}
|
||||
});
|
||||
PMA_consoleInput._inputs.console.on("inputRead", codemirrorAutocompleteOnInputRead);
|
||||
PMA_consoleInput._inputs.console.on("keydown", function(instance, event) {
|
||||
@ -565,7 +570,12 @@ var PMA_consoleInput = {
|
||||
mode: 'text/x-sql',
|
||||
lineWrapping: true,
|
||||
extraKeys: {"Ctrl-Space": "autocomplete"},
|
||||
hintOptions: {"completeSingle": false, "completeOnSingleClick": true}
|
||||
hintOptions: {"completeSingle": false, "completeOnSingleClick": true},
|
||||
gutters: ["CodeMirror-lint-markers"],
|
||||
lint: {
|
||||
"getAnnotations": CodeMirror.sqlLint,
|
||||
"async": true,
|
||||
}
|
||||
});
|
||||
PMA_consoleInput._inputs.bookmark.on("inputRead", codemirrorAutocompleteOnInputRead);
|
||||
}
|
||||
|
||||
@ -36,13 +36,6 @@ class Array2d extends Component
|
||||
{
|
||||
$ret = array();
|
||||
|
||||
/**
|
||||
* Whether an array was parsed or not. To be a valid parsing, at least
|
||||
* one array must be parsed after each comma.
|
||||
* @var bool $parsed
|
||||
*/
|
||||
$parsed = false;
|
||||
|
||||
/**
|
||||
* The number of values in each set.
|
||||
* @var int
|
||||
@ -95,14 +88,12 @@ class Array2d extends Component
|
||||
$parser->error("{$count} values were expected, but found {$arrCount}.", $token);
|
||||
}
|
||||
$ret[] = $arr;
|
||||
$parsed = true;
|
||||
$state = 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} elseif ($state === 1) {
|
||||
if ($token->value === ',') {
|
||||
$parsed = false;
|
||||
$state = 0;
|
||||
} else {
|
||||
break;
|
||||
@ -110,7 +101,7 @@ class Array2d extends Component
|
||||
}
|
||||
}
|
||||
|
||||
if (!$parsed) {
|
||||
if ($state === 0) {
|
||||
$parser->error(
|
||||
'An opening bracket followed by a set of values was expected.',
|
||||
$list->tokens[$list->idx]
|
||||
|
||||
@ -239,6 +239,9 @@ class Expression extends Component
|
||||
|
||||
if ($alias) {
|
||||
// An alias is expected (the keyword `AS` was previously found).
|
||||
if (!empty($ret->alias)) {
|
||||
$parser->error('An alias was previously found.', $token);
|
||||
}
|
||||
$ret->alias = $token->value;
|
||||
$alias = 0;
|
||||
} else {
|
||||
@ -265,12 +268,18 @@ class Expression extends Component
|
||||
break;
|
||||
}
|
||||
|
||||
// Parsing aliases without `AS` keyword and any whitespace.
|
||||
// Parsing aliases without `AS` keyword and any
|
||||
// whitespace.
|
||||
// Example: SELECT 1`foo`
|
||||
if (($token->type === Token::TYPE_STRING)
|
||||
|| (($token->type === Token::TYPE_SYMBOL)
|
||||
&& ($token->flags & Token::FLAG_SYMBOL_BACKTICK))
|
||||
) {
|
||||
if (!empty($ret->alias)) {
|
||||
$parser->error(
|
||||
'An alias was previously found.', $token
|
||||
);
|
||||
}
|
||||
$ret->alias = $token->value;
|
||||
}
|
||||
} else {
|
||||
@ -285,6 +294,11 @@ class Expression extends Component
|
||||
if (($token->type === Token::TYPE_NONE) || ($token->type === Token::TYPE_STRING)
|
||||
|| (($token->type === Token::TYPE_SYMBOL) && ($token->flags & Token::FLAG_SYMBOL_BACKTICK))
|
||||
) {
|
||||
if (!empty($ret->alias)) {
|
||||
$parser->error(
|
||||
'An alias was previously found.', $token
|
||||
);
|
||||
}
|
||||
$ret->alias = $token->value;
|
||||
continue;
|
||||
}
|
||||
@ -301,8 +315,8 @@ class Expression extends Component
|
||||
} else {
|
||||
$prev = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ($alias === 2) {
|
||||
$parser->error('An alias was expected.', $list->tokens[$list->idx - 1]);
|
||||
}
|
||||
|
||||
@ -38,6 +38,20 @@ class ExpressionArray extends Component
|
||||
|
||||
$expr = null;
|
||||
|
||||
/**
|
||||
* The state of the parser.
|
||||
*
|
||||
* Below are the states of the parser.
|
||||
*
|
||||
* 0 ----------------------[ array ]---------------------> 1
|
||||
*
|
||||
* 1 ------------------------[ , ]------------------------> 0
|
||||
* 1 -----------------------[ else ]----------------------> -1
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
$state = 0;
|
||||
|
||||
for (; $list->idx < $list->count; ++$list->idx) {
|
||||
/**
|
||||
* Token parsed at this moment.
|
||||
@ -60,20 +74,27 @@ class ExpressionArray extends Component
|
||||
break;
|
||||
}
|
||||
|
||||
if (($token->type === Token::TYPE_OPERATOR) && ($token->value === ',')) {
|
||||
$ret[] = $expr;
|
||||
} else {
|
||||
if ($state === 0) {
|
||||
$expr = Expression::parse($parser, $list, $options);
|
||||
if ($expr === null) {
|
||||
break;
|
||||
}
|
||||
$ret[] = $expr;
|
||||
$state = 1;
|
||||
} elseif ($state === 1) {
|
||||
if ($token->value === ',') {
|
||||
$state = 0;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Last iteration was not processed.
|
||||
if ($expr !== null) {
|
||||
$ret[] = $expr;
|
||||
if ($state === 0) {
|
||||
$parser->error(
|
||||
'An expression was expected.',
|
||||
$list->tokens[$list->idx]
|
||||
);
|
||||
}
|
||||
|
||||
--$list->idx;
|
||||
|
||||
@ -52,13 +52,6 @@ class RenameOperation extends Component
|
||||
|
||||
$expr = new RenameOperation();
|
||||
|
||||
/**
|
||||
* Whether an operation was parsed or not. To be a valid parsing, at
|
||||
* least one operation must be parsed after each comma.
|
||||
* @var bool $parsed
|
||||
*/
|
||||
$parsed = false;
|
||||
|
||||
/**
|
||||
* The state of the parser.
|
||||
*
|
||||
@ -129,21 +122,18 @@ class RenameOperation extends Component
|
||||
$parser->error('The new name of the table was expected.', $token);
|
||||
}
|
||||
$state = 3;
|
||||
$parsed = true;
|
||||
} elseif ($state === 3) {
|
||||
if (($token->type === Token::TYPE_OPERATOR) && ($token->value === ',')) {
|
||||
$ret[] = $expr;
|
||||
$expr = new RenameOperation();
|
||||
$state = 0;
|
||||
// Found a comma, looking for another operation.
|
||||
$parsed = false;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$parsed) {
|
||||
if ($state !== 3) {
|
||||
$parser->error('A rename operation was expected.', $list->tokens[$list->idx - 1]);
|
||||
}
|
||||
|
||||
|
||||
@ -327,6 +327,13 @@ class Parser
|
||||
// Statements can start with keywords only.
|
||||
// Comments, whitespaces, etc. are ignored.
|
||||
if ($token->type !== Token::TYPE_KEYWORD) {
|
||||
if (($token->type !== TOKEN::TYPE_COMMENT)
|
||||
&& ($token->type !== Token::TYPE_WHITESPACE)
|
||||
&& ($token->type !== Token::TYPE_OPERATOR) // `(` and `)`
|
||||
&& ($token->type !== Token::TYPE_DELIMITER)
|
||||
) {
|
||||
$this->error('Unexpected beginning of statement.', $token);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -337,10 +344,7 @@ class Parser
|
||||
|
||||
// Checking if it is a known statement that can be parsed.
|
||||
if (empty(static::$STATEMENT_PARSERS[$token->value])) {
|
||||
$this->error(
|
||||
'Unrecognized statement type.',
|
||||
$token
|
||||
);
|
||||
$this->error('Unrecognized statement type.', $token);
|
||||
// Skipping to the end of this statement.
|
||||
$list->getNextOfType(Token::TYPE_DELIMITER);
|
||||
//
|
||||
@ -356,35 +360,35 @@ class Parser
|
||||
|
||||
/**
|
||||
* Processed statement.
|
||||
* @var Statement $stmt
|
||||
* @var Statement $statement
|
||||
*/
|
||||
$stmt = new $class($this, $this->list);
|
||||
$statement = new $class($this, $this->list);
|
||||
|
||||
// The first token that is a part of this token is the next token
|
||||
// unprocessed by the previous statement.
|
||||
// There might be brackets around statements and this shouldn't
|
||||
// affect the parser
|
||||
$stmt->first = $prevLastIdx + 1;
|
||||
$statement->first = $prevLastIdx + 1;
|
||||
|
||||
// Storing the index of the last token parsed and updating the old
|
||||
// index.
|
||||
$stmt->last = $list->idx;
|
||||
$statement->last = $list->idx;
|
||||
$prevLastIdx = $list->idx;
|
||||
|
||||
// Finally, storing the statement.
|
||||
if (($inUnion)
|
||||
&& ($lastStatement instanceof SelectStatement)
|
||||
&& ($stmt instanceof SelectStatement)
|
||||
&& ($statement instanceof SelectStatement)
|
||||
) {
|
||||
/**
|
||||
* Last SELECT statement.
|
||||
* @var SelectStatement $lastStatement
|
||||
*/
|
||||
$lastStatement->union[] = $stmt;
|
||||
$lastStatement->union[] = $statement;
|
||||
$inUnion = false;
|
||||
} else {
|
||||
$this->statements[] = $stmt;
|
||||
$lastStatement = $stmt;
|
||||
$this->statements[] = $statement;
|
||||
$lastStatement = $statement;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -195,6 +195,11 @@ abstract class Statement
|
||||
// Only keywords are relevant here. Other parts of the query are
|
||||
// processed in the functions below.
|
||||
if ($token->type !== Token::TYPE_KEYWORD) {
|
||||
if (($token->type !== TOKEN::TYPE_COMMENT)
|
||||
&& ($token->type !== Token::TYPE_WHITESPACE)
|
||||
) {
|
||||
$parser->error('Unexpected token.', $token);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user