Explorar o código

ZF-4099
- Fix for multiple order statements in Mssql limit with offset

git-svn-id: http://framework.zend.com/svn/framework/standard/trunk@17706 44c647ce-9c0f-0410-b52a-842ac1e357ba

ralph %!s(int64=16) %!d(string=hai) anos
pai
achega
66386cb3be
Modificáronse 2 ficheiros con 70 adicións e 27 borrados
  1. 22 6
      library/Zend/Db/Adapter/Pdo/Mssql.php
  2. 48 21
      tests/Zend/Db/Adapter/Pdo/MssqlTest.php

+ 22 - 6
library/Zend/Db/Adapter/Pdo/Mssql.php

@@ -315,22 +315,38 @@ class Zend_Db_Adapter_Pdo_Mssql extends Zend_Db_Adapter_Pdo_Abstract
         }
 
         $orderby = stristr($sql, 'ORDER BY');
+        
         if ($orderby !== false) {
-            $sort = (stripos($orderby, ' desc') !== false) ? 'desc' : 'asc';
-            $order = str_ireplace('ORDER BY', '', $orderby);
-            $order = trim(preg_replace('/\bASC\b|\bDESC\b/i', '', $order));
+            $orderParts = explode(',', substr($orderby, 8));
+            $pregReplaceCount = null;
+            $orderbyInverseParts = array();
+            foreach ($orderParts as $orderPart) {
+                $inv = preg_replace('/\s+desc$/i', ' ASC', $orderPart, 1, $pregReplaceCount);
+                if ($pregReplaceCount) {
+                    $orderbyInverseParts[] = $inv;
+                    continue;
+                }
+                $inv = preg_replace('/\s+asc$/i', ' DESC', $orderPart, 1, $pregReplaceCount);
+                if ($pregReplaceCount) {
+                    $orderbyInverseParts[] = $inv;
+                    continue;
+                } else {
+                    $orderbyInverseParts[] = $orderPart . ' DESC';
+                }
+            }
+            
+            $orderbyInverse = 'ORDER BY ' . implode(', ', $orderbyInverseParts);
         }
 
         $sql = preg_replace('/^SELECT\s/i', 'SELECT TOP ' . ($count+$offset) . ' ', $sql);
 
         $sql = 'SELECT * FROM (SELECT TOP ' . $count . ' * FROM (' . $sql . ') AS inner_tbl';
         if ($orderby !== false) {
-            $sql .= ' ORDER BY ' . $order . ' ';
-            $sql .= (stripos($sort, 'asc') !== false) ? 'DESC' : 'ASC';
+            $sql .= ' ' . $orderbyInverse . ' ';
         }
         $sql .= ') AS outer_tbl';
         if ($orderby !== false) {
-            $sql .= ' ORDER BY ' . $order . ' ' . $sort;
+            $sql .= ' ' . $orderby;
         }
 
         return $sql;

+ 48 - 21
tests/Zend/Db/Adapter/Pdo/MssqlTest.php

@@ -297,28 +297,55 @@ class Zend_Db_Adapter_Pdo_MssqlTest extends Zend_Db_Adapter_Pdo_TestCommon
     }
 
     /**
-      * Test the Adapter's insert() method.
-      * This requires providing an associative array of column=>value pairs.
-      */
-     public function testAdapterInsert()
-     {
-         $row = array (
-             'bug_description' => 'New bug',
-             'bug_status'      => 'NEW',
-             'created_on'      => '2007-04-02',
-             'updated_on'      => '2007-04-02',
-             'reported_by'     => 'micky',
-             'assigned_to'     => 'goofy',
-             'verified_by'     => 'dduck'
-         );
-         $rowsAffected = $this->_db->insert('zfbugs', $row);
-         $this->assertEquals(1, $rowsAffected);
-         $lastInsertId = $this->_db->lastInsertId();
-         $this->assertType('integer', $lastInsertId);
-         $this->assertEquals('5', (string) $lastInsertId,
-             'Expected new id to be 5');
-     }
+     * Test the Adapter's insert() method.
+     * This requires providing an associative array of column=>value pairs.
+     */
+    public function testAdapterInsert()
+    {
+        $row = array (
+            'bug_description' => 'New bug',
+            'bug_status'      => 'NEW',
+            'created_on'      => '2007-04-02',
+            'updated_on'      => '2007-04-02',
+            'reported_by'     => 'micky',
+            'assigned_to'     => 'goofy',
+            'verified_by'     => 'dduck'
+        );
+        $rowsAffected = $this->_db->insert('zfbugs', $row);
+        $this->assertEquals(1, $rowsAffected);
+        $lastInsertId = $this->_db->lastInsertId();
+        $this->assertType('integer', $lastInsertId);
+        $this->assertEquals('5', (string) $lastInsertId,
+            'Expected new id to be 5');
+    }
 
+    /**
+     * @group ZF-4099
+     */
+    public function testAdapterLimitWorksWithOrderByClause()
+    {
+    	// more values
+        $this->_db->insert('zfproducts', array('product_name' => 'Unix'));
+        $this->_db->insert('zfproducts', array('product_name' => 'Windows'));
+        $this->_db->insert('zfproducts', array('product_name' => 'AIX'));
+        $this->_db->insert('zfproducts', array('product_name' => 'I5'));
+        $this->_db->insert('zfproducts', array('product_name' => 'Linux'));
+        
+        $select = $this->_db->select();
+        $select->from('zfproducts')
+           ->order(array('product_name ASC', 'product_id DESC'))
+           ->limit(4, 4);
+        $products = $this->_db->fetchAll($select);
+        $expectedProducts = array(
+            0 => array('product_id' => '3', 'product_name' => 'OS X'),
+            1 => array('product_id' => '4', 'product_name' => 'Unix'),
+            2 => array('product_id' => '5', 'product_name' => 'Windows'),
+            3 => array ('product_id' => '1', 'product_name' => 'Windows')
+            );
+        $this->assertEquals($expectedProducts, $products);
+    }
+    
+    
     public function getDriver()
     {
         return 'Pdo_Mssql';