summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDan Ungureanu <udan1107@gmail.com>2015-11-02 23:10:28 +0200
committerDan Ungureanu <udan1107@gmail.com>2015-11-02 23:40:44 +0200
commit991fe545514e51bacaf58ad87358f984bce2c6f8 (patch)
tree61ae3ab1313f56e8d25c29ae66e27506a3abefbd /src
parent03eb61c873122d46f605d6de7a4aecc3de09ff9b (diff)
downloadsql-parser-991fe545514e51bacaf58ad87358f984bce2c6f8.zip
sql-parser-991fe545514e51bacaf58ad87358f984bce2c6f8.tar.gz
sql-parser-991fe545514e51bacaf58ad87358f984bce2c6f8.tar.bz2
Fix the order of clauses in SELECT statements involing UNIONs.
Diffstat (limited to 'src')
-rw-r--r--src/Parser.php15
-rw-r--r--src/Statement.php26
-rw-r--r--src/Statements/SelectStatement.php21
-rw-r--r--src/Utils/Query.php10
4 files changed, 61 insertions, 11 deletions
diff --git a/src/Parser.php b/src/Parser.php
index 1277601..4646ed2 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -151,7 +151,7 @@ class Parser
'FROM' => array(
'class' => 'SqlParser\\Components\\ExpressionArray',
'field' => 'from',
- 'options' => array('skipColumn' => true),
+ 'options' => array('skipColumn' => true, 'noBrackets' => true),
),
'GROUP BY' => array(
'class' => 'SqlParser\\Components\\OrderKeyword',
@@ -298,6 +298,13 @@ class Parser
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.
@@ -381,6 +388,12 @@ class Parser
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) {
diff --git a/src/Statement.php b/src/Statement.php
index b15dc3d..a9d4dc8 100644
--- a/src/Statement.php
+++ b/src/Statement.php
@@ -122,7 +122,14 @@ abstract class Statement
*/
$built = array();
- foreach (static::$CLAUSES as $clause) {
+ /**
+ * Statement's clauses.
+ *
+ * @var array
+ */
+ $clauses = $this->getClauses();
+
+ foreach ($clauses as $clause) {
/**
* The name of the clause.
*
@@ -224,6 +231,13 @@ abstract class Statement
break;
}
+ // Checking if this closing bracket is the pair for a bracket
+ // outside the statement.
+ if (($token->value === ')') && ($parser->brackets > 0)) {
+ --$parser->brackets;
+ continue;
+ }
+
// Only keywords are relevant here. Other parts of the query are
// processed in the functions below.
if ($token->type !== Token::TYPE_KEYWORD) {
@@ -364,6 +378,16 @@ abstract class Statement
}
/**
+ * Gets the clauses of this statement.
+ *
+ * @return array
+ */
+ public function getClauses()
+ {
+ return static::$CLAUSES;
+ }
+
+ /**
* Builds the string representation of this statement.
*
* @see static::build
diff --git a/src/Statements/SelectStatement.php b/src/Statements/SelectStatement.php
index add3b8b..4bcbf2d 100644
--- a/src/Statements/SelectStatement.php
+++ b/src/Statements/SelectStatement.php
@@ -195,4 +195,25 @@ class SelectStatement extends Statement
* @var SelectStatement[]
*/
public $union = array();
+
+ /**
+ * Gets the clauses of this statement.
+ *
+ * @return array
+ */
+ public function getClauses()
+ {
+ // This is a cheap fix for `SELECT` statements that contain `UNION`.
+ // The `ORDER BY` and `LIMIT` clauses should be at the end of the
+ // statement.
+ if (!empty($this->union)) {
+ $clauses = static::$CLAUSES;
+ unset($clauses['ORDER BY']);
+ unset($clauses['LIMIT']);
+ $clauses['ORDER BY'] = array('ORDER BY', 3);
+ $clauses['LIMIT'] = array('LIMIT', 3);
+ return $clauses;
+ }
+ return static::$CLAUSES;
+ }
}
diff --git a/src/Utils/Query.php b/src/Utils/Query.php
index ab2849b..d76e6bb 100644
--- a/src/Utils/Query.php
+++ b/src/Utils/Query.php
@@ -546,15 +546,7 @@ class Query
*
* @var array $clauses
*/
- $clauses = array_flip(array_keys($statement::$CLAUSES));
-
- // This is a cheap fix for `SELECT` statements that contain `UNION`.
- // Replacing the `ORDER BY` or `LIMIT` clauses should replace the last
- // clause.
- if (($statement instanceof SelectStatement) && (!empty($statement->union))) {
- $clauses['ORDER BY'] = count($clauses) + 1;
- $clauses['LIMIT'] = count($clauses) + 2;
- }
+ $clauses = array_flip(array_keys($statement->getClauses()));
/**
* Lexer used for lexing the clause.