Browse Source

Added tests for all expression that are capable of accepting
values convertible to other expressions

Jose Lorenzo Rodriguez 10 years ago
parent
commit
bff49bd2b6

+ 11 - 2
src/Database/Expression/CaseExpression.php

@@ -116,17 +116,19 @@ class CaseExpression implements ExpressionInterface
     {
         $rawValues = array_values($values);
         $keyValues = array_keys($values);
+
         foreach ($conditions as $k => $c) {
             $numericKey = is_numeric($k);
 
             if ($numericKey && empty($c)) {
                 continue;
             }
+
             if (!$c instanceof ExpressionInterface) {
                 continue;
             }
-            array_push($this->_conditions, $c);
 
+            array_push($this->_conditions, $c);
             $value = isset($rawValues[$k]) ? $rawValues[$k] : 1;
 
             if ($value === 'literal') {
@@ -134,6 +136,7 @@ class CaseExpression implements ExpressionInterface
                 array_push($this->_values, $value);
                 continue;
             }
+
             if ($value === 'identifier') {
                 $value = new IdentifierExpression($keyValues[$k]);
                 array_push($this->_values, $value);
@@ -168,7 +171,13 @@ class CaseExpression implements ExpressionInterface
         if (is_array($value)) {
             end($value);
             $value = key($value);
-        } elseif ($value !== null && !$value instanceof ExpressionInterface) {
+        }
+
+        if ($value !== null && !$value instanceof ExpressionInterface) {
+            $value = $this->_castToExpression($value, $type);
+        }
+
+        if (!$value instanceof ExpressionInterface) {
             $value = ['value' => $value, 'type' => $type];
         }
 

+ 4 - 0
src/Database/Type/TypeExpressionCasterTrait.php

@@ -26,6 +26,10 @@ trait TypeExpressionCasterTrait
 
     protected function _castToExpression($value, $type)
     {
+        if (empty($type)) {
+            return $value;
+        }
+
         $baseType = str_replace('[]', '', $type);
         $converter = Type::build($baseType);
 

+ 100 - 0
tests/TestCase/Database/ExpressionTypeCastingTest.php

@@ -20,6 +20,8 @@ use Cake\Database\Expression\FunctionExpression;
 use Cake\Database\ValueBinder;
 use Cake\Database\Type;
 use Cake\Database\Expression\Comparison;
+use Cake\Database\Expression\BetweenExpression;
+use Cake\Database\Expression\CaseExpression;
 
 class TestType extends StringType implements ExpressionTypeInterface
 {
@@ -49,6 +51,12 @@ class ExpressionTypeCastingTest extends TestCase
         Type::map('test', new TestType);
     }
 
+    /**
+     * Tests that the Comparison expression can handle values convertible to
+     * expressions
+     *
+     * @return void
+     */
     public function testComparisonSimple()
     {
         $comparison = new Comparison('field', 'the thing', 'test', '=');
@@ -56,8 +64,20 @@ class ExpressionTypeCastingTest extends TestCase
         $sql = $comparison->sql($binder);
         $this->assertEquals('field = (CONCAT(:c0, :c1))', $sql);
         $this->assertEquals('the thing', $binder->bindings()[':c0']['value']);
+
+        $found = false;
+        $comparison->traverse(function ($exp) use (&$found) {
+            $found = $exp instanceof FunctionExpression;
+        });
+        $this->assertTrue($found, 'The expression is not included in the tree');
     }
 
+    /**
+     * Tests that the Comparison expression can handle values convertible to
+     * expressions
+     *
+     * @return void
+     */
     public function testComparisonMultiple()
     {
         $comparison = new Comparison('field', ['2', '3'], 'test[]', 'IN');
@@ -66,6 +86,86 @@ class ExpressionTypeCastingTest extends TestCase
         $this->assertEquals('field IN (CONCAT(:c0, :c1),CONCAT(:c2, :c3))', $sql);
         $this->assertEquals('2', $binder->bindings()[':c0']['value']);
         $this->assertEquals('3', $binder->bindings()[':c2']['value']);
+
+        $found = false;
+        $comparison->traverse(function ($exp) use (&$found) {
+            $found = $exp instanceof FunctionExpression;
+        });
+        $this->assertTrue($found, 'The expression is not included in the tree');
     }
 
+    /**
+     * Tests that the Between expression casts values to expresisons correctly
+     *
+     * @return void
+     */
+    public function testBetween()
+    {
+        $between = new BetweenExpression('field', 'from', 'to', 'test');
+        $binder = new ValueBinder;
+        $sql = $between->sql($binder);
+        $this->assertEquals('field BETWEEN CONCAT(:c0, :c1) AND CONCAT(:c2, :c3)', $sql);
+        $this->assertEquals('from', $binder->bindings()[':c0']['value']);
+        $this->assertEquals('to', $binder->bindings()[':c2']['value']);
+
+        $expressions = [];
+        $between->traverse(function ($exp) use (&$expressions) {
+            $expressions[] = $exp instanceof FunctionExpression ? 1 : 0;
+        });
+
+        $result = array_sum($expressions);
+        $this->assertEquals(2, $result, 'Missing expressions in the tree');
+    }
+
+    /**
+     * Tests that the Case expressions converts values to expressions correctly
+     *
+     * @return void
+     */
+    public function testCaseExpression()
+    {
+        $case = new CaseExpression(
+            [new Comparison('foo', '1', 'string', '=')],
+            ['value1', 'value2'],
+            ['test' , 'test']
+        );
+
+        $binder = new ValueBinder;
+        $sql = $case->sql($binder);
+        $this->assertEquals('CASE WHEN foo = :c0 THEN CONCAT(:c1, :c2) ELSE CONCAT(:c3, :c4) END', $sql);
+
+        $this->assertEquals('1', $binder->bindings()[':c0']['value']);
+        $this->assertEquals('value1', $binder->bindings()[':c1']['value']);
+        $this->assertEquals('value2', $binder->bindings()[':c3']['value']);
+
+        $expressions = [];
+        $case->traverse(function ($exp) use (&$expressions) {
+            $expressions[] = $exp instanceof FunctionExpression ? 1 : 0;
+        });
+
+        $result = array_sum($expressions);
+        $this->assertEquals(2, $result, 'Missing expressions in the tree');
+    }
+
+    /**
+     * Tests that values in FunctionExpressions are converted to expressions correctly
+     *
+     * @return void
+     */
+    public function testFunctionExpression()
+    {
+        $function = new FunctionExpression('DATE', ['2016-01'], ['test']);
+        $binder = new ValueBinder;
+        $sql = $function->sql($binder);
+        $this->assertEquals('DATE((CONCAT(:c0, :c1)))', $sql);
+        $this->assertEquals('2016-01', $binder->bindings()[':c0']['value']);
+
+        $expressions = [];
+        $function->traverse(function ($exp) use (&$expressions) {
+            $expressions[] = $exp instanceof FunctionExpression ? 1 : 0;
+        });
+
+        $result = array_sum($expressions);
+        $this->assertEquals(1, $result, 'Missing expressions in the tree');
+    }
 }