Browse Source

Add support for setting the `CASE` value via the factory method.

ndm2 4 years ago
parent
commit
11d6ea84db

+ 2 - 1
src/Database/Expression/CaseExpressionInterface.php

@@ -53,7 +53,8 @@ interface CaseExpressionInterface extends ExpressionInterface, TypedResultInterf
      * hold the comparisons.
      *
      * @param \Cake\Database\ExpressionInterface|object|scalar|null $value The case value.
-     * @param string|null $valueType The case value type.
+     * @param string|null $valueType The case value type. If no type is provided, the type will be tried to be inferred
+     *  from the value.
      * @return $this
      */
     public function value($value, ?string $valueType = null);

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

@@ -350,11 +350,29 @@ class QueryExpression implements ExpressionInterface, Countable
     /**
      * Returns a new case expression object.
      *
+     * When a value is set, the syntax generated is
+     * `CASE case_value WHEN when_value ... END`, where the
+     * `when_value`'s are compared against the `case_value`.
+     *
+     * When no value is set, the syntax generated is
+     * `CASE WHEN when_conditions ... END`, where the conditions
+     * hold the comparisons.
+     *
+     * @param \Cake\Database\ExpressionInterface|object|scalar|null $value The case value.
+     * @param string|null $valueType The case value type. If no type is provided, the type will be tried to be inferred
+     *  from the value.
      * @return \Cake\Database\Expression\CaseExpressionInterface
+     * @see \Cake\Database\Expression\CaseExpressionInterface::value()
      */
-    public function case(): CaseExpressionInterface
+    public function case($value = null, ?string $valueType = null): CaseExpressionInterface
     {
-        return new CaseStatementExpression($this->getTypeMap());
+        $expression = new CaseStatementExpression($this->getTypeMap());
+
+        if (func_num_args() > 0) {
+            $expression->value($value, $valueType);
+        }
+
+        return $expression;
     }
 
     /**

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

@@ -16,6 +16,7 @@ declare(strict_types=1);
  */
 namespace Cake\Test\TestCase\Database\Expression;
 
+use Cake\Database\Expression\IdentifierExpression;
 use Cake\Database\Expression\QueryExpression;
 use Cake\Database\ValueBinder;
 use Cake\TestSuite\TestCase;
@@ -211,4 +212,54 @@ class QueryExpressionTest extends TestCase
 
         (new QueryExpression())->addCase([]);
     }
+
+    public function testCaseWithoutValue(): void
+    {
+        $expression = (new QueryExpression())
+            ->case()
+            ->when(1)
+            ->then(2);
+
+        $this->assertEqualsSql(
+            'CASE WHEN :c0 THEN :c1 ELSE NULL END',
+            $expression->sql(new ValueBinder())
+        );
+    }
+
+    public function testCaseWithValue(): void
+    {
+        $expression = (new QueryExpression())
+            ->case(new IdentifierExpression('Table.column'))
+            ->when(1)
+            ->then('Yes');
+
+        $this->assertEqualsSql(
+            'CASE Table.column WHEN :c0 THEN :c1 ELSE NULL END',
+            $expression->sql(new ValueBinder())
+        );
+    }
+
+    public function testCaseWithValueAndType(): void
+    {
+        $expression = (new QueryExpression())
+            ->case('1', 'integer')
+            ->when(1)
+            ->then('Yes');
+
+        $valueBinder = new ValueBinder();
+
+        $this->assertEqualsSql(
+            'CASE :c0 WHEN :c1 THEN :c2 ELSE NULL END',
+            $expression->sql($valueBinder)
+        );
+
+        $this->assertSame(
+            [
+                'value' => '1',
+                'type' => 'integer',
+                'placeholder' => 'c0',
+            ],
+            $valueBinder->bindings()[':c0']
+        );
+    }
 }