Browse Source

Make union not supporting order by a flag.

There are 2 dialects that do not support this behavior and I felt bad
creating a trait or duplicating code for this.
Mark Story 11 years ago
parent
commit
855503af03

+ 19 - 3
src/Database/QueryCompiler.php

@@ -76,6 +76,15 @@ class QueryCompiler
     protected $_insertParts = ['insert', 'values', 'epilog'];
 
     /**
+     * Indicate whether or not this query dialect supports ordered unions.
+     *
+     * Overidden in subclasses.
+     *
+     * @var bool
+     */
+    protected $_orderedUnion = true;
+
+    /**
      * Returns the SQL representation of the provided query after generating
      * the placeholders for the bound values using the provided generator
      *
@@ -135,7 +144,7 @@ class QueryCompiler
     {
         $driver = $query->connection()->driver();
         $select = 'SELECT %s%s%s';
-        if ($query->clause('union')) {
+        if ($this->_orderedUnion && $query->clause('union')) {
             $select = '(SELECT %s%s%s';
         }
         $distinct = $query->clause('distinct');
@@ -257,9 +266,16 @@ class QueryCompiler
             $p['query'] = $p['query']->sql($generator);
             $p['query'] = $p['query'][0] === '(' ? trim($p['query'], '()') : $p['query'];
             $prefix = $p['all'] ? 'ALL ' : '';
-            return sprintf('%s(%s)', $prefix, $p['query']);
+            if ($this->_orderedUnion) {
+                return "{$prefix}({$p['query']})";
+            }
+            return $prefix . $p['query'];
         }, $parts);
-        return sprintf(")\nUNION %s", implode("\nUNION ", $parts));
+
+        if ($this->_orderedUnion) {
+            return sprintf(")\nUNION %s", implode("\nUNION ", $parts));
+        }
+        return sprintf("\nUNION %s", implode("\nUNION ", $parts));
     }
 
     /**

+ 3 - 37
src/Database/SqliteCompiler.php

@@ -25,43 +25,9 @@ use Cake\Database\QueryCompiler;
 class SqliteCompiler extends QueryCompiler
 {
     /**
-     * Helper function used to build the string representation of a SELECT clause,
-     * it constructs the field list taking care of aliasing and
-     * converting expression objects to string. This function also constructs the
-     * DISTINCT clause for the query.
+     * SQLite does not support ORDER BY in UNION queries.
      *
-     * @param array $parts list of fields to be transformed to string
-     * @param \Cake\Database\Query $query The query that is being compiled
-     * @param \Cake\Database\ValueBinder $generator the placeholder generator to be used in expressions
-     * @return string
+     * @var bool
      */
-    protected function _buildSelectPart($parts, $query, $generator)
-    {
-        $clause = parent::_buildSelectPart($parts, $query, $generator);
-        if ($clause[0] === '(') {
-            return substr($clause, 1);
-        }
-        return $clause;
-    }
-
-    /**
-     * Builds the SQL string for all the UNION clauses in this query, when dealing
-     * with query objects it will also transform them using their configured SQL
-     * dialect.
-     *
-     * @param array $parts list of queries to be operated with UNION
-     * @param \Cake\Database\Query $query The query that is being compiled
-     * @param \Cake\Database\ValueBinder $generator the placeholder generator to be used in expressions
-     * @return string
-     */
-    protected function _buildUnionPart($parts, $query, $generator)
-    {
-        $parts = array_map(function ($p) use ($generator) {
-            $p['query'] = $p['query']->sql($generator);
-            $p['query'] = $p['query'][0] === '(' ? trim($p['query'], '()') : $p['query'];
-            $prefix = $p['all'] ? 'ALL' : '';
-            return sprintf('%s %s', $prefix, $p['query']);
-        }, $parts);
-        return sprintf("\nUNION %s", implode("\nUNION ", $parts));
-    }
+    protected $_orderedUnion = false;
 }

+ 6 - 0
src/Database/SqlserverCompiler.php

@@ -24,6 +24,12 @@ use Cake\Database\QueryCompiler;
  */
 class SqlserverCompiler extends QueryCompiler
 {
+    /**
+     * SQLserver does not support ORDER BY in UNION queries.
+     *
+     * @var bool
+     */
+    protected $_orderedUnion = false;
 
     /**
      * {@inheritDoc}

+ 3 - 2
tests/TestCase/Database/QueryTest.php

@@ -1952,8 +1952,9 @@ class QueryTest extends TestCase
     public function testUnionOrderBy()
     {
         $this->skipIf(
-            $this->connection->driver() instanceof \Cake\Database\Driver\Sqlite,
-            'SQLite does not support ORDER BY in UNIONed queries.'
+            ($this->connection->driver() instanceof \Cake\Database\Driver\Sqlite ||
+            $this->connection->driver() instanceof \Cake\Database\Driver\Sqlserver),
+            'Driver does not support ORDER BY in UNIONed queries.'
         );
         $union = (new Query($this->connection))
             ->select(['id', 'title'])