2
0
Просмотр исходного кода

ZF-5956: Zend_Paginator factory chokes when Zend_Db_Select has UNION

git-svn-id: http://framework.zend.com/svn/framework/standard/trunk@16144 44c647ce-9c0f-0410-b52a-842ac1e357ba
norm2782 16 лет назад
Родитель
Сommit
55a1dda5fb

+ 46 - 40
library/Zend/Paginator/Adapter/DbSelect.php

@@ -153,58 +153,64 @@ class Zend_Paginator_Adapter_DbSelect implements Zend_Paginator_Adapter_Interfac
             $rowCount = clone $this->_select;
             $db = $rowCount->getAdapter();
 
-            /**
-             * The DISTINCT and GROUP BY queries only work when selecting one column.
-             * The question is whether any RDBMS supports DISTINCT for multiple columns, without workarounds.
-             */
-            if (true === $rowCount->getPart(Zend_Db_Select::DISTINCT)) {
-                $columnParts = $rowCount->getPart(Zend_Db_Select::COLUMNS);
+            $countColumn = $db->quoteIdentifier($db->foldCase(self::ROW_COUNT_COLUMN));
 
-                $columns = array();
+            if ($rowCount->getPart(Zend_Db_Select::UNION) != array()) {
+                $expression = new Zend_Db_Expr('COUNT(*) AS ' . $countColumn);
 
-                foreach ($columnParts as $part) {
-                    if ($part[1] == Zend_Db_Select::SQL_WILDCARD || $part[1] instanceof Zend_Db_Expr) {
-                        $columns[] = $part[1];
-                    } else {
-                        $column = $db->quoteIdentifier($part[1], true);
+                $rowCount = $db->select()->from($rowCount, $expression);
+            } else {
+                /**
+                 * The DISTINCT and GROUP BY queries only work when selecting one column.
+                 * The question is whether any RDBMS supports DISTINCT for multiple columns, without workarounds.
+                 */
+                if (true === $rowCount->getPart(Zend_Db_Select::DISTINCT)) {
+                    $columnParts = $rowCount->getPart(Zend_Db_Select::COLUMNS);
 
-                        if (!empty($part[0])) {
-                            $column = $db->quoteIdentifier($part[0], true) . '.' . $column;
-                        }
+                    $columns = array();
+
+                    foreach ($columnParts as $part) {
+                        if ($part[1] == Zend_Db_Select::SQL_WILDCARD || $part[1] instanceof Zend_Db_Expr) {
+                            $columns[] = $part[1];
+                        } else {
+                            $column = $db->quoteIdentifier($part[1], true);
 
-                        $columns[] = $column;
+                            if (!empty($part[0])) {
+                                $column = $db->quoteIdentifier($part[0], true) . '.' . $column;
+                            }
+
+                            $columns[] = $column;
+                        }
                     }
-                }
 
-                if (count($columns) == 1 && $columns[0] == Zend_Db_Select::SQL_WILDCARD) {
-                    $groupPart = null;
+                    if (count($columns) == 1 && $columns[0] == Zend_Db_Select::SQL_WILDCARD) {
+                        $groupPart = null;
+                    } else {
+                        $groupPart = implode(',', $columns);
+                    }
                 } else {
-                    $groupPart = implode(',', $columns);
-                }
-            } else {
-                $groupParts = $rowCount->getPart(Zend_Db_Select::GROUP);
+                    $groupParts = $rowCount->getPart(Zend_Db_Select::GROUP);
 
-                foreach ($groupParts as &$part) {
-                    if (!($part == Zend_Db_Select::SQL_WILDCARD || $part instanceof Zend_Db_Expr)) {
-                        $part = $db->quoteIdentifier($part, true);
+                    foreach ($groupParts as &$part) {
+                        if (!($part == Zend_Db_Select::SQL_WILDCARD || $part instanceof Zend_Db_Expr)) {
+                            $part = $db->quoteIdentifier($part, true);
+                        }
                     }
+
+                    $groupPart = implode(',', $groupParts);
                 }
 
-                $groupPart = implode(',', $groupParts);
-            }
+                $countPart  = empty($groupPart) ? 'COUNT(*)' : 'COUNT(DISTINCT ' . $groupPart . ')';
+                $expression = new Zend_Db_Expr($countPart . ' AS ' . $countColumn);
 
-            $countPart  = empty($groupPart) ? 'COUNT(*)' : 'COUNT(DISTINCT ' . $groupPart . ')';
-            $expression = new Zend_Db_Expr(
-                $countPart . ' AS ' . $db->quoteIdentifier($db->foldCase(self::ROW_COUNT_COLUMN))
-            );
-
-            $rowCount->__toString(); // Workaround for ZF-3719 and related
-            $rowCount->reset(Zend_Db_Select::COLUMNS)
-                     ->reset(Zend_Db_Select::ORDER)
-                     ->reset(Zend_Db_Select::LIMIT_OFFSET)
-                     ->reset(Zend_Db_Select::GROUP)
-                     ->reset(Zend_Db_Select::DISTINCT)
-                     ->columns($expression);
+                $rowCount->__toString(); // Workaround for ZF-3719 and related
+                $rowCount->reset(Zend_Db_Select::COLUMNS)
+                         ->reset(Zend_Db_Select::ORDER)
+                         ->reset(Zend_Db_Select::LIMIT_OFFSET)
+                         ->reset(Zend_Db_Select::GROUP)
+                         ->reset(Zend_Db_Select::DISTINCT)
+                         ->columns($expression);
+            }
 
             $this->setRowCount($rowCount);
         }

+ 15 - 0
tests/Zend/Paginator/Adapter/DbSelectTest.php

@@ -340,4 +340,19 @@ class Zend_Paginator_Adapter_DbSelectTest extends PHPUnit_Framework_TestCase
             $this->fail($e->getMessage());
         }
     }
+
+    public function testUnionSelect()
+    {
+        $union = $this->_db->select()->union(array(
+            $this->_db->select()->from('test')->where('number <= 250'),
+            $this->_db->select()->from('test')->where('number > 250')
+        ));
+
+        //$this->_db->select()->from($union, 'count(*)')
+        $adapter = new Zend_Paginator_Adapter_DbSelect($union);
+        $expected = 500;
+        $actual = $adapter->count();
+
+        $this->assertEquals($expected, $actual);
+    }
 }