From 1ec99a431b3d67efc2a0c90a8621b204ab9e6da0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20=C4=8Ciha=C5=99?= Date: Tue, 25 Oct 2016 10:02:48 +0200 Subject: [PATCH] Update SQL parser to 3.4.11 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - issue #12344 Fixed parsing of labels in loop - issue #12228 Fixed parsing of BEGIN labels Signed-off-by: Michal Čihař --- ChangeLog | 2 + .../src/Components/CreateDefinition.php | 2 +- .../sql-parser/src/Components/Expression.php | 9 ++- .../sql-parser/src/Components/JoinKeyword.php | 20 ++++++- libraries/sql-parser/src/Context.php | 10 ++++ .../src/Contexts/ContextMySql50000.php | 15 ++--- .../src/Contexts/ContextMySql50100.php | 15 ++--- .../src/Contexts/ContextMySql50500.php | 15 ++--- .../src/Contexts/ContextMySql50600.php | 15 ++--- .../src/Contexts/ContextMySql50700.php | 15 ++--- libraries/sql-parser/src/Lexer.php | 57 ++++++++++++++++++- libraries/sql-parser/src/Parser.php | 22 ++++++- .../src/Statements/SelectStatement.php | 45 ++++++++------- libraries/sql-parser/src/Token.php | 12 ++++ 14 files changed, 193 insertions(+), 61 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1bd86288b8..ad8f99b965 100644 --- a/ChangeLog +++ b/ChangeLog @@ -70,6 +70,8 @@ phpMyAdmin - ChangeLog - issue #12365 Fix records count for large tables - issue #12533 Fix records count for complex queries - issue #12454 Query history not updated in console until page refresh +- issue #12344 Fixed parsing of labels in loop +- issue #12228 Fixed parsing of BEGIN labels 4.6.4 (2016-08-16) - issue [security] Weaknesses with cookie encryption, see PMASA-2016-29 diff --git a/libraries/sql-parser/src/Components/CreateDefinition.php b/libraries/sql-parser/src/Components/CreateDefinition.php index 0ef8a31160..3f2df089d8 100644 --- a/libraries/sql-parser/src/Components/CreateDefinition.php +++ b/libraries/sql-parser/src/Components/CreateDefinition.php @@ -50,7 +50,7 @@ class CreateDefinition extends Component 'UNIQUE KEY' => 4, 'COMMENT' => array(5, 'var'), 'COLUMN_FORMAT' => array(6, 'var'), - 'ON UPDATE' => array(7, 'var'), + 'ON UPDATE' => array(7, 'expr'), // Generated columns options. 'GENERATED ALWAYS' => 8, diff --git a/libraries/sql-parser/src/Components/Expression.php b/libraries/sql-parser/src/Components/Expression.php index 1ca05968c8..e4079603aa 100644 --- a/libraries/sql-parser/src/Components/Expression.php +++ b/libraries/sql-parser/src/Components/Expression.php @@ -33,7 +33,7 @@ class Expression extends Component * @var array */ private static $ALLOWED_KEYWORDS = array( - 'AS' => 1, 'DUAL' => 1, 'NULL' => 1, 'REGEXP' => 1 + 'AS' => 1, 'DUAL' => 1, 'NULL' => 1, 'REGEXP' => 1, 'CASE' => 1 ); /** @@ -252,6 +252,13 @@ class Expression extends Component } $alias = true; continue; + } elseif ($token->value === 'CASE') { + // For a use of CASE like + // 'SELECT a = CASE .... END, b=1, `id`, ... FROM ...' + $tempCaseExpr = CaseExpression::parse($parser, $list); + $ret->expr .= CaseExpression::build($tempCaseExpr); + $isExpr = true; + continue; } $isExpr = true; } elseif ($brackets === 0 && count($ret->expr) > 0 && ! $alias) { diff --git a/libraries/sql-parser/src/Components/JoinKeyword.php b/libraries/sql-parser/src/Components/JoinKeyword.php index 7062783c30..548a64e9a0 100644 --- a/libraries/sql-parser/src/Components/JoinKeyword.php +++ b/libraries/sql-parser/src/Components/JoinKeyword.php @@ -30,6 +30,7 @@ class JoinKeyword extends Component * @var array */ public static $JOINS = array( + 'CROSS JOIN' => 'CROSS', 'FULL JOIN' => 'FULL', 'FULL OUTER JOIN' => 'FULL', 'INNER JOIN' => 'INNER', @@ -38,6 +39,12 @@ class JoinKeyword extends Component 'LEFT OUTER JOIN' => 'LEFT', 'RIGHT JOIN' => 'RIGHT', 'RIGHT OUTER JOIN' => 'RIGHT', + 'NATURAL JOIN' => 'NATURAL', + 'NATURAL LEFT JOIN' => 'NATURAL LEFT', + 'NATURAL LEFT JOIN' => 'NATURAL LEFT', + 'NATURAL RIGHT JOIN' => 'NATURAL RIGHT', + 'NATURAL LEFT OUTER JOIN' => 'NATURAL LEFT OUTER', + 'NATURAL RIGHT OUTER JOIN' => 'NATURAL RIGHT OUTER', 'STRAIGHT_JOIN' => 'STRAIGHT', ); @@ -147,8 +154,17 @@ class JoinKeyword extends Component } elseif ($token->value === 'USING') { $state = 4; } else { - /* Next clause is starting */ - break; + if (($token->type === Token::TYPE_KEYWORD) + && (!empty(static::$JOINS[$token->value])) + ) { + $ret[] = $expr; + $expr = new JoinKeyword(); + $expr->type = static::$JOINS[$token->value]; + $state = 1; + } else { + /* Next clause is starting */ + break; + } } } } elseif ($state === 3) { diff --git a/libraries/sql-parser/src/Context.php b/libraries/sql-parser/src/Context.php index 0bdc6960db..3685857b7c 100644 --- a/libraries/sql-parser/src/Context.php +++ b/libraries/sql-parser/src/Context.php @@ -29,6 +29,16 @@ abstract class Context */ const KEYWORD_MAX_LENGTH = 30; + /** + * The maximum length of a label. + * + * @see static::$TOKEN_LABEL + * Ref: https://dev.mysql.com/doc/refman/5.7/en/statement-labels.html + * + * @var int + */ + const LABEL_MAX_LENGTH = 16; + /** * The maximum length of an operator. * diff --git a/libraries/sql-parser/src/Contexts/ContextMySql50000.php b/libraries/sql-parser/src/Contexts/ContextMySql50000.php index 4931faa1ff..f8afd18f36 100644 --- a/libraries/sql-parser/src/Contexts/ContextMySql50000.php +++ b/libraries/sql-parser/src/Contexts/ContextMySql50000.php @@ -145,20 +145,21 @@ class ContextMySql50000 extends Context 'AND CHAIN' => 7, 'FULL JOIN' => 7, 'IF EXISTS' => 7, 'LEFT JOIN' => 7, 'LESS THAN' => 7, 'NO ACTION' => 7, 'ON DELETE' => 7, 'ON UPDATE' => 7, 'UNION ALL' => 7, - 'INNER JOIN' => 7, 'LINEAR KEY' => 7, 'NO RELEASE' => 7, 'OR REPLACE' => 7, - 'RIGHT JOIN' => 7, + 'CROSS JOIN' => 7, 'INNER JOIN' => 7, 'LINEAR KEY' => 7, 'NO RELEASE' => 7, + 'OR REPLACE' => 7, 'RIGHT JOIN' => 7, 'LINEAR HASH' => 7, - 'AND NO CHAIN' => 7, 'FOR EACH ROW' => 7, 'PARTITION BY' => 7, - 'SET PASSWORD' => 7, 'SQL SECURITY' => 7, + 'AND NO CHAIN' => 7, 'FOR EACH ROW' => 7, 'NATURAL JOIN' => 7, + 'PARTITION BY' => 7, 'SET PASSWORD' => 7, 'SQL SECURITY' => 7, 'CHARACTER SET' => 7, 'IF NOT EXISTS' => 7, 'DATA DIRECTORY' => 7, 'UNION DISTINCT' => 7, 'DEFAULT CHARSET' => 7, 'DEFAULT COLLATE' => 7, 'FULL OUTER JOIN' => 7, 'INDEX DIRECTORY' => 7, 'LEFT OUTER JOIN' => 7, 'SUBPARTITION BY' => 7, 'GENERATED ALWAYS' => 7, 'RIGHT OUTER JOIN' => 7, - 'START TRANSACTION' => 7, - 'SELECT TRANSACTION' => 7, + 'NATURAL LEFT JOIN' => 7, 'START TRANSACTION' => 7, + 'NATURAL RIGHT JOIN' => 7, 'SELECT TRANSACTION' => 7, 'DEFAULT CHARACTER SET' => 7, - 'WITH CONSISTENT SNAPSHOT' => 7, + 'NATURAL LEFT OUTER JOIN' => 7, + 'NATURAL RIGHT OUTER JOIN' => 7, 'WITH CONSISTENT SNAPSHOT' => 7, 'BIT' => 9, 'XML' => 9, 'ENUM' => 9, 'JSON' => 9, 'TEXT' => 9, diff --git a/libraries/sql-parser/src/Contexts/ContextMySql50100.php b/libraries/sql-parser/src/Contexts/ContextMySql50100.php index a547e6405d..dd2b6774c0 100644 --- a/libraries/sql-parser/src/Contexts/ContextMySql50100.php +++ b/libraries/sql-parser/src/Contexts/ContextMySql50100.php @@ -159,20 +159,21 @@ class ContextMySql50100 extends Context 'AND CHAIN' => 7, 'FULL JOIN' => 7, 'IF EXISTS' => 7, 'LEFT JOIN' => 7, 'LESS THAN' => 7, 'NO ACTION' => 7, 'ON DELETE' => 7, 'ON UPDATE' => 7, 'UNION ALL' => 7, - 'INNER JOIN' => 7, 'LINEAR KEY' => 7, 'NO RELEASE' => 7, 'OR REPLACE' => 7, - 'RIGHT JOIN' => 7, + 'CROSS JOIN' => 7, 'INNER JOIN' => 7, 'LINEAR KEY' => 7, 'NO RELEASE' => 7, + 'OR REPLACE' => 7, 'RIGHT JOIN' => 7, 'LINEAR HASH' => 7, - 'AND NO CHAIN' => 7, 'FOR EACH ROW' => 7, 'PARTITION BY' => 7, - 'SET PASSWORD' => 7, 'SQL SECURITY' => 7, + 'AND NO CHAIN' => 7, 'FOR EACH ROW' => 7, 'NATURAL JOIN' => 7, + 'PARTITION BY' => 7, 'SET PASSWORD' => 7, 'SQL SECURITY' => 7, 'CHARACTER SET' => 7, 'IF NOT EXISTS' => 7, 'DATA DIRECTORY' => 7, 'UNION DISTINCT' => 7, 'DEFAULT CHARSET' => 7, 'DEFAULT COLLATE' => 7, 'FULL OUTER JOIN' => 7, 'INDEX DIRECTORY' => 7, 'LEFT OUTER JOIN' => 7, 'SUBPARTITION BY' => 7, 'GENERATED ALWAYS' => 7, 'RIGHT OUTER JOIN' => 7, - 'START TRANSACTION' => 7, - 'SELECT TRANSACTION' => 7, + 'NATURAL LEFT JOIN' => 7, 'START TRANSACTION' => 7, + 'NATURAL RIGHT JOIN' => 7, 'SELECT TRANSACTION' => 7, 'DEFAULT CHARACTER SET' => 7, - 'WITH CONSISTENT SNAPSHOT' => 7, + 'NATURAL LEFT OUTER JOIN' => 7, + 'NATURAL RIGHT OUTER JOIN' => 7, 'WITH CONSISTENT SNAPSHOT' => 7, 'BIT' => 9, 'XML' => 9, 'ENUM' => 9, 'JSON' => 9, 'TEXT' => 9, diff --git a/libraries/sql-parser/src/Contexts/ContextMySql50500.php b/libraries/sql-parser/src/Contexts/ContextMySql50500.php index a15744a8b0..02acdacf0a 100644 --- a/libraries/sql-parser/src/Contexts/ContextMySql50500.php +++ b/libraries/sql-parser/src/Contexts/ContextMySql50500.php @@ -163,20 +163,21 @@ class ContextMySql50500 extends Context 'AND CHAIN' => 7, 'FULL JOIN' => 7, 'IF EXISTS' => 7, 'LEFT JOIN' => 7, 'LESS THAN' => 7, 'NO ACTION' => 7, 'ON DELETE' => 7, 'ON UPDATE' => 7, 'UNION ALL' => 7, - 'INNER JOIN' => 7, 'LINEAR KEY' => 7, 'NO RELEASE' => 7, 'OR REPLACE' => 7, - 'RIGHT JOIN' => 7, + 'CROSS JOIN' => 7, 'INNER JOIN' => 7, 'LINEAR KEY' => 7, 'NO RELEASE' => 7, + 'OR REPLACE' => 7, 'RIGHT JOIN' => 7, 'LINEAR HASH' => 7, - 'AND NO CHAIN' => 7, 'FOR EACH ROW' => 7, 'PARTITION BY' => 7, - 'SET PASSWORD' => 7, 'SQL SECURITY' => 7, + 'AND NO CHAIN' => 7, 'FOR EACH ROW' => 7, 'NATURAL JOIN' => 7, + 'PARTITION BY' => 7, 'SET PASSWORD' => 7, 'SQL SECURITY' => 7, 'CHARACTER SET' => 7, 'IF NOT EXISTS' => 7, 'DATA DIRECTORY' => 7, 'UNION DISTINCT' => 7, 'DEFAULT CHARSET' => 7, 'DEFAULT COLLATE' => 7, 'FULL OUTER JOIN' => 7, 'INDEX DIRECTORY' => 7, 'LEFT OUTER JOIN' => 7, 'SUBPARTITION BY' => 7, 'GENERATED ALWAYS' => 7, 'RIGHT OUTER JOIN' => 7, - 'START TRANSACTION' => 7, - 'SELECT TRANSACTION' => 7, + 'NATURAL LEFT JOIN' => 7, 'START TRANSACTION' => 7, + 'NATURAL RIGHT JOIN' => 7, 'SELECT TRANSACTION' => 7, 'DEFAULT CHARACTER SET' => 7, - 'WITH CONSISTENT SNAPSHOT' => 7, + 'NATURAL LEFT OUTER JOIN' => 7, + 'NATURAL RIGHT OUTER JOIN' => 7, 'WITH CONSISTENT SNAPSHOT' => 7, 'BIT' => 9, 'XML' => 9, 'ENUM' => 9, 'JSON' => 9, 'TEXT' => 9, diff --git a/libraries/sql-parser/src/Contexts/ContextMySql50600.php b/libraries/sql-parser/src/Contexts/ContextMySql50600.php index 7a0cf56234..11439780a5 100644 --- a/libraries/sql-parser/src/Contexts/ContextMySql50600.php +++ b/libraries/sql-parser/src/Contexts/ContextMySql50600.php @@ -169,20 +169,21 @@ class ContextMySql50600 extends Context 'AND CHAIN' => 7, 'FULL JOIN' => 7, 'IF EXISTS' => 7, 'LEFT JOIN' => 7, 'LESS THAN' => 7, 'NO ACTION' => 7, 'ON DELETE' => 7, 'ON UPDATE' => 7, 'UNION ALL' => 7, - 'INNER JOIN' => 7, 'LINEAR KEY' => 7, 'NO RELEASE' => 7, 'OR REPLACE' => 7, - 'RIGHT JOIN' => 7, + 'CROSS JOIN' => 7, 'INNER JOIN' => 7, 'LINEAR KEY' => 7, 'NO RELEASE' => 7, + 'OR REPLACE' => 7, 'RIGHT JOIN' => 7, 'LINEAR HASH' => 7, - 'AND NO CHAIN' => 7, 'FOR EACH ROW' => 7, 'PARTITION BY' => 7, - 'SET PASSWORD' => 7, 'SQL SECURITY' => 7, + 'AND NO CHAIN' => 7, 'FOR EACH ROW' => 7, 'NATURAL JOIN' => 7, + 'PARTITION BY' => 7, 'SET PASSWORD' => 7, 'SQL SECURITY' => 7, 'CHARACTER SET' => 7, 'IF NOT EXISTS' => 7, 'DATA DIRECTORY' => 7, 'UNION DISTINCT' => 7, 'DEFAULT CHARSET' => 7, 'DEFAULT COLLATE' => 7, 'FULL OUTER JOIN' => 7, 'INDEX DIRECTORY' => 7, 'LEFT OUTER JOIN' => 7, 'SUBPARTITION BY' => 7, 'GENERATED ALWAYS' => 7, 'RIGHT OUTER JOIN' => 7, - 'START TRANSACTION' => 7, - 'SELECT TRANSACTION' => 7, + 'NATURAL LEFT JOIN' => 7, 'START TRANSACTION' => 7, + 'NATURAL RIGHT JOIN' => 7, 'SELECT TRANSACTION' => 7, 'DEFAULT CHARACTER SET' => 7, - 'WITH CONSISTENT SNAPSHOT' => 7, + 'NATURAL LEFT OUTER JOIN' => 7, + 'NATURAL RIGHT OUTER JOIN' => 7, 'WITH CONSISTENT SNAPSHOT' => 7, 'BIT' => 9, 'XML' => 9, 'ENUM' => 9, 'JSON' => 9, 'TEXT' => 9, diff --git a/libraries/sql-parser/src/Contexts/ContextMySql50700.php b/libraries/sql-parser/src/Contexts/ContextMySql50700.php index 8682032dc3..04f410b592 100644 --- a/libraries/sql-parser/src/Contexts/ContextMySql50700.php +++ b/libraries/sql-parser/src/Contexts/ContextMySql50700.php @@ -175,20 +175,21 @@ class ContextMySql50700 extends Context 'AND CHAIN' => 7, 'FULL JOIN' => 7, 'IF EXISTS' => 7, 'LEFT JOIN' => 7, 'LESS THAN' => 7, 'NO ACTION' => 7, 'ON DELETE' => 7, 'ON UPDATE' => 7, 'UNION ALL' => 7, - 'INNER JOIN' => 7, 'LINEAR KEY' => 7, 'NO RELEASE' => 7, 'OR REPLACE' => 7, - 'RIGHT JOIN' => 7, + 'CROSS JOIN' => 7, 'INNER JOIN' => 7, 'LINEAR KEY' => 7, 'NO RELEASE' => 7, + 'OR REPLACE' => 7, 'RIGHT JOIN' => 7, 'LINEAR HASH' => 7, - 'AND NO CHAIN' => 7, 'FOR EACH ROW' => 7, 'PARTITION BY' => 7, - 'SET PASSWORD' => 7, 'SQL SECURITY' => 7, + 'AND NO CHAIN' => 7, 'FOR EACH ROW' => 7, 'NATURAL JOIN' => 7, + 'PARTITION BY' => 7, 'SET PASSWORD' => 7, 'SQL SECURITY' => 7, 'CHARACTER SET' => 7, 'IF NOT EXISTS' => 7, 'DATA DIRECTORY' => 7, 'UNION DISTINCT' => 7, 'DEFAULT CHARSET' => 7, 'DEFAULT COLLATE' => 7, 'FULL OUTER JOIN' => 7, 'INDEX DIRECTORY' => 7, 'LEFT OUTER JOIN' => 7, 'SUBPARTITION BY' => 7, 'GENERATED ALWAYS' => 7, 'RIGHT OUTER JOIN' => 7, - 'START TRANSACTION' => 7, - 'SELECT TRANSACTION' => 7, + 'NATURAL LEFT JOIN' => 7, 'START TRANSACTION' => 7, + 'NATURAL RIGHT JOIN' => 7, 'SELECT TRANSACTION' => 7, 'DEFAULT CHARACTER SET' => 7, - 'WITH CONSISTENT SNAPSHOT' => 7, + 'NATURAL LEFT OUTER JOIN' => 7, + 'NATURAL RIGHT OUTER JOIN' => 7, 'WITH CONSISTENT SNAPSHOT' => 7, 'BIT' => 9, 'XML' => 9, 'ENUM' => 9, 'JSON' => 9, 'TEXT' => 9, diff --git a/libraries/sql-parser/src/Lexer.php b/libraries/sql-parser/src/Lexer.php index 7fb2356d76..9de2a7ab14 100644 --- a/libraries/sql-parser/src/Lexer.php +++ b/libraries/sql-parser/src/Lexer.php @@ -76,7 +76,7 @@ class Lexer 'parseDelimiter', 'parseWhitespace', 'parseNumber', 'parseComment', 'parseOperator', 'parseBool', 'parseString', - 'parseSymbol', 'parseKeyword', 'parseUnknown' + 'parseSymbol', 'parseKeyword', 'parseLabel', 'parseUnknown' ); /** @@ -441,6 +441,61 @@ class Lexer return $ret; } + /** + * Parses a label. + * + * @return Token + */ + public function parseLabel() + { + $token = ''; + + /** + * Value to be returned. + * + * @var Token $ret + */ + $ret = null; + + /** + * The value of `$this->last` where `$token` ends in `$this->str`. + * + * @var int $iEnd + */ + $iEnd = $this->last; + + /** + * Whether last parsed character is a whitespace. + * + * @var bool $lastSpace + */ + $lastSpace = false; + + for ($j = 1; $j < Context::LABEL_MAX_LENGTH && $this->last < $this->len; ++$j, ++$this->last) { + // Composed keywords shouldn't have more than one whitespace between + // keywords. + if (Context::isWhitespace($this->str[$this->last])) { + if ($lastSpace) { + --$j; // The size of the keyword didn't increase. + continue; + } else { + $lastSpace = true; + } + } elseif ($this->str[$this->last] === ':') { + $token .= $this->str[$this->last]; + $ret = new Token($token, Token::TYPE_LABEL); + $iEnd = $this->last; + break; + } else { + $lastSpace = false; + } + $token .= $this->str[$this->last]; + } + + $this->last = $iEnd; + return $ret; + } + /** * Parses an operator. * diff --git a/libraries/sql-parser/src/Parser.php b/libraries/sql-parser/src/Parser.php index 21e1b395f9..0d48a41936 100644 --- a/libraries/sql-parser/src/Parser.php +++ b/libraries/sql-parser/src/Parser.php @@ -154,6 +154,10 @@ class Parser 'field' => 'tables', 'options' => array('parseField' => 'table'), ), + 'CROSS JOIN' => array( + 'class' => 'SqlParser\\Components\\JoinKeyword', + 'field' => 'join', + ), 'DROP' => array( 'class' => 'SqlParser\\Components\\ExpressionArray', 'field' => 'fields', @@ -213,7 +217,23 @@ class Parser 'class' => 'SqlParser\\Components\\JoinKeyword', 'field' => 'join', ), - 'STRAIGHT_JOIN' => array( + 'NATURAL JOIN' => array( + 'class' => 'SqlParser\\Components\\JoinKeyword', + 'field' => 'join', + ), + 'NATURAL LEFT JOIN' => array( + 'class' => 'SqlParser\\Components\\JoinKeyword', + 'field' => 'join', + ), + 'NATURAL RIGHT JOIN' => array( + 'class' => 'SqlParser\\Components\\JoinKeyword', + 'field' => 'join', + ), + 'NATURAL LEFT OUTER JOIN' => array( + 'class' => 'SqlParser\\Components\\JoinKeyword', + 'field' => 'join', + ), + 'NATURAL RIGHT OUTER JOIN' => array( 'class' => 'SqlParser\\Components\\JoinKeyword', 'field' => 'join', ), diff --git a/libraries/sql-parser/src/Statements/SelectStatement.php b/libraries/sql-parser/src/Statements/SelectStatement.php index 34a68c3e45..8ff0b454c1 100644 --- a/libraries/sql-parser/src/Statements/SelectStatement.php +++ b/libraries/sql-parser/src/Statements/SelectStatement.php @@ -82,30 +82,35 @@ class SelectStatement extends Statement * @var array */ public static $CLAUSES = array( - 'SELECT' => array('SELECT', 2), + 'SELECT' => array('SELECT', 2), // Used for options. - '_OPTIONS' => array('_OPTIONS', 1), + '_OPTIONS' => array('_OPTIONS', 1), // Used for selected expressions. - '_SELECT' => array('SELECT', 1), - 'INTO' => array('INTO', 3), - 'FROM' => array('FROM', 3), - 'PARTITION' => array('PARTITION', 3), + '_SELECT' => array('SELECT', 1), + 'INTO' => array('INTO', 3), + 'FROM' => array('FROM', 3), + 'PARTITION' => array('PARTITION', 3), - 'JOIN' => array('JOIN', 1), - 'FULL JOIN' => array('FULL JOIN', 1), - 'INNER JOIN' => array('INNER JOIN', 1), - 'LEFT JOIN' => array('LEFT JOIN', 1), - 'LEFT OUTER JOIN' => array('LEFT OUTER JOIN', 1), - 'RIGHT JOIN' => array('RIGHT JOIN', 1), - 'RIGHT OUTER JOIN' => array('RIGHT OUTER JOIN', 1), + 'JOIN' => array('JOIN', 1), + 'FULL JOIN' => array('FULL JOIN', 1), + 'INNER JOIN' => array('INNER JOIN', 1), + 'LEFT JOIN' => array('LEFT JOIN', 1), + 'LEFT OUTER JOIN' => array('LEFT OUTER JOIN', 1), + 'RIGHT JOIN' => array('RIGHT JOIN', 1), + 'RIGHT OUTER JOIN' => array('RIGHT OUTER JOIN', 1), + 'NATURAL JOIN' => array('NATURAL JOIN', 1), + 'NATURAL LEFT JOIN' => array('NATURAL LEFT JOIN', 1), + 'NATURAL RIGHT JOIN' => array('NATURAL RIGHT JOIN', 1), + 'NATURAL LEFT OUTER JOIN' => array('NATURAL LEFT OUTER JOIN', 1), + 'NATURAL RIGHT OUTER JOIN' => array('NATURAL RIGHT JOIN', 1), - 'WHERE' => array('WHERE', 3), - 'GROUP BY' => array('GROUP BY', 3), - 'HAVING' => array('HAVING', 3), - 'ORDER BY' => array('ORDER BY', 3), - 'LIMIT' => array('LIMIT', 3), - 'PROCEDURE' => array('PROCEDURE', 3), - 'UNION' => array('UNION', 1), + 'WHERE' => array('WHERE', 3), + 'GROUP BY' => array('GROUP BY', 3), + 'HAVING' => array('HAVING', 3), + 'ORDER BY' => array('ORDER BY', 3), + 'LIMIT' => array('LIMIT', 3), + 'PROCEDURE' => array('PROCEDURE', 3), + 'UNION' => array('UNION', 1), // These are available only when `UNION` is present. // 'ORDER BY' => array('ORDER BY', 3), // 'LIMIT' => array('LIMIT', 3), diff --git a/libraries/sql-parser/src/Token.php b/libraries/sql-parser/src/Token.php index 3181a446ab..e5001ef9e1 100644 --- a/libraries/sql-parser/src/Token.php +++ b/libraries/sql-parser/src/Token.php @@ -119,6 +119,18 @@ class Token */ const TYPE_DELIMITER = 9; + /** + * Labels in LOOP statement, ITERATE statement etc. + * For example (only for begin label): + * begin_label: BEGIN [statement_list] END [end_label] + * begin_label: LOOP [statement_list] END LOOP [end_label] + * begin_label: REPEAT [statement_list] ... END REPEAT [end_label] + * begin_label: WHILE ... DO [statement_list] END WHILE [end_label] + * + * @var int + */ + const TYPE_LABEL = 10; + // Flags that describe the tokens in more detail. // All keywords must have flag 1 so `Context::isKeyword` method doesn't // require strict comparison.