Browse Source

Fix identifier quoting in conditions & order

Both generated UnaryExpressions and OrderByExpression instances were
not being quoted correctly by the identifier quoter. The `foo IS NULL` and
`foo IS NOT NULL` expressions were missing identifier markers, while
order by statements were also missing identifier quoting. Correctly
quoting these query elements fixes errors in postgres related to
TreeBehavior.

Refs #6794
Mark Story 10 years ago
parent
commit
c369cfcd4e

+ 1 - 0
src/Database/Expression/OrderByExpression.php

@@ -15,6 +15,7 @@
 namespace Cake\Database\Expression;
 
 use Cake\Database\ExpressionInterface;
+use Cake\Database\Expression\IdentifierExpression;
 use Cake\Database\ValueBinder;
 
 /**

+ 10 - 2
src/Database/Expression/QueryExpression.php

@@ -587,11 +587,19 @@ class QueryExpression implements ExpressionInterface, Countable
         }
 
         if ($operator === 'is' && $value === null) {
-            return new UnaryExpression('IS NULL', $expression, UnaryExpression::POSTFIX);
+            return new UnaryExpression(
+                'IS NULL',
+                new IdentifierExpression($expression),
+                UnaryExpression::POSTFIX
+            );
         }
 
         if ($operator === 'is not' && $value === null) {
-            return new UnaryExpression('IS NOT NULL', $expression, UnaryExpression::POSTFIX);
+            return new UnaryExpression(
+                'IS NOT NULL',
+                new IdentifierExpression($expression),
+                UnaryExpression::POSTFIX
+            );
         }
 
         if ($operator === 'is' && $value !== null) {

+ 4 - 0
src/Database/IdentifierQuoter.php

@@ -214,6 +214,10 @@ class IdentifierQuoter
         $expression->iterateParts(function ($part, &$field) {
             if (is_string($field)) {
                 $field = $this->_driver->quoteIdentifier($field);
+                return $part;
+            }
+            if (is_string($part)) {
+                return $this->_driver->quoteIdentifier($part);
             }
             return $part;
         });

+ 0 - 1
tests/TestCase/Database/Expression/QueryExpressionTest.php

@@ -24,7 +24,6 @@ use Cake\TestSuite\TestCase;
  */
 class QueryExpressionTest extends TestCase
 {
-
     /**
      * Test and() and or() calls work transparently
      *

+ 23 - 0
tests/TestCase/Database/QueryTest.php

@@ -521,6 +521,29 @@ class QueryTest extends TestCase
     }
 
     /**
+     * Test that unary expressions in selects are built correctly.
+     *
+     * @return void
+     */
+    public function testSelectWhereUnary()
+    {
+        $query = new Query($this->connection);
+        $result = $query
+            ->select(['id'])
+            ->from('articles')
+            ->where([
+                'title is not' => null,
+                'user_id is' => null
+            ])
+            ->sql();
+        $this->assertQuotedQuery(
+            'SELECT <id> FROM <articles> WHERE \(\(<title>\) IS NOT NULL AND \(<user_id>\) IS NULL\)',
+            $result,
+            true
+        );
+    }
+
+    /**
      * Tests selecting with conditions and specifying types for those
      *
      * @return void