Skip to content

Commit

Permalink
improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
tpetry committed Nov 30, 2023
1 parent 46b82b2 commit b642c12
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 57 deletions.
12 changes: 8 additions & 4 deletions src/Language/CaseBlock.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,20 @@ class CaseBlock extends ManyArgumentsExpression implements ConditionExpression
/**
* @param non-empty-array<int, CaseCondition> $when
*/
public function __construct(readonly array $when, private readonly string|Expression $else)
{
public function __construct(
array $when,
private readonly string|Expression|null $else = null,
) {
parent::__construct($when);
}

public function getValue(Grammar $grammar)
{
$conditions = implode(' ', $this->getExpressions($grammar));
$else = $this->stringize($grammar, $this->else);

return "(case {$conditions} else {$else} end)";
return match ($this->else) {
null => "(case {$conditions} end)",
default => "(case {$conditions} else {$this->stringize($grammar, $this->else)} end)",
};
}
}
8 changes: 5 additions & 3 deletions src/Language/CaseCondition.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Tpetry\QueryExpressions\Language;

use Illuminate\Contracts\Database\Query\ConditionExpression;
use Illuminate\Contracts\Database\Query\Expression;
use Illuminate\Database\Grammar;
use Tpetry\QueryExpressions\Concerns\StringizeExpression;
Expand All @@ -12,9 +13,10 @@ class CaseCondition implements Expression
{
use StringizeExpression;

public function __construct(private readonly string|Expression $result, private readonly string|Expression $condition)
{

public function __construct(
private readonly string|Expression $result,
private readonly ConditionExpression $condition,
) {
}

public function getValue(Grammar $grammar)
Expand Down
12 changes: 12 additions & 0 deletions tests/ConditionExpression.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace Tpetry\QueryExpressions\Tests;

use Illuminate\Contracts\Database\Query\ConditionExpression as ConditionExpressionContract;
use Illuminate\Database\Query\Expression;

class ConditionExpression extends Expression implements ConditionExpressionContract
{
}
92 changes: 42 additions & 50 deletions tests/Language/CaseTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,66 +2,58 @@

declare(strict_types=1);

use Illuminate\Database\Query\Expression;
use Tpetry\QueryExpressions\Language\CaseBlock;
use Tpetry\QueryExpressions\Language\CaseCondition;
use Tpetry\QueryExpressions\Operator\Comparison\Equal;
use Tpetry\QueryExpressions\Value\Number;
use Tpetry\QueryExpressions\Tests\ConditionExpression;

it('uses a caseBlock with one condition blocks')
it('can create create a case-expression with a single branch')
->expect(
new CaseBlock(when: [
new CaseCondition(result: new Number(5), condition: new Equal(new Number(1), new Number(2))),
],
else: new Number(2)
)
new CaseBlock([
new CaseCondition(new Expression(2), new ConditionExpression('1 = 1')),
])
)
->toBeExecutable()
->toBeMysql('(case when (1 = 2) then 5 else 2 end)')
->toBePgsql('(case when (1 = 2) then 5 else 2 end)')
->toBeSqlite('(case when (1 = 2) then 5 else 2 end)')
->toBeSqlsrv('(case when (1 = 2) then 5 else 2 end)');
->toBeMysql('(case when 1 = 1 then 2 end)')
->toBePgsql('(case when 1 = 1 then 2 end)')
->toBeSqlite('(case when 1 = 1 then 2 end)')
->toBeSqlsrv('(case when 1 = 1 then 2 end)');

it('uses a caseBlock with multiple condition blocks')
->expect(
new CaseBlock(when: [
new CaseCondition(result: new Number(5), condition: new Equal(new Number(1), new Number(2))),
new CaseCondition(result: new Number(6), condition: new Equal(new Number(2), new Number(2))),
],
else: new Number(2)
)
)
->toBeExecutable()
->toBeMysql('(case when (1 = 2) then 5 when (2 = 2) then 6 else 2 end)')
->toBePgsql('(case when (1 = 2) then 5 when (2 = 2) then 6 else 2 end)')
->toBeSqlite('(case when (1 = 2) then 5 when (2 = 2) then 6 else 2 end)')
->toBeSqlsrv('(case when (1 = 2) then 5 when (2 = 2) then 6 else 2 end)');
it('can create create a case-expression with multiple branches')
->expect(new CaseBlock([
new CaseCondition(new Expression(2), new ConditionExpression('1 = 1')),
new CaseCondition('val', new ConditionExpression('2 = 2')),
]))
->toBeExecutable(['val int'])
->toBeMysql('(case when 1 = 1 then 2 when 2 = 2 then `val` end)')
->toBePgsql('(case when 1 = 1 then 2 when 2 = 2 then "val" end)')
->toBeSqlite('(case when 1 = 1 then 2 when 2 = 2 then "val" end)')
->toBeSqlsrv('(case when 1 = 1 then 2 when 2 = 2 then [val] end)');

it('uses a caseBlock with multiple condition and value')
->expect(
new CaseBlock(when: [
new CaseCondition(result: new Number(5), condition: new Equal(new Number(1), new Number(2))),
new CaseCondition(result: new Number(6), condition: new Equal(new Number(2), new Number(2))),
it('can create create a case-expression with multiple branches and expression default')
->expect(new CaseBlock(
[
new CaseCondition(new Expression(2), new ConditionExpression('1 = 1')),
new CaseCondition('val', new ConditionExpression('2 = 2')),
],
else: 'val'
)
)
new Expression('4'),
))
->toBeExecutable(['val int'])
->toBeMysql('(case when (1 = 2) then 5 when (2 = 2) then 6 else `val` end)')
->toBePgsql('(case when (1 = 2) then 5 when (2 = 2) then 6 else "val" end)')
->toBeSqlite('(case when (1 = 2) then 5 when (2 = 2) then 6 else "val" end)')
->toBeSqlsrv('(case when (1 = 2) then 5 when (2 = 2) then 6 else [val] end)');
->toBeMysql('(case when 1 = 1 then 2 when 2 = 2 then `val` else 4 end)')
->toBePgsql('(case when 1 = 1 then 2 when 2 = 2 then "val" else 4 end)')
->toBeSqlite('(case when 1 = 1 then 2 when 2 = 2 then "val" else 4 end)')
->toBeSqlsrv('(case when 1 = 1 then 2 when 2 = 2 then [val] else 4 end)');

it('uses a caseBlock with multiple condition and value aliased')
->expect(
new \Tpetry\QueryExpressions\Language\Alias(new CaseBlock(when: [
new CaseCondition(result: new Number(5), condition: new Equal(new Number(1), new Number(2))),
new CaseCondition(result: new Number(6), condition: new Equal(new Number(2), new Number(2))),
it('can create create a case-expression with multiple branches and column default')
->expect(new CaseBlock(
[
new CaseCondition(new Expression(2), new ConditionExpression('1 = 1')),
new CaseCondition('val', new ConditionExpression('2 = 2')),
],
else: 'val'
), 'name')
)
'val',
))
->toBeExecutable(['val int'])
->toBeMysql('(case when (1 = 2) then 5 when (2 = 2) then 6 else `val` end) as `name`')
->toBePgsql('(case when (1 = 2) then 5 when (2 = 2) then 6 else "val" end) as "name"')
->toBeSqlite('(case when (1 = 2) then 5 when (2 = 2) then 6 else "val" end) as "name"')
->toBeSqlsrv('(case when (1 = 2) then 5 when (2 = 2) then 6 else [val] end) as [name]');
->toBeMysql('(case when 1 = 1 then 2 when 2 = 2 then `val` else `val` end)')
->toBePgsql('(case when 1 = 1 then 2 when 2 = 2 then "val" else "val" end)')
->toBeSqlite('(case when 1 = 1 then 2 when 2 = 2 then "val" else "val" end)')
->toBeSqlsrv('(case when 1 = 1 then 2 when 2 = 2 then [val] else [val] end)');

0 comments on commit b642c12

Please sign in to comment.