summaryrefslogtreecommitdiffstats
path: root/src/Parser.php
diff options
context:
space:
mode:
Diffstat (limited to 'src/Parser.php')
-rw-r--r--src/Parser.php508
1 files changed, 248 insertions, 260 deletions
diff --git a/src/Parser.php b/src/Parser.php
index ddefc7e..1ad5bb8 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -4,9 +4,8 @@
* Defines the parser of the library.
*
* This is one of the most important components, along with the lexer.
- *
- * @package SqlParser
*/
+
namespace SqlParser;
require_once 'common.php';
@@ -20,76 +19,74 @@ use SqlParser\Statements\TransactionStatement;
* parse tree.
*
* @category Parser
- * @package SqlParser
+ *
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL-2.0+
*/
class Parser
{
-
/**
* Array of classes that are used in parsing the SQL statements.
*
* @var array
*/
public static $STATEMENT_PARSERS = array(
-
// MySQL Utility Statements
- 'DESCRIBE' => 'SqlParser\\Statements\\ExplainStatement',
- 'DESC' => 'SqlParser\\Statements\\ExplainStatement',
- 'EXPLAIN' => 'SqlParser\\Statements\\ExplainStatement',
- 'FLUSH' => '',
- 'GRANT' => '',
- 'HELP' => '',
- 'SET PASSWORD' => '',
- 'STATUS' => '',
- 'USE' => '',
+ 'DESCRIBE' => 'SqlParser\\Statements\\ExplainStatement',
+ 'DESC' => 'SqlParser\\Statements\\ExplainStatement',
+ 'EXPLAIN' => 'SqlParser\\Statements\\ExplainStatement',
+ 'FLUSH' => '',
+ 'GRANT' => '',
+ 'HELP' => '',
+ 'SET PASSWORD' => '',
+ 'STATUS' => '',
+ 'USE' => '',
// Table Maintenance Statements
// https://dev.mysql.com/doc/refman/5.7/en/table-maintenance-sql.html
- 'ANALYZE' => 'SqlParser\\Statements\\AnalyzeStatement',
- 'BACKUP' => 'SqlParser\\Statements\\BackupStatement',
- 'CHECK' => 'SqlParser\\Statements\\CheckStatement',
- 'CHECKSUM' => 'SqlParser\\Statements\\ChecksumStatement',
- 'OPTIMIZE' => 'SqlParser\\Statements\\OptimizeStatement',
- 'REPAIR' => 'SqlParser\\Statements\\RepairStatement',
- 'RESTORE' => 'SqlParser\\Statements\\RestoreStatement',
+ 'ANALYZE' => 'SqlParser\\Statements\\AnalyzeStatement',
+ 'BACKUP' => 'SqlParser\\Statements\\BackupStatement',
+ 'CHECK' => 'SqlParser\\Statements\\CheckStatement',
+ 'CHECKSUM' => 'SqlParser\\Statements\\ChecksumStatement',
+ 'OPTIMIZE' => 'SqlParser\\Statements\\OptimizeStatement',
+ 'REPAIR' => 'SqlParser\\Statements\\RepairStatement',
+ 'RESTORE' => 'SqlParser\\Statements\\RestoreStatement',
// Database Administration Statements
// https://dev.mysql.com/doc/refman/5.7/en/sql-syntax-server-administration.html
- 'SET' => 'SqlParser\\Statements\\SetStatement',
- 'SHOW' => 'SqlParser\\Statements\\ShowStatement',
+ 'SET' => 'SqlParser\\Statements\\SetStatement',
+ 'SHOW' => 'SqlParser\\Statements\\ShowStatement',
// Data Definition Statements.
// https://dev.mysql.com/doc/refman/5.7/en/sql-syntax-data-definition.html
- 'ALTER' => 'SqlParser\\Statements\\AlterStatement',
- 'CREATE' => 'SqlParser\\Statements\\CreateStatement',
- 'DROP' => 'SqlParser\\Statements\\DropStatement',
- 'RENAME' => 'SqlParser\\Statements\\RenameStatement',
- 'TRUNCATE' => 'SqlParser\\Statements\\TruncateStatement',
+ 'ALTER' => 'SqlParser\\Statements\\AlterStatement',
+ 'CREATE' => 'SqlParser\\Statements\\CreateStatement',
+ 'DROP' => 'SqlParser\\Statements\\DropStatement',
+ 'RENAME' => 'SqlParser\\Statements\\RenameStatement',
+ 'TRUNCATE' => 'SqlParser\\Statements\\TruncateStatement',
// Data Manipulation Statements.
// https://dev.mysql.com/doc/refman/5.7/en/sql-syntax-data-manipulation.html
- 'CALL' => 'SqlParser\\Statements\\CallStatement',
- 'DELETE' => 'SqlParser\\Statements\\DeleteStatement',
- 'DO' => '',
- 'HANDLER' => '',
- 'INSERT' => 'SqlParser\\Statements\\InsertStatement',
- 'LOAD' => '',
- 'REPLACE' => 'SqlParser\\Statements\\ReplaceStatement',
- 'SELECT' => 'SqlParser\\Statements\\SelectStatement',
- 'UPDATE' => 'SqlParser\\Statements\\UpdateStatement',
+ 'CALL' => 'SqlParser\\Statements\\CallStatement',
+ 'DELETE' => 'SqlParser\\Statements\\DeleteStatement',
+ 'DO' => '',
+ 'HANDLER' => '',
+ 'INSERT' => 'SqlParser\\Statements\\InsertStatement',
+ 'LOAD' => '',
+ 'REPLACE' => 'SqlParser\\Statements\\ReplaceStatement',
+ 'SELECT' => 'SqlParser\\Statements\\SelectStatement',
+ 'UPDATE' => 'SqlParser\\Statements\\UpdateStatement',
// Prepared Statements.
// https://dev.mysql.com/doc/refman/5.7/en/sql-syntax-prepared-statements.html
- 'DEALLOCATE' => '',
- 'EXECUTE' => '',
- 'PREPARE' => '',
+ 'DEALLOCATE' => '',
+ 'EXECUTE' => '',
+ 'PREPARE' => '',
// Transactional and Locking Statements
// https://dev.mysql.com/doc/refman/5.7/en/commit.html
- 'BEGIN' => 'SqlParser\\Statements\\TransactionStatement',
- 'COMMIT' => 'SqlParser\\Statements\\TransactionStatement',
- 'ROLLBACK' => 'SqlParser\\Statements\\TransactionStatement',
+ 'BEGIN' => 'SqlParser\\Statements\\TransactionStatement',
+ 'COMMIT' => 'SqlParser\\Statements\\TransactionStatement',
+ 'ROLLBACK' => 'SqlParser\\Statements\\TransactionStatement',
'START TRANSACTION' => 'SqlParser\\Statements\\TransactionStatement',
);
@@ -99,216 +96,213 @@ class Parser
* @var array
*/
public static $KEYWORD_PARSERS = array(
-
// This is not a proper keyword and was added here to help the
// formatter.
- 'PARTITION BY' => array(),
- 'SUBPARTITION BY' => array(),
+ 'PARTITION BY' => array(),
+ 'SUBPARTITION BY' => array(),
// This is not a proper keyword and was added here to help the
// builder.
- '_OPTIONS' => array(
- 'class' => 'SqlParser\\Components\\OptionsArray',
- 'field' => 'options',
+ '_OPTIONS' => array(
+ 'class' => 'SqlParser\\Components\\OptionsArray',
+ 'field' => 'options',
),
- '_END_OPTIONS' => array(
- 'class' => 'SqlParser\\Components\\OptionsArray',
- 'field' => 'end_options',
+ '_END_OPTIONS' => array(
+ 'class' => 'SqlParser\\Components\\OptionsArray',
+ 'field' => 'end_options',
),
-
- 'UNION' => array(
- 'class' => 'SqlParser\\Components\\UnionKeyword',
- 'field' => 'union',
+ 'UNION' => array(
+ 'class' => 'SqlParser\\Components\\UnionKeyword',
+ 'field' => 'union',
),
- 'UNION ALL' => array(
- 'class' => 'SqlParser\\Components\\UnionKeyword',
- 'field' => 'union',
+ 'UNION ALL' => array(
+ 'class' => 'SqlParser\\Components\\UnionKeyword',
+ 'field' => 'union',
),
- 'UNION DISTINCT' => array(
- 'class' => 'SqlParser\\Components\\UnionKeyword',
- 'field' => 'union',
+ 'UNION DISTINCT' => array(
+ 'class' => 'SqlParser\\Components\\UnionKeyword',
+ 'field' => 'union',
),
// Actual clause parsers.
- 'ALTER' => array(
- 'class' => 'SqlParser\\Components\\Expression',
- 'field' => 'table',
- 'options' => array('parseField' => 'table'),
- ),
- 'ANALYZE' => array(
- 'class' => 'SqlParser\\Components\\ExpressionArray',
- 'field' => 'tables',
- 'options' => array('parseField' => 'table'),
- ),
- 'BACKUP' => array(
- 'class' => 'SqlParser\\Components\\ExpressionArray',
- 'field' => 'tables',
- 'options' => array('parseField' => 'table'),
- ),
- 'CALL' => array(
- 'class' => 'SqlParser\\Components\\FunctionCall',
- 'field' => 'call',
- ),
- 'CHECK' => array(
- 'class' => 'SqlParser\\Components\\ExpressionArray',
- 'field' => 'tables',
- 'options' => array('parseField' => 'table'),
- ),
- 'CHECKSUM' => array(
- 'class' => 'SqlParser\\Components\\ExpressionArray',
- 'field' => 'tables',
- 'options' => array('parseField' => 'table'),
- ),
- 'CROSS JOIN' => array(
- 'class' => 'SqlParser\\Components\\JoinKeyword',
- 'field' => 'join',
- ),
- 'DROP' => array(
- 'class' => 'SqlParser\\Components\\ExpressionArray',
- 'field' => 'fields',
- 'options' => array('parseField' => 'table'),
- ),
- 'FROM' => array(
- 'class' => 'SqlParser\\Components\\ExpressionArray',
- 'field' => 'from',
- 'options' => array('field' => 'table'),
- ),
- 'GROUP BY' => array(
- 'class' => 'SqlParser\\Components\\OrderKeyword',
- 'field' => 'group',
- ),
- 'HAVING' => array(
- 'class' => 'SqlParser\\Components\\Condition',
- 'field' => 'having',
- ),
- 'INTO' => array(
- 'class' => 'SqlParser\\Components\\IntoKeyword',
- 'field' => 'into',
- ),
- 'JOIN' => array(
- 'class' => 'SqlParser\\Components\\JoinKeyword',
- 'field' => 'join',
- ),
- 'LEFT JOIN' => array(
- 'class' => 'SqlParser\\Components\\JoinKeyword',
- 'field' => 'join',
- ),
- 'LEFT OUTER JOIN' => array(
- 'class' => 'SqlParser\\Components\\JoinKeyword',
- 'field' => 'join',
- ),
- 'ON' => array(
- 'class' => 'SqlParser\\Components\\Expression',
- 'field' => 'table',
- 'options' => array('parseField' => 'table'),
- ),
- 'RIGHT JOIN' => array(
- 'class' => 'SqlParser\\Components\\JoinKeyword',
- 'field' => 'join',
- ),
- 'RIGHT OUTER JOIN' => array(
- 'class' => 'SqlParser\\Components\\JoinKeyword',
- 'field' => 'join',
- ),
- 'INNER JOIN' => array(
- 'class' => 'SqlParser\\Components\\JoinKeyword',
- 'field' => 'join',
- ),
- 'FULL JOIN' => array(
- 'class' => 'SqlParser\\Components\\JoinKeyword',
- 'field' => 'join',
- ),
- 'FULL OUTER JOIN' => array(
- 'class' => 'SqlParser\\Components\\JoinKeyword',
- 'field' => 'join',
- ),
- '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',
- ),
- 'LIMIT' => array(
- 'class' => 'SqlParser\\Components\\Limit',
- 'field' => 'limit',
- ),
- 'OPTIMIZE' => array(
- 'class' => 'SqlParser\\Components\\ExpressionArray',
- 'field' => 'tables',
- 'options' => array('parseField' => 'table'),
- ),
- 'ORDER BY' => array(
- 'class' => 'SqlParser\\Components\\OrderKeyword',
- 'field' => 'order',
- ),
- 'PARTITION' => array(
- 'class' => 'SqlParser\\Components\\ArrayObj',
- 'field' => 'partition',
- ),
- 'PROCEDURE' => array(
- 'class' => 'SqlParser\\Components\\FunctionCall',
- 'field' => 'procedure',
- ),
- 'RENAME' => array(
- 'class' => 'SqlParser\\Components\\RenameOperation',
- 'field' => 'renames',
- ),
- 'REPAIR' => array(
- 'class' => 'SqlParser\\Components\\ExpressionArray',
- 'field' => 'tables',
- 'options' => array('parseField' => 'table'),
+ 'ALTER' => array(
+ 'class' => 'SqlParser\\Components\\Expression',
+ 'field' => 'table',
+ 'options' => array('parseField' => 'table'),
+ ),
+ 'ANALYZE' => array(
+ 'class' => 'SqlParser\\Components\\ExpressionArray',
+ 'field' => 'tables',
+ 'options' => array('parseField' => 'table'),
+ ),
+ 'BACKUP' => array(
+ 'class' => 'SqlParser\\Components\\ExpressionArray',
+ 'field' => 'tables',
+ 'options' => array('parseField' => 'table'),
+ ),
+ 'CALL' => array(
+ 'class' => 'SqlParser\\Components\\FunctionCall',
+ 'field' => 'call',
+ ),
+ 'CHECK' => array(
+ 'class' => 'SqlParser\\Components\\ExpressionArray',
+ 'field' => 'tables',
+ 'options' => array('parseField' => 'table'),
+ ),
+ 'CHECKSUM' => array(
+ 'class' => 'SqlParser\\Components\\ExpressionArray',
+ 'field' => 'tables',
+ 'options' => array('parseField' => 'table'),
+ ),
+ 'CROSS JOIN' => array(
+ 'class' => 'SqlParser\\Components\\JoinKeyword',
+ 'field' => 'join',
+ ),
+ 'DROP' => array(
+ 'class' => 'SqlParser\\Components\\ExpressionArray',
+ 'field' => 'fields',
+ 'options' => array('parseField' => 'table'),
+ ),
+ 'FROM' => array(
+ 'class' => 'SqlParser\\Components\\ExpressionArray',
+ 'field' => 'from',
+ 'options' => array('field' => 'table'),
+ ),
+ 'GROUP BY' => array(
+ 'class' => 'SqlParser\\Components\\OrderKeyword',
+ 'field' => 'group',
+ ),
+ 'HAVING' => array(
+ 'class' => 'SqlParser\\Components\\Condition',
+ 'field' => 'having',
+ ),
+ 'INTO' => array(
+ 'class' => 'SqlParser\\Components\\IntoKeyword',
+ 'field' => 'into',
+ ),
+ 'JOIN' => array(
+ 'class' => 'SqlParser\\Components\\JoinKeyword',
+ 'field' => 'join',
+ ),
+ 'LEFT JOIN' => array(
+ 'class' => 'SqlParser\\Components\\JoinKeyword',
+ 'field' => 'join',
+ ),
+ 'LEFT OUTER JOIN' => array(
+ 'class' => 'SqlParser\\Components\\JoinKeyword',
+ 'field' => 'join',
+ ),
+ 'ON' => array(
+ 'class' => 'SqlParser\\Components\\Expression',
+ 'field' => 'table',
+ 'options' => array('parseField' => 'table'),
+ ),
+ 'RIGHT JOIN' => array(
+ 'class' => 'SqlParser\\Components\\JoinKeyword',
+ 'field' => 'join',
+ ),
+ 'RIGHT OUTER JOIN' => array(
+ 'class' => 'SqlParser\\Components\\JoinKeyword',
+ 'field' => 'join',
+ ),
+ 'INNER JOIN' => array(
+ 'class' => 'SqlParser\\Components\\JoinKeyword',
+ 'field' => 'join',
+ ),
+ 'FULL JOIN' => array(
+ 'class' => 'SqlParser\\Components\\JoinKeyword',
+ 'field' => 'join',
+ ),
+ 'FULL OUTER JOIN' => array(
+ 'class' => 'SqlParser\\Components\\JoinKeyword',
+ 'field' => 'join',
+ ),
+ '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',
+ ),
+ 'LIMIT' => array(
+ 'class' => 'SqlParser\\Components\\Limit',
+ 'field' => 'limit',
+ ),
+ 'OPTIMIZE' => array(
+ 'class' => 'SqlParser\\Components\\ExpressionArray',
+ 'field' => 'tables',
+ 'options' => array('parseField' => 'table'),
+ ),
+ 'ORDER BY' => array(
+ 'class' => 'SqlParser\\Components\\OrderKeyword',
+ 'field' => 'order',
+ ),
+ 'PARTITION' => array(
+ 'class' => 'SqlParser\\Components\\ArrayObj',
+ 'field' => 'partition',
+ ),
+ 'PROCEDURE' => array(
+ 'class' => 'SqlParser\\Components\\FunctionCall',
+ 'field' => 'procedure',
+ ),
+ 'RENAME' => array(
+ 'class' => 'SqlParser\\Components\\RenameOperation',
+ 'field' => 'renames',
+ ),
+ 'REPAIR' => array(
+ 'class' => 'SqlParser\\Components\\ExpressionArray',
+ 'field' => 'tables',
+ 'options' => array('parseField' => 'table'),
+ ),
+ 'RESTORE' => array(
+ 'class' => 'SqlParser\\Components\\ExpressionArray',
+ 'field' => 'tables',
+ 'options' => array('parseField' => 'table'),
),
- 'RESTORE' => array(
- 'class' => 'SqlParser\\Components\\ExpressionArray',
- 'field' => 'tables',
- 'options' => array('parseField' => 'table'),
+ 'SET' => array(
+ 'class' => 'SqlParser\\Components\\SetOperation',
+ 'field' => 'set',
),
- 'SET' => array(
- 'class' => 'SqlParser\\Components\\SetOperation',
- 'field' => 'set',
+ 'SELECT' => array(
+ 'class' => 'SqlParser\\Components\\ExpressionArray',
+ 'field' => 'expr',
),
- 'SELECT' => array(
- 'class' => 'SqlParser\\Components\\ExpressionArray',
- 'field' => 'expr',
+ 'TRUNCATE' => array(
+ 'class' => 'SqlParser\\Components\\Expression',
+ 'field' => 'table',
+ 'options' => array('parseField' => 'table'),
+ ),
+ 'UPDATE' => array(
+ 'class' => 'SqlParser\\Components\\ExpressionArray',
+ 'field' => 'tables',
+ 'options' => array('parseField' => 'table'),
+ ),
+ 'VALUE' => array(
+ 'class' => 'SqlParser\\Components\\Array2d',
+ 'field' => 'values',
+ ),
+ 'VALUES' => array(
+ 'class' => 'SqlParser\\Components\\Array2d',
+ 'field' => 'values',
+ ),
+ 'WHERE' => array(
+ 'class' => 'SqlParser\\Components\\Condition',
+ 'field' => 'where',
),
- 'TRUNCATE' => array(
- 'class' => 'SqlParser\\Components\\Expression',
- 'field' => 'table',
- 'options' => array('parseField' => 'table'),
- ),
- 'UPDATE' => array(
- 'class' => 'SqlParser\\Components\\ExpressionArray',
- 'field' => 'tables',
- 'options' => array('parseField' => 'table'),
- ),
- 'VALUE' => array(
- 'class' => 'SqlParser\\Components\\Array2d',
- 'field' => 'values',
- ),
- 'VALUES' => array(
- 'class' => 'SqlParser\\Components\\Array2d',
- 'field' => 'values',
- ),
- 'WHERE' => array(
- 'class' => 'SqlParser\\Components\\Condition',
- 'field' => 'where',
- ),
-
);
/**
@@ -357,8 +351,8 @@ class Parser
/**
* Constructor.
*
- * @param string|UtfString|TokensList $list The list of tokens to be parsed.
- * @param bool $strict Whether strict mode should be enabled or not.
+ * @param string|UtfString|TokensList $list the list of tokens to be parsed
+ * @param bool $strict whether strict mode should be enabled or not
*/
public function __construct($list = null, $strict = false)
{
@@ -378,44 +372,41 @@ class Parser
/**
* Builds the parse trees.
- *
- * @return void
*/
public function parse()
{
-
/**
* Last transaction.
*
- * @var TransactionStatement $lastTransaction
+ * @var TransactionStatement
*/
$lastTransaction = null;
/**
* Last parsed statement.
*
- * @var Statement $lastStatement
+ * @var Statement
*/
$lastStatement = null;
/**
* Union's type or false for no union.
*
- * @var bool|string $unionType
+ * @var bool|string
*/
$unionType = false;
/**
* The index of the last token from the last statement.
*
- * @var int $prevLastIdx
+ * @var int
*/
$prevLastIdx = -1;
/**
* The list of tokens.
*
- * @var TokensList $list
+ * @var TokensList
*/
$list = &$this->list;
@@ -423,7 +414,7 @@ class Parser
/**
* Token parsed at this moment.
*
- * @var Token $token
+ * @var Token
*/
$token = $list->tokens[$list->idx];
@@ -485,14 +476,14 @@ class Parser
/**
* The name of the class that is used for parsing.
*
- * @var string $class
+ * @var string
*/
$class = static::$STATEMENT_PARSERS[$token->value];
/**
* Processed statement.
*
- * @var Statement $statement
+ * @var Statement
*/
$statement = new $class($this, $this->list);
@@ -512,13 +503,13 @@ class Parser
&& ($lastStatement instanceof SelectStatement)
&& ($statement instanceof SelectStatement)
) {
- /**
+ /*
* This SELECT statement.
*
* @var SelectStatement $statement
*/
- /**
+ /*
* Last SELECT statement.
*
* @var SelectStatement $lastStatement
@@ -545,8 +536,8 @@ class Parser
// Handles transactions.
if ($statement instanceof TransactionStatement) {
- /**
- * @var TransactionStatement $statement
+ /*
+ * @var TransactionStatement
*/
if ($statement->type === TransactionStatement::TYPE_BEGIN) {
$lastTransaction = $statement;
@@ -581,20 +572,17 @@ class Parser
$this->statements[] = $statement;
}
$lastStatement = $statement;
-
}
}
/**
* Creates a new error log.
*
- * @param string $msg The error message.
- * @param Token $token The token that produced the error.
- * @param int $code The code of the error.
- *
- * @throws ParserException Throws the exception, if strict mode is enabled.
+ * @param string $msg the error message
+ * @param Token $token the token that produced the error
+ * @param int $code the code of the error
*
- * @return void
+ * @throws ParserException throws the exception, if strict mode is enabled
*/
public function error($msg = '', Token $token = null, $code = 0)
{