404

[ Avaa Bypassed ]




Upload:

Command:

botdev@3.143.110.79: ~ $
<?php

/**
 * Defines the parser of the library.
 *
 * This is one of the most important components, along with the lexer.
 */

namespace SqlParser;

require_once 'common.php';

use SqlParser\Exceptions\ParserException;
use SqlParser\Statements\SelectStatement;
use SqlParser\Statements\TransactionStatement;

/**
 * Takes multiple tokens (contained in a Lexer instance) as input and builds a
 * parse tree.
 *
 * @category Parser
 *
 * @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' => '',

        // 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',

        // 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',

        // 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',

        // 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',

        // Prepared Statements.
        // https://dev.mysql.com/doc/refman/5.7/en/sql-syntax-prepared-statements.html
        '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',
        'START TRANSACTION' => 'SqlParser\\Statements\\TransactionStatement',
    );

    /**
     * Array of classes that are used in parsing SQL components.
     *
     * @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(),

        // This is not a proper keyword and was added here to help the
        // builder.
        '_OPTIONS' => array(
            'class' => 'SqlParser\\Components\\OptionsArray',
            'field' => 'options',
        ),
        '_END_OPTIONS' => array(
            'class' => 'SqlParser\\Components\\OptionsArray',
            'field' => 'end_options',
        ),

        'UNION' => 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',
        ),

        // 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'),
        ),
        'RESTORE' => array(
            'class' => 'SqlParser\\Components\\ExpressionArray',
            'field' => 'tables',
            'options' => array('parseField' => 'table'),
        ),
        'SET' => array(
            'class' => 'SqlParser\\Components\\SetOperation',
            'field' => 'set',
        ),
        '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',
        ),
    );

    /**
     * The list of tokens that are parsed.
     *
     * @var TokensList
     */
    public $list;

    /**
     * Whether errors should throw exceptions or just be stored.
     *
     * @var bool
     *
     * @see static::$errors
     */
    public $strict = false;

    /**
     * List of errors that occurred during parsing.
     *
     * Usually, the parsing does not stop once an error occurred because that
     * error might be a false positive or a partial result (even a bad one)
     * might be needed.
     *
     * @var ParserException[]
     *
     * @see Parser::error()
     */
    public $errors = array();

    /**
     * List of statements parsed.
     *
     * @var Statement[]
     */
    public $statements = array();

    /**
     * The number of opened brackets.
     *
     * @var int
     */
    public $brackets = 0;

    /**
     * Constructor.
     *
     * @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)
    {
        if ((is_string($list)) || ($list instanceof UtfString)) {
            $lexer = new Lexer($list, $strict);
            $this->list = $lexer->list;
        } elseif ($list instanceof TokensList) {
            $this->list = $list;
        }

        $this->strict = $strict;

        if ($list !== null) {
            $this->parse();
        }
    }

    /**
     * Builds the parse trees.
     */
    public function parse()
    {
        /**
         * Last transaction.
         *
         * @var TransactionStatement
         */
        $lastTransaction = null;

        /**
         * Last parsed statement.
         *
         * @var Statement
         */
        $lastStatement = null;

        /**
         * Union's type or false for no union.
         *
         * @var bool|string
         */
        $unionType = false;

        /**
         * The index of the last token from the last statement.
         *
         * @var int
         */
        $prevLastIdx = -1;

        /**
         * The list of tokens.
         *
         * @var TokensList
         */
        $list = &$this->list;

        for (; $list->idx < $list->count; ++$list->idx) {
            /**
             * Token parsed at this moment.
             *
             * @var Token
             */
            $token = $list->tokens[$list->idx];

            // `DELIMITER` is not an actual statement and it requires
            // special handling.
            if (($token->type === Token::TYPE_NONE)
                && (strtoupper($token->token) === 'DELIMITER')
            ) {
                // Skipping to the end of this statement.
                $list->getNextOfType(Token::TYPE_DELIMITER);
                $prevLastIdx = $list->idx;
                continue;
            }

            // Counting the brackets around statements.
            if ($token->value === '(') {
                ++$this->brackets;
                continue;
            }

            // 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;
            }

            if (($token->value === 'UNION') || ($token->value === 'UNION ALL') || ($token->value === 'UNION DISTINCT')) {
                $unionType = $token->value;
                continue;
            }

            // Checking if it is a known statement that can be parsed.
            if (empty(static::$STATEMENT_PARSERS[$token->value])) {
                if (!isset(static::$STATEMENT_PARSERS[$token->value])) {
                    // A statement is considered recognized if the parser
                    // is aware that it is a statement, but it does not have
                    // a parser for it yet.
                    $this->error(
                        __('Unrecognized statement type.'),
                        $token
                    );
                }
                // Skipping to the end of this statement.
                $list->getNextOfType(Token::TYPE_DELIMITER);
                $prevLastIdx = $list->idx;
                continue;
            }

            /**
             * The name of the class that is used for parsing.
             *
             * @var string
             */
            $class = static::$STATEMENT_PARSERS[$token->value];

            /**
             * Processed statement.
             *
             * @var Statement
             */
            $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
            $statement->first = $prevLastIdx + 1;

            // Storing the index of the last token parsed and updating the old
            // index.
            $statement->last = $list->idx;
            $prevLastIdx = $list->idx;

            // Handles unions.
            if ((!empty($unionType))
                && ($lastStatement instanceof SelectStatement)
                && ($statement instanceof SelectStatement)
            ) {
                /*
                 * This SELECT statement.
                 *
                 * @var SelectStatement $statement
                 */

                /*
                 * Last SELECT statement.
                 *
                 * @var SelectStatement $lastStatement
                 */
                $lastStatement->union[] = array($unionType, $statement);

                // if there are no no delimiting brackets, the `ORDER` and
                // `LIMIT` keywords actually belong to the first statement.
                $lastStatement->order = $statement->order;
                $lastStatement->limit = $statement->limit;
                $statement->order = array();
                $statement->limit = null;

                // The statement actually ends where the last statement in
                // union ends.
                $lastStatement->last = $statement->last;

                $unionType = false;

                // Validate clause order
                $statement->validateClauseOrder($this, $list);
                continue;
            }

            // Handles transactions.
            if ($statement instanceof TransactionStatement) {
                /*
                 * @var TransactionStatement
                 */
                if ($statement->type === TransactionStatement::TYPE_BEGIN) {
                    $lastTransaction = $statement;
                    $this->statements[] = $statement;
                } elseif ($statement->type === TransactionStatement::TYPE_END) {
                    if ($lastTransaction === null) {
                        // Even though an error occurred, the query is being
                        // saved.
                        $this->statements[] = $statement;
                        $this->error(
                            __('No transaction was previously started.'),
                            $token
                        );
                    } else {
                        $lastTransaction->end = $statement;
                    }
                    $lastTransaction = null;
                }

                // Validate clause order
                $statement->validateClauseOrder($this, $list);
                continue;
            }

            // Validate clause order
            $statement->validateClauseOrder($this, $list);

            // Finally, storing the statement.
            if ($lastTransaction !== null) {
                $lastTransaction->statements[] = $statement;
            } else {
                $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
     */
    public function error($msg = '', Token $token = null, $code = 0)
    {
        $error = new ParserException($msg, $token, $code);
        if ($this->strict) {
            throw $error;
        }
        $this->errors[] = $error;
    }
}

Filemanager

Name Type Size Permission Actions
Components Folder 0755
Contexts Folder 0755
Exceptions Folder 0755
Statements Folder 0755
Utils Folder 0755
Component.php File 2.1 KB 0644
Context.php File 16.2 KB 0644
Lexer.php File 29.23 KB 0644
Parser.php File 19.33 KB 0644
Statement.php File 15.25 KB 0644
Token.php File 8.02 KB 0644
TokensList.php File 4.39 KB 0644
UtfString.php File 4.65 KB 0644
common.php File 288 B 0644