diff options
author | Dan Ungureanu <udan1107@gmail.com> | 2015-07-02 01:22:45 +0300 |
---|---|---|
committer | Dan Ungureanu <udan1107@gmail.com> | 2015-07-02 01:22:45 +0300 |
commit | fe199733111d7fa2eef929df39c39ee50bb55d89 (patch) | |
tree | 2094d7d916d3e27634a4bdcbb927f726830f8463 /src | |
parent | 532ada6c8ed9eade76341dc39c99f209192d77e5 (diff) | |
download | sql-parser-fe199733111d7fa2eef929df39c39ee50bb55d89.zip sql-parser-fe199733111d7fa2eef929df39c39ee50bb55d89.tar.gz sql-parser-fe199733111d7fa2eef929df39c39ee50bb55d89.tar.bz2 |
Improved WHERE keyword parser and query's utilities.
Diffstat (limited to 'src')
-rw-r--r-- | src/Fragments/WhereKeyword.php | 51 | ||||
-rw-r--r-- | src/Utils/Query.php | 83 |
2 files changed, 76 insertions, 58 deletions
diff --git a/src/Fragments/WhereKeyword.php b/src/Fragments/WhereKeyword.php index 0710738..f5bec24 100644 --- a/src/Fragments/WhereKeyword.php +++ b/src/Fragments/WhereKeyword.php @@ -30,7 +30,14 @@ class WhereKeyword extends Fragment * * @var array */ - public static $OPERATORS = array('&&', '(', ')', 'AND', 'OR', 'XOR', '||'); + public static $OPERATORS = array('&&', 'AND', 'OR', 'XOR', '||'); + + /** + * Identifiers recognized. + * + * @var array + */ + public $identifiers = array(); /** * Whether this fragment is an operator. @@ -67,11 +74,13 @@ class WhereKeyword extends Fragment { $ret = array(); + $expr = new WhereKeyword(); + /** - * The condition that was parsed so far. - * @var string + * Counts brackets. + * @var int */ - $tmp = ''; + $brackets = 0; for (; $list->idx < $list->count; ++$list->idx) { @@ -93,10 +102,10 @@ class WhereKeyword extends Fragment // Conditions are delimited by logical operators. if (in_array($token->value, static::$OPERATORS, true)) { - if (!empty(trim($tmp))) { + $expr->expr = trim($expr->expr); + if (!empty($expr->expr)) { // Adding the condition that is delimited by this operator. - $ret[] = new WhereKeyword($tmp); - $tmp = ''; + $ret[] = $expr; } // Adding the operator. @@ -104,21 +113,39 @@ class WhereKeyword extends Fragment $expr->isOperator = true; $ret[] = $expr; + $expr = new WhereKeyword(); continue; } + if ($token->type === Token::TYPE_OPERATOR) { + if ($token->value === '(') { + ++$brackets; + } elseif ($token->value === ')') { + --$brackets; + } + } + // No keyword is expected. if (($token->type === Token::TYPE_KEYWORD) && ($token->flags & Token::FLAG_KEYWORD_RESERVED)) { - break; + if ($brackets == 0) { + break; + } } - $tmp .= $token->token; - + $expr->expr .= $token->token; + if (($token->type === Token::TYPE_NONE) + || (($token->type === Token::TYPE_KEYWORD) && (!($token->flags & Token::FLAG_KEYWORD_RESERVED))) + || ($token->type === Token::TYPE_STRING) + || ($token->type === Token::TYPE_SYMBOL) + ) { + $expr->identifiers[] = $token->value; + } } // Last iteration was not processed. - if (!empty(trim($tmp))) { - $ret[] = new WhereKeyword($tmp); + $expr->expr = trim($expr->expr); + if (!empty($expr->expr)) { + $ret[] = $expr; } --$list->idx; diff --git a/src/Utils/Query.php b/src/Utils/Query.php index f973744..11a08d0 100644 --- a/src/Utils/Query.php +++ b/src/Utils/Query.php @@ -8,6 +8,7 @@ */ namespace SqlParser\Utils; +use SqlParser\Lexer; use SqlParser\Parser; use SqlParser\Statement; use SqlParser\Token; @@ -407,32 +408,6 @@ class Query } /** - * Gets the type of clause. - * - * @param string $clause The clause. - * - * @return string - */ - public static function getClauseType($clause) - { - $type = ''; - for ($i = 0, $len = strlen($clause); $i < $len; ++$i) { - if ((empty($type)) && (ctype_space($clause[$i]))) { - // Skipping whitespaces if we haven't started determining the - // type. - continue; - } - if (!ctype_alnum($clause[$i])) { - // The type contains only alphanumeric characters. - break; - } - // Adding character. - $type .= $clause[$i]; - } - return $type; - } - - /** * Gets a specific clause. * * @param Statement $statement The parsed query that has to be modified. @@ -475,10 +450,22 @@ class Query $clauses = array_flip(array_keys($statement::$CLAUSES)); /** + * Lexer used for lexing the clause. + * @var Lexer + */ + $lexer = new Lexer($clause); + + /** + * The type of this clause. + * @var string + */ + $clauseType = $lexer->list->getNextOfType(Token::TYPE_KEYWORD)->value; + + /** * The index of this clause. * @var int */ - $clauseIdx = $clauses[static::getClauseType($clause)]; + $clauseIdx = $clauses[$clauseType]; for ($i = $statement->first; $i <= $statement->last; ++$i) { $token = $list->tokens[$i]; @@ -493,16 +480,15 @@ class Query if ($brackets == 0) { // Checking if we changed sections. - if ($token->type === Token::TYPE_KEYWORD) { - if (isset($clauses[$token->value])) { - if ($clauses[$token->value] >= $currIdx) { - $currIdx = $clauses[$token->value]; - if (($skipFirst) && ($currIdx == $clauseIdx)) { - // This token is skipped (not added to the old - // clause) because it will be replaced. - continue; - } - } + if (($token->type === Token::TYPE_KEYWORD) + && (isset($clauses[$token->value])) + && ($clauses[$token->value] >= $currIdx) + ) { + $currIdx = $clauses[$token->value]; + if (($skipFirst) && ($currIdx == $clauseIdx)) { + // This token is skipped (not added to the old + // clause) because it will be replaced. + continue; } } } @@ -526,25 +512,30 @@ class Query * * @param Statement $statement The parsed query that has to be modified. * @param TokensList $list The list of tokens. - * @param string $clause The clause to be replaced. + * @param string $old The type of the clause that should be + * replaced. This can be an entire clause. + * @param string $new The new clause. If this parameter is omitted + * it is considered to be equal with `$old`. * @param bool $onlyType Whether only the type of the clause should * be replaced or the entire clause. * * @return string */ - public static function replaceClause($statement, $list, $clause, $onlyType = false) + public static function replaceClause($statement, $list, $old, $new = null, $onlyType = false) { // TODO: Update the tokens list and the statement. + if ($new === null) { + $new = $old; + } + if ($onlyType) { - return static::getClause($statement, $list, $clause, -1, false) . ' ' . - $clause . ' ' . - static::getCLause($statement, $list, $clause, 0) . ' ' . - static::getClause($statement, $list, $clause, 1, false); + return static::getClause($statement, $list, $old, -1, false) . ' ' . + $new . ' ' . static::getCLause($statement, $list, $old, 0) . ' ' . + static::getClause($statement, $list, $old, 1, false); } - return static::getClause($statement, $list, $clause, -1, false) . ' ' . - $clause . ' ' . - static::getClause($statement, $list, $clause, 1, false); + return static::getClause($statement, $list, $old, -1, false) . ' ' . + $new . ' ' . static::getClause($statement, $list, $old, 1, false); } } |