Explorar o código

Merge pull request #492 from foxel/columnQuotes

Fix regexp to detect functions in column definition
Frank Brückner %!s(int64=10) %!d(string=hai) anos
pai
achega
b760b92fbe
Modificáronse 2 ficheiros con 86 adicións e 3 borrados
  1. 5 3
      library/Zend/Db/Select.php
  2. 81 0
      tests/Zend/Db/Select/StaticTest.php

+ 5 - 3
library/Zend/Db/Select.php

@@ -81,6 +81,8 @@ class Zend_Db_Select
     const SQL_ASC        = 'ASC';
     const SQL_DESC       = 'DESC';
 
+    const REGEX_COLUMN_EXPR = '/^([\w]*\(([^\(\)]|(?1))*\))$/';
+
     /**
      * Bind variables for query
      *
@@ -509,7 +511,7 @@ class Zend_Db_Select
         }
 
         foreach ($spec as $val) {
-            if (preg_match('/^([\w]*\(([^\)]|(?1))*\))$/', (string) $val)) {
+            if (preg_match(self::REGEX_COLUMN_EXPR, (string) $val)) {
                 $val = new Zend_Db_Expr($val);
             }
             $this->_parts[self::GROUP][] = $val;
@@ -601,7 +603,7 @@ class Zend_Db_Select
                     $val = trim($matches[1]);
                     $direction = $matches[2];
                 }
-                if (preg_match('/^([\w]*\(([^\)]|(?1))*\))$/', (string) $val)) {
+                if (preg_match(self::REGEX_COLUMN_EXPR, (string) $val)) {
                     $val = new Zend_Db_Expr($val);
                 }
                 $this->_parts[self::ORDER][] = array($val, $direction);
@@ -943,7 +945,7 @@ class Zend_Db_Select
                     $alias = $m[2];
                 }
                 // Check for columns that look like functions and convert to Zend_Db_Expr
-                if (preg_match('/^([\w]*\(([^\)]|(?1))*\))$/', (string) $col)) {
+                if (preg_match(self::REGEX_COLUMN_EXPR, (string) $col)) {
                     $col = new Zend_Db_Expr($col);
                 } elseif (preg_match('/(.+)\.(.+)/', $col, $m)) {
                     $currentCorrelationName = $m[1];

+ 81 - 0
tests/Zend/Db/Select/StaticTest.php

@@ -874,6 +874,46 @@ class Zend_Db_Select_StaticTest extends Zend_Db_Select_TestCommon
         $this->assertEquals("SELECT \"table1\".*, IF(table2.id IS NOT NULL, IF(table2.id2 IS NOT NULL, 1, 2), 0) AS \"bar\" FROM \"table1\"\n INNER JOIN \"table2\" ON table1.id = table2.id", $select->assemble());
     }
 
+    public function testDeepNestedIfInColumn()
+    {
+        $select = $this->_db->select();
+        $select->from('table1', '*');
+        $select->join(array('table2'),
+            'table1.id = table2.id',
+            array('bar' => 'IF(table2.id IS NOT NULL, IF(table2.id2 IS NOT NULL, SUM(1), 2), 0)'));
+        $this->assertEquals("SELECT \"table1\".*, IF(table2.id IS NOT NULL, IF(table2.id2 IS NOT NULL, SUM(1), 2), 0) AS \"bar\" FROM \"table1\"\n INNER JOIN \"table2\" ON table1.id = table2.id", $select->assemble());
+    }
+
+    public function testNestedUnbalancedParenthesesInColumn()
+    {
+        $select = $this->_db->select();
+        $select->from('table1', '*');
+        $select->join(array('table2'),
+            'table1.id = table2.id',
+            array('bar' => 'IF(SUM()'));
+        $this->assertEquals("SELECT \"table1\".*, \"table2\".\"IF(SUM()\" AS \"bar\" FROM \"table1\"\n INNER JOIN \"table2\" ON table1.id = table2.id", $select->assemble());
+    }
+
+    public function testNestedIfInGroup()
+    {
+        $select = $this->_db->select();
+        $select->from(array ('p' => 'product'))
+            ->group('IF(p.id IS NOT NULL, IF(p.id2 IS NOT NULL, SUM(1), 2), 0)');
+
+        $expected = 'SELECT "p".* FROM "product" AS "p" GROUP BY IF(p.id IS NOT NULL, IF(p.id2 IS NOT NULL, SUM(1), 2), 0)';
+        $this->assertEquals($expected, $select->assemble());
+    }
+
+    public function testUnbalancedParenthesesInGroup()
+    {
+        $select = $this->_db->select();
+        $select->from(array ('p' => 'product'))
+            ->group('IF(SUM() ASC');
+
+        $expected = 'SELECT "p".* FROM "product" AS "p" GROUP BY "IF(SUM() ASC"';
+        $this->assertEquals($expected, $select->assemble());
+    }
+
     /**
      * @group ZF-378
      */
@@ -930,4 +970,45 @@ class Zend_Db_Select_StaticTest extends Zend_Db_Select_TestCommon
         $this->assertEquals($expected, $select->assemble(),
             'Order direction of field failed');
     }
+
+    public function testOrderOfDeepConditionalField()
+    {
+        $select = $this->_db->select();
+        $select->from(array ('p' => 'product'))
+            ->order('IF(p.id IS NOT NULL, IF(p.id2 IS NOT NULL, SUM(1), 2), 0)');
+
+        $expected = 'SELECT "p".* FROM "product" AS "p" ORDER BY IF(p.id IS NOT NULL, IF(p.id2 IS NOT NULL, SUM(1), 2), 0) ASC';
+        $this->assertEquals($expected, $select->assemble());
+    }
+
+    public function testOrderOfDeepUnbalancedConditionalField()
+    {
+        $select = $this->_db->select();
+        $select->from(array ('p' => 'product'))
+            ->order('IF(SUM()');
+
+        $expected = 'SELECT "p".* FROM "product" AS "p" ORDER BY "IF(SUM()" ASC';
+        $this->assertEquals($expected, $select->assemble());
+    }
+
+    public function testOrderOfDeepConditionalFieldWithDirection()
+    {
+        $select = $this->_db->select();
+        $select->from(array ('p' => 'product'))
+            ->order('IF(p.id IS NOT NULL, IF(p.id2 IS NOT NULL, SUM(1), 2), 0) ASC');
+
+        $expected = 'SELECT "p".* FROM "product" AS "p" ORDER BY IF(p.id IS NOT NULL, IF(p.id2 IS NOT NULL, SUM(1), 2), 0) ASC';
+        $this->assertEquals($expected, $select->assemble());
+    }
+
+    public function testOrderOfDeepUnbalancedConditionalFieldWithDirection()
+    {
+        $select = $this->_db->select();
+        $select->from(array ('p' => 'product'))
+            ->order('IF(SUM() ASC');
+
+        $expected = 'SELECT "p".* FROM "product" AS "p" ORDER BY "IF(SUM()" ASC';
+        $this->assertEquals($expected, $select->assemble());
+    }
+
 }