From 68fe83874215047caf6c9081f16d4b89190be6bb Mon Sep 17 00:00:00 2001 From: Jasper Tey Date: Sat, 27 Jan 2024 14:12:53 -0500 Subject: [PATCH 1/5] Support variable length arithmetic arguments where applicable. --- src/Operator/Arithmetic/Add.php | 4 +- src/Operator/Arithmetic/Divide.php | 4 +- src/Operator/Arithmetic/Modulo.php | 4 +- src/Operator/Arithmetic/Multiply.php | 4 +- src/Operator/Arithmetic/Subtract.php | 4 +- .../VariableLengthOperatorExpression.php | 35 ++++++ tests/Operator/Arithmetic/AddTest.php | 100 ++++++++++++++++++ tests/Operator/Arithmetic/DivideTest.php | 100 ++++++++++++++++++ tests/Operator/Arithmetic/ModuloTest.php | 100 ++++++++++++++++++ tests/Operator/Arithmetic/MultiplyTest.php | 100 ++++++++++++++++++ tests/Operator/Arithmetic/SubtractTest.php | 100 ++++++++++++++++++ 11 files changed, 545 insertions(+), 10 deletions(-) create mode 100644 src/Operator/VariableLengthOperatorExpression.php diff --git a/src/Operator/Arithmetic/Add.php b/src/Operator/Arithmetic/Add.php index 610e38d..37f7b27 100644 --- a/src/Operator/Arithmetic/Add.php +++ b/src/Operator/Arithmetic/Add.php @@ -4,9 +4,9 @@ namespace Tpetry\QueryExpressions\Operator\Arithmetic; -use Tpetry\QueryExpressions\Operator\OperatorExpression; +use Tpetry\QueryExpressions\Operator\VariableLengthOperatorExpression; -class Add extends OperatorExpression +class Add extends VariableLengthOperatorExpression { protected function operator(): string { diff --git a/src/Operator/Arithmetic/Divide.php b/src/Operator/Arithmetic/Divide.php index 772f037..e345c86 100644 --- a/src/Operator/Arithmetic/Divide.php +++ b/src/Operator/Arithmetic/Divide.php @@ -4,9 +4,9 @@ namespace Tpetry\QueryExpressions\Operator\Arithmetic; -use Tpetry\QueryExpressions\Operator\OperatorExpression; +use Tpetry\QueryExpressions\Operator\VariableLengthOperatorExpression; -class Divide extends OperatorExpression +class Divide extends VariableLengthOperatorExpression { protected function operator(): string { diff --git a/src/Operator/Arithmetic/Modulo.php b/src/Operator/Arithmetic/Modulo.php index 7c8b576..9be76fc 100644 --- a/src/Operator/Arithmetic/Modulo.php +++ b/src/Operator/Arithmetic/Modulo.php @@ -4,9 +4,9 @@ namespace Tpetry\QueryExpressions\Operator\Arithmetic; -use Tpetry\QueryExpressions\Operator\OperatorExpression; +use Tpetry\QueryExpressions\Operator\VariableLengthOperatorExpression; -class Modulo extends OperatorExpression +class Modulo extends VariableLengthOperatorExpression { protected function operator(): string { diff --git a/src/Operator/Arithmetic/Multiply.php b/src/Operator/Arithmetic/Multiply.php index ebb9fd0..49513a1 100644 --- a/src/Operator/Arithmetic/Multiply.php +++ b/src/Operator/Arithmetic/Multiply.php @@ -4,9 +4,9 @@ namespace Tpetry\QueryExpressions\Operator\Arithmetic; -use Tpetry\QueryExpressions\Operator\OperatorExpression; +use Tpetry\QueryExpressions\Operator\VariableLengthOperatorExpression; -class Multiply extends OperatorExpression +class Multiply extends VariableLengthOperatorExpression { protected function operator(): string { diff --git a/src/Operator/Arithmetic/Subtract.php b/src/Operator/Arithmetic/Subtract.php index 02fb2ad..f8cfea2 100644 --- a/src/Operator/Arithmetic/Subtract.php +++ b/src/Operator/Arithmetic/Subtract.php @@ -4,9 +4,9 @@ namespace Tpetry\QueryExpressions\Operator\Arithmetic; -use Tpetry\QueryExpressions\Operator\OperatorExpression; +use Tpetry\QueryExpressions\Operator\VariableLengthOperatorExpression; -class Subtract extends OperatorExpression +class Subtract extends VariableLengthOperatorExpression { protected function operator(): string { diff --git a/src/Operator/VariableLengthOperatorExpression.php b/src/Operator/VariableLengthOperatorExpression.php new file mode 100644 index 0000000..485c1da --- /dev/null +++ b/src/Operator/VariableLengthOperatorExpression.php @@ -0,0 +1,35 @@ +values = $values; + } + + public function getValue(Grammar $grammar): string + { + $value = "{$this->stringize($grammar, $this->value1)} {$this->operator()} {$this->stringize($grammar, $this->value2)}"; + + foreach ($this->values as $additional) { + $value .= " {$this->operator()} {$this->stringize($grammar, $additional)}"; + } + + return "({$value})"; + } +} diff --git a/tests/Operator/Arithmetic/AddTest.php b/tests/Operator/Arithmetic/AddTest.php index e49a740..be6d7d6 100644 --- a/tests/Operator/Arithmetic/AddTest.php +++ b/tests/Operator/Arithmetic/AddTest.php @@ -44,3 +44,103 @@ ->toBePgsql('(0 + "val")') ->toBeSqlite('(0 + "val")') ->toBeSqlsrv('(0 + [val])'); + +it('can add many columns', function ($columns, $expectations) { + expect(new Add(...$columns)) + ->toBeExecutable(function (Blueprint $table) use ($columns) { + foreach ($columns as $column) { + $table->integer($column); + } + }) + ->toBeMysql($expectations['mysql']) + ->toBePgsql($expectations['pgsql']) + ->toBeSqlite($expectations['sqlite']) + ->toBeSqlsrv($expectations['sqlsrv']); +})->with([ + 'three' => [ + ['val1', 'val2', 'val3'], + [ + 'mysql' => '(`val1` + `val2` + `val3`)', + 'pgsql' => '("val1" + "val2" + "val3")', + 'sqlite' => '("val1" + "val2" + "val3")', + 'sqlsrv' => '([val1] + [val2] + [val3])', + ], + ], + 'eight' => [ + ['val1', 'val2', 'val3', 'val4', 'val5', 'val6', 'val7', 'val8'], + [ + 'mysql' => '(`val1` + `val2` + `val3` + `val4` + `val5` + `val6` + `val7` + `val8`)', + 'pgsql' => '("val1" + "val2" + "val3" + "val4" + "val5" + "val6" + "val7" + "val8")', + 'sqlite' => '("val1" + "val2" + "val3" + "val4" + "val5" + "val6" + "val7" + "val8")', + 'sqlsrv' => '([val1] + [val2] + [val3] + [val4] + [val5] + [val6] + [val7] + [val8])', + ], + ], +]); + +it('can add many expressions', function ($values, $expectations) { + $expressions = array_map(fn ($value) => new Expression($value), $values); + + expect(new Add(...$expressions)) + ->toBeExecutable() + ->toBeMysql($expectations['mysql']) + ->toBePgsql($expectations['pgsql']) + ->toBeSqlite($expectations['sqlite']) + ->toBeSqlsrv($expectations['sqlsrv']); +})->with([ + 'three' => [ + [1, 2, 3], + [ + 'mysql' => '(1 + 2 + 3)', + 'pgsql' => '(1 + 2 + 3)', + 'sqlite' => '(1 + 2 + 3)', + 'sqlsrv' => '(1 + 2 + 3)', + ], + ], + 'eight' => [ + [1, 2, 3, 4, 5, 6, 7, 8], + [ + 'mysql' => '(1 + 2 + 3 + 4 + 5 + 6 + 7 + 8)', + 'pgsql' => '(1 + 2 + 3 + 4 + 5 + 6 + 7 + 8)', + 'sqlite' => '(1 + 2 + 3 + 4 + 5 + 6 + 7 + 8)', + 'sqlsrv' => '(1 + 2 + 3 + 4 + 5 + 6 + 7 + 8)', + ], + ], +]); + +it('can add many expressions and columns', function (array $values, array $expectations) { + $expressions = array_map( + fn ($value) => is_int($value) + ? new Expression($value) + : $value, + $values + ); + + expect(new Add(...$expressions)) + ->toBeExecutable(function (Blueprint $table) { + $table->integer('val1'); + $table->integer('val2'); + }) + ->toBeMysql($expectations['mysql']) + ->toBePgsql($expectations['pgsql']) + ->toBeSqlite($expectations['sqlite']) + ->toBeSqlsrv($expectations['sqlsrv']); +})->with([ + 'expression/column/...' => [ + ['val1', 1, 'val2', 2], + [ + 'mysql' => '(`val1` + 1 + `val2` + 2)', + 'pgsql' => '("val1" + 1 + "val2" + 2)', + 'sqlite' => '("val1" + 1 + "val2" + 2)', + 'sqlsrv' => '([val1] + 1 + [val2] + 2)', + ], + ], + 'column/expression/...' => [ + [1, 'val1', 2, 'val2'], + [ + 'mysql' => '(1 + `val1` + 2 + `val2`)', + 'pgsql' => '(1 + "val1" + 2 + "val2")', + 'sqlite' => '(1 + "val1" + 2 + "val2")', + 'sqlsrv' => '(1 + [val1] + 2 + [val2])', + ], + ], +]); diff --git a/tests/Operator/Arithmetic/DivideTest.php b/tests/Operator/Arithmetic/DivideTest.php index ae46393..0a46517 100644 --- a/tests/Operator/Arithmetic/DivideTest.php +++ b/tests/Operator/Arithmetic/DivideTest.php @@ -44,3 +44,103 @@ ->toBePgsql('(0 / "val")') ->toBeSqlite('(0 / "val")') ->toBeSqlsrv('(0 / [val])'); + +it('can divide many columns', function ($columns, $expectations) { + expect(new Divide(...$columns)) + ->toBeExecutable(function (Blueprint $table) use ($columns) { + foreach ($columns as $column) { + $table->integer($column); + } + }) + ->toBeMysql($expectations['mysql']) + ->toBePgsql($expectations['pgsql']) + ->toBeSqlite($expectations['sqlite']) + ->toBeSqlsrv($expectations['sqlsrv']); +})->with([ + 'three' => [ + ['val1', 'val2', 'val3'], + [ + 'mysql' => '(`val1` / `val2` / `val3`)', + 'pgsql' => '("val1" / "val2" / "val3")', + 'sqlite' => '("val1" / "val2" / "val3")', + 'sqlsrv' => '([val1] / [val2] / [val3])', + ], + ], + 'eight' => [ + ['val1', 'val2', 'val3', 'val4', 'val5', 'val6', 'val7', 'val8'], + [ + 'mysql' => '(`val1` / `val2` / `val3` / `val4` / `val5` / `val6` / `val7` / `val8`)', + 'pgsql' => '("val1" / "val2" / "val3" / "val4" / "val5" / "val6" / "val7" / "val8")', + 'sqlite' => '("val1" / "val2" / "val3" / "val4" / "val5" / "val6" / "val7" / "val8")', + 'sqlsrv' => '([val1] / [val2] / [val3] / [val4] / [val5] / [val6] / [val7] / [val8])', + ], + ], +]); + +it('can divide many expressions', function ($values, $expectations) { + $expressions = array_map(fn ($value) => new Expression($value), $values); + + expect(new Divide(...$expressions)) + ->toBeExecutable() + ->toBeMysql($expectations['mysql']) + ->toBePgsql($expectations['pgsql']) + ->toBeSqlite($expectations['sqlite']) + ->toBeSqlsrv($expectations['sqlsrv']); +})->with([ + 'three' => [ + [1, 2, 3], + [ + 'mysql' => '(1 / 2 / 3)', + 'pgsql' => '(1 / 2 / 3)', + 'sqlite' => '(1 / 2 / 3)', + 'sqlsrv' => '(1 / 2 / 3)', + ], + ], + 'eight' => [ + [1, 2, 3, 4, 5, 6, 7, 8], + [ + 'mysql' => '(1 / 2 / 3 / 4 / 5 / 6 / 7 / 8)', + 'pgsql' => '(1 / 2 / 3 / 4 / 5 / 6 / 7 / 8)', + 'sqlite' => '(1 / 2 / 3 / 4 / 5 / 6 / 7 / 8)', + 'sqlsrv' => '(1 / 2 / 3 / 4 / 5 / 6 / 7 / 8)', + ], + ], +]); + +it('can divide many expressions and columns', function (array $values, array $expectations) { + $expressions = array_map( + fn ($value) => is_int($value) + ? new Expression($value) + : $value, + $values + ); + + expect(new Divide(...$expressions)) + ->toBeExecutable(function (Blueprint $table) { + $table->integer('val1'); + $table->integer('val2'); + }) + ->toBeMysql($expectations['mysql']) + ->toBePgsql($expectations['pgsql']) + ->toBeSqlite($expectations['sqlite']) + ->toBeSqlsrv($expectations['sqlsrv']); +})->with([ + 'expression/column/...' => [ + ['val1', 1, 'val2', 2], + [ + 'mysql' => '(`val1` / 1 / `val2` / 2)', + 'pgsql' => '("val1" / 1 / "val2" / 2)', + 'sqlite' => '("val1" / 1 / "val2" / 2)', + 'sqlsrv' => '([val1] / 1 / [val2] / 2)', + ], + ], + 'column/expression/...' => [ + [1, 'val1', 2, 'val2'], + [ + 'mysql' => '(1 / `val1` / 2 / `val2`)', + 'pgsql' => '(1 / "val1" / 2 / "val2")', + 'sqlite' => '(1 / "val1" / 2 / "val2")', + 'sqlsrv' => '(1 / [val1] / 2 / [val2])', + ], + ], +]); diff --git a/tests/Operator/Arithmetic/ModuloTest.php b/tests/Operator/Arithmetic/ModuloTest.php index b60d573..1a679e4 100644 --- a/tests/Operator/Arithmetic/ModuloTest.php +++ b/tests/Operator/Arithmetic/ModuloTest.php @@ -44,3 +44,103 @@ ->toBePgsql('(0 % "val")') ->toBeSqlite('(0 % "val")') ->toBeSqlsrv('(0 % [val])'); + +it('can modulo many columns', function ($columns, $expectations) { + expect(new Modulo(...$columns)) + ->toBeExecutable(function (Blueprint $table) use ($columns) { + foreach ($columns as $column) { + $table->integer($column); + } + }) + ->toBeMysql($expectations['mysql']) + ->toBePgsql($expectations['pgsql']) + ->toBeSqlite($expectations['sqlite']) + ->toBeSqlsrv($expectations['sqlsrv']); +})->with([ + 'three' => [ + ['val1', 'val2', 'val3'], + [ + 'mysql' => '(`val1` % `val2` % `val3`)', + 'pgsql' => '("val1" % "val2" % "val3")', + 'sqlite' => '("val1" % "val2" % "val3")', + 'sqlsrv' => '([val1] % [val2] % [val3])', + ], + ], + 'eight' => [ + ['val1', 'val2', 'val3', 'val4', 'val5', 'val6', 'val7', 'val8'], + [ + 'mysql' => '(`val1` % `val2` % `val3` % `val4` % `val5` % `val6` % `val7` % `val8`)', + 'pgsql' => '("val1" % "val2" % "val3" % "val4" % "val5" % "val6" % "val7" % "val8")', + 'sqlite' => '("val1" % "val2" % "val3" % "val4" % "val5" % "val6" % "val7" % "val8")', + 'sqlsrv' => '([val1] % [val2] % [val3] % [val4] % [val5] % [val6] % [val7] % [val8])', + ], + ], +]); + +it('can modulo many expressions', function (array $values, array $expectations) { + $expressions = array_map(fn ($value) => new Expression($value), $values); + + expect(new Modulo(...$expressions)) + ->toBeExecutable() + ->toBeMysql($expectations['mysql']) + ->toBePgsql($expectations['pgsql']) + ->toBeSqlite($expectations['sqlite']) + ->toBeSqlsrv($expectations['sqlsrv']); +})->with([ + 'three' => [ + [1, 2, 3], + [ + 'mysql' => '(1 % 2 % 3)', + 'pgsql' => '(1 % 2 % 3)', + 'sqlite' => '(1 % 2 % 3)', + 'sqlsrv' => '(1 % 2 % 3)', + ], + ], + 'eight' => [ + [1, 2, 3, 4, 5, 6, 7, 8], + [ + 'mysql' => '(1 % 2 % 3 % 4 % 5 % 6 % 7 % 8)', + 'pgsql' => '(1 % 2 % 3 % 4 % 5 % 6 % 7 % 8)', + 'sqlite' => '(1 % 2 % 3 % 4 % 5 % 6 % 7 % 8)', + 'sqlsrv' => '(1 % 2 % 3 % 4 % 5 % 6 % 7 % 8)', + ], + ], +]); + +it('can modulo many expressions and columns', function (array $values, array $expectations) { + $expressions = array_map( + fn ($value) => is_int($value) + ? new Expression($value) + : $value, + $values + ); + + expect(new Modulo(...$expressions)) + ->toBeExecutable(function (Blueprint $table) { + $table->integer('val1'); + $table->integer('val2'); + }) + ->toBeMysql($expectations['mysql']) + ->toBePgsql($expectations['pgsql']) + ->toBeSqlite($expectations['sqlite']) + ->toBeSqlsrv($expectations['sqlsrv']); +})->with([ + 'expression/column/...' => [ + ['val1', 1, 'val2', 2], + [ + 'mysql' => '(`val1` % 1 % `val2` % 2)', + 'pgsql' => '("val1" % 1 % "val2" % 2)', + 'sqlite' => '("val1" % 1 % "val2" % 2)', + 'sqlsrv' => '([val1] % 1 % [val2] % 2)', + ], + ], + 'column/expression/...' => [ + [1, 'val1', 2, 'val2'], + [ + 'mysql' => '(1 % `val1` % 2 % `val2`)', + 'pgsql' => '(1 % "val1" % 2 % "val2")', + 'sqlite' => '(1 % "val1" % 2 % "val2")', + 'sqlsrv' => '(1 % [val1] % 2 % [val2])', + ], + ], +]); diff --git a/tests/Operator/Arithmetic/MultiplyTest.php b/tests/Operator/Arithmetic/MultiplyTest.php index bba93bd..cd58c3f 100644 --- a/tests/Operator/Arithmetic/MultiplyTest.php +++ b/tests/Operator/Arithmetic/MultiplyTest.php @@ -44,3 +44,103 @@ ->toBePgsql('(0 * "val")') ->toBeSqlite('(0 * "val")') ->toBeSqlsrv('(0 * [val])'); + +it('can multiply many columns', function ($columns, $expectations) { + expect(new Multiply(...$columns)) + ->toBeExecutable(function (Blueprint $table) use ($columns) { + foreach ($columns as $column) { + $table->integer($column); + } + }) + ->toBeMysql($expectations['mysql']) + ->toBePgsql($expectations['pgsql']) + ->toBeSqlite($expectations['sqlite']) + ->toBeSqlsrv($expectations['sqlsrv']); +})->with([ + 'three' => [ + ['val1', 'val2', 'val3'], + [ + 'mysql' => '(`val1` * `val2` * `val3`)', + 'pgsql' => '("val1" * "val2" * "val3")', + 'sqlite' => '("val1" * "val2" * "val3")', + 'sqlsrv' => '([val1] * [val2] * [val3])', + ], + ], + 'eight' => [ + ['val1', 'val2', 'val3', 'val4', 'val5', 'val6', 'val7', 'val8'], + [ + 'mysql' => '(`val1` * `val2` * `val3` * `val4` * `val5` * `val6` * `val7` * `val8`)', + 'pgsql' => '("val1" * "val2" * "val3" * "val4" * "val5" * "val6" * "val7" * "val8")', + 'sqlite' => '("val1" * "val2" * "val3" * "val4" * "val5" * "val6" * "val7" * "val8")', + 'sqlsrv' => '([val1] * [val2] * [val3] * [val4] * [val5] * [val6] * [val7] * [val8])', + ], + ], +]); + +it('can multiply many expressions', function (array $values, array $expectations) { + $expressions = array_map(fn ($value) => new Expression($value), $values); + + expect(new Multiply(...$expressions)) + ->toBeExecutable() + ->toBeMysql($expectations['mysql']) + ->toBePgsql($expectations['pgsql']) + ->toBeSqlite($expectations['sqlite']) + ->toBeSqlsrv($expectations['sqlsrv']); +})->with([ + 'three' => [ + [1, 2, 3], + [ + 'mysql' => '(1 * 2 * 3)', + 'pgsql' => '(1 * 2 * 3)', + 'sqlite' => '(1 * 2 * 3)', + 'sqlsrv' => '(1 * 2 * 3)', + ], + ], + 'eight' => [ + [1, 2, 3, 4, 5, 6, 7, 8], + [ + 'mysql' => '(1 * 2 * 3 * 4 * 5 * 6 * 7 * 8)', + 'pgsql' => '(1 * 2 * 3 * 4 * 5 * 6 * 7 * 8)', + 'sqlite' => '(1 * 2 * 3 * 4 * 5 * 6 * 7 * 8)', + 'sqlsrv' => '(1 * 2 * 3 * 4 * 5 * 6 * 7 * 8)', + ], + ], +]); + +it('can multiply many expressions and columns', function (array $values, array $expectations) { + $expressions = array_map( + fn ($value) => is_int($value) + ? new Expression($value) + : $value, + $values + ); + + expect(new Multiply(...$expressions)) + ->toBeExecutable(function (Blueprint $table) { + $table->integer('val1'); + $table->integer('val2'); + }) + ->toBeMysql($expectations['mysql']) + ->toBePgsql($expectations['pgsql']) + ->toBeSqlite($expectations['sqlite']) + ->toBeSqlsrv($expectations['sqlsrv']); +})->with([ + 'expression/column/...' => [ + ['val1', 1, 'val2', 2], + [ + 'mysql' => '(`val1` * 1 * `val2` * 2)', + 'pgsql' => '("val1" * 1 * "val2" * 2)', + 'sqlite' => '("val1" * 1 * "val2" * 2)', + 'sqlsrv' => '([val1] * 1 * [val2] * 2)', + ], + ], + 'column/expression/...' => [ + [1, 'val1', 2, 'val2'], + [ + 'mysql' => '(1 * `val1` * 2 * `val2`)', + 'pgsql' => '(1 * "val1" * 2 * "val2")', + 'sqlite' => '(1 * "val1" * 2 * "val2")', + 'sqlsrv' => '(1 * [val1] * 2 * [val2])', + ], + ], +]); diff --git a/tests/Operator/Arithmetic/SubtractTest.php b/tests/Operator/Arithmetic/SubtractTest.php index 05d5844..5626abb 100644 --- a/tests/Operator/Arithmetic/SubtractTest.php +++ b/tests/Operator/Arithmetic/SubtractTest.php @@ -44,3 +44,103 @@ ->toBePgsql('(0 - "val")') ->toBeSqlite('(0 - "val")') ->toBeSqlsrv('(0 - [val])'); + +it('can subtract many columns', function ($columns, $expectations) { + expect(new Subtract(...$columns)) + ->toBeExecutable(function (Blueprint $table) use ($columns) { + foreach ($columns as $column) { + $table->integer($column); + } + }) + ->toBeMysql($expectations['mysql']) + ->toBePgsql($expectations['pgsql']) + ->toBeSqlite($expectations['sqlite']) + ->toBeSqlsrv($expectations['sqlsrv']); +})->with([ + 'three' => [ + ['val1', 'val2', 'val3'], + [ + 'mysql' => '(`val1` - `val2` - `val3`)', + 'pgsql' => '("val1" - "val2" - "val3")', + 'sqlite' => '("val1" - "val2" - "val3")', + 'sqlsrv' => '([val1] - [val2] - [val3])', + ], + ], + 'eight' => [ + ['val1', 'val2', 'val3', 'val4', 'val5', 'val6', 'val7', 'val8'], + [ + 'mysql' => '(`val1` - `val2` - `val3` - `val4` - `val5` - `val6` - `val7` - `val8`)', + 'pgsql' => '("val1" - "val2" - "val3" - "val4" - "val5" - "val6" - "val7" - "val8")', + 'sqlite' => '("val1" - "val2" - "val3" - "val4" - "val5" - "val6" - "val7" - "val8")', + 'sqlsrv' => '([val1] - [val2] - [val3] - [val4] - [val5] - [val6] - [val7] - [val8])', + ], + ], +]); + +it('can subtract many expressions', function (array $values, array $expectations) { + $expressions = array_map(fn ($value) => new Expression($value), $values); + + expect(new Subtract(...$expressions)) + ->toBeExecutable() + ->toBeMysql($expectations['mysql']) + ->toBePgsql($expectations['pgsql']) + ->toBeSqlite($expectations['sqlite']) + ->toBeSqlsrv($expectations['sqlsrv']); +})->with([ + 'three' => [ + [1, 2, 3], + [ + 'mysql' => '(1 - 2 - 3)', + 'pgsql' => '(1 - 2 - 3)', + 'sqlite' => '(1 - 2 - 3)', + 'sqlsrv' => '(1 - 2 - 3)', + ], + ], + 'eight' => [ + [1, 2, 3, 4, 5, 6, 7, 8], + [ + 'mysql' => '(1 - 2 - 3 - 4 - 5 - 6 - 7 - 8)', + 'pgsql' => '(1 - 2 - 3 - 4 - 5 - 6 - 7 - 8)', + 'sqlite' => '(1 - 2 - 3 - 4 - 5 - 6 - 7 - 8)', + 'sqlsrv' => '(1 - 2 - 3 - 4 - 5 - 6 - 7 - 8)', + ], + ], +]); + +it('can subtract many expressions and columns', function (array $values, array $expectations) { + $expressions = array_map( + fn ($value) => is_int($value) + ? new Expression($value) + : $value, + $values + ); + + expect(new Subtract(...$expressions)) + ->toBeExecutable(function (Blueprint $table) { + $table->integer('val1'); + $table->integer('val2'); + }) + ->toBeMysql($expectations['mysql']) + ->toBePgsql($expectations['pgsql']) + ->toBeSqlite($expectations['sqlite']) + ->toBeSqlsrv($expectations['sqlsrv']); +})->with([ + 'expression/column/...' => [ + ['val1', 1, 'val2', 2], + [ + 'mysql' => '(`val1` - 1 - `val2` - 2)', + 'pgsql' => '("val1" - 1 - "val2" - 2)', + 'sqlite' => '("val1" - 1 - "val2" - 2)', + 'sqlsrv' => '([val1] - 1 - [val2] - 2)', + ], + ], + 'column/expression/...' => [ + [1, 'val1', 2, 'val2'], + [ + 'mysql' => '(1 - `val1` - 2 - `val2`)', + 'pgsql' => '(1 - "val1" - 2 - "val2")', + 'sqlite' => '(1 - "val1" - 2 - "val2")', + 'sqlsrv' => '(1 - [val1] - 2 - [val2])', + ], + ], +]); From 11b7d5ac68c9757c68abd2809fe53a672ca8139f Mon Sep 17 00:00:00 2001 From: Jasper Tey Date: Sat, 27 Jan 2024 14:17:01 -0500 Subject: [PATCH 2/5] Change detail. --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c812644..2a38c23 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] +### Changed +* Arithmetic expressions `Add`, `Subtract`, `Multiply`, `Divide` and `Modulo` now accept variable number of additional arguments beyond the first two + ## [0.9.0] - 2023-11-30 ### Added * Case-when syntax From 87dd71b6927e58df2addba500f75190a507115ba Mon Sep 17 00:00:00 2001 From: Jasper Tey Date: Sat, 27 Jan 2024 19:17:53 -0500 Subject: [PATCH 3/5] Update arithmetic signatures. --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 3ce2fcf..39692ea 100644 --- a/README.md +++ b/README.md @@ -140,12 +140,12 @@ use Tpetry\QueryExpressions\Operator\Arithmetic\{ }; use Tpetry\QueryExpressions\Operator\Value\Value; -new Add(string|Expression $value1, string|Expression $value2); -new Divide(string|Expression $value1, string|Expression $value2); -new Modulo(string|Expression $value1, string|Expression $value2); -new Multiply(string|Expression $value1, string|Expression $value2); +new Add(string|Expression $value1, string|Expression $value2, string|Expression ...$values); +new Divide(string|Expression $value1, string|Expression $value2, string|Expression ...$values); +new Modulo(string|Expression $value1, string|Expression $value2, string|Expression ...$values); +new Multiply(string|Expression $value1, string|Expression $value2, string|Expression ...$values); new Power(string|Expression $value1, string|Expression $value2); -new Subtract(string|Expression $value1, string|Expression $value2); +new Subtract(string|Expression $value1, string|Expression $value2, string|Expression ...$values); // UPDATE user_quotas SET credits = credits - 15 WHERE id = 1985 $quota->update([ From a96d8f87d067caede05db92da5da2c05e5bf3662 Mon Sep 17 00:00:00 2001 From: tpetry Date: Mon, 12 Feb 2024 17:20:54 +0100 Subject: [PATCH 4/5] improvements --- src/Operator/Arithmetic/Add.php | 4 +- .../Arithmetic/ArithmeticExpression.php | 48 ++++++++ src/Operator/Arithmetic/Divide.php | 4 +- src/Operator/Arithmetic/Modulo.php | 4 +- src/Operator/Arithmetic/Multiply.php | 4 +- src/Operator/Arithmetic/Power.php | 39 ++++--- src/Operator/Arithmetic/Subtract.php | 4 +- .../VariableLengthOperatorExpression.php | 35 ------ tests/Operator/Arithmetic/AddTest.php | 109 ++---------------- tests/Operator/Arithmetic/DivideTest.php | 109 ++---------------- tests/Operator/Arithmetic/ModuloTest.php | 109 ++---------------- tests/Operator/Arithmetic/MultiplyTest.php | 109 ++---------------- tests/Operator/Arithmetic/PowerTest.php | 11 ++ tests/Operator/Arithmetic/SubtractTest.php | 109 ++---------------- 14 files changed, 140 insertions(+), 558 deletions(-) create mode 100644 src/Operator/Arithmetic/ArithmeticExpression.php delete mode 100644 src/Operator/VariableLengthOperatorExpression.php diff --git a/src/Operator/Arithmetic/Add.php b/src/Operator/Arithmetic/Add.php index 37f7b27..fc218c1 100644 --- a/src/Operator/Arithmetic/Add.php +++ b/src/Operator/Arithmetic/Add.php @@ -4,9 +4,7 @@ namespace Tpetry\QueryExpressions\Operator\Arithmetic; -use Tpetry\QueryExpressions\Operator\VariableLengthOperatorExpression; - -class Add extends VariableLengthOperatorExpression +class Add extends ArithmeticExpression { protected function operator(): string { diff --git a/src/Operator/Arithmetic/ArithmeticExpression.php b/src/Operator/Arithmetic/ArithmeticExpression.php new file mode 100644 index 0000000..e1d1f59 --- /dev/null +++ b/src/Operator/Arithmetic/ArithmeticExpression.php @@ -0,0 +1,48 @@ +values = $values; + } + + public function getValue(Grammar $grammar): string + { + $expression = implode(" {$this->operator()} ", $this->expressions($grammar)); + + return "({$expression})"; + } + + /** + * @return array + */ + protected function expressions(Grammar $grammar): array + { + return array_map( + fn (string|Expression $value) => $this->stringize($grammar, $value), + [$this->value1, $this->value2, ...$this->values], + ); + } + + abstract protected function operator(): string; +} diff --git a/src/Operator/Arithmetic/Divide.php b/src/Operator/Arithmetic/Divide.php index e345c86..962202a 100644 --- a/src/Operator/Arithmetic/Divide.php +++ b/src/Operator/Arithmetic/Divide.php @@ -4,9 +4,7 @@ namespace Tpetry\QueryExpressions\Operator\Arithmetic; -use Tpetry\QueryExpressions\Operator\VariableLengthOperatorExpression; - -class Divide extends VariableLengthOperatorExpression +class Divide extends ArithmeticExpression { protected function operator(): string { diff --git a/src/Operator/Arithmetic/Modulo.php b/src/Operator/Arithmetic/Modulo.php index 9be76fc..24dc94f 100644 --- a/src/Operator/Arithmetic/Modulo.php +++ b/src/Operator/Arithmetic/Modulo.php @@ -4,9 +4,7 @@ namespace Tpetry\QueryExpressions\Operator\Arithmetic; -use Tpetry\QueryExpressions\Operator\VariableLengthOperatorExpression; - -class Modulo extends VariableLengthOperatorExpression +class Modulo extends ArithmeticExpression { protected function operator(): string { diff --git a/src/Operator/Arithmetic/Multiply.php b/src/Operator/Arithmetic/Multiply.php index 49513a1..3087816 100644 --- a/src/Operator/Arithmetic/Multiply.php +++ b/src/Operator/Arithmetic/Multiply.php @@ -4,9 +4,7 @@ namespace Tpetry\QueryExpressions\Operator\Arithmetic; -use Tpetry\QueryExpressions\Operator\VariableLengthOperatorExpression; - -class Multiply extends VariableLengthOperatorExpression +class Multiply extends ArithmeticExpression { protected function operator(): string { diff --git a/src/Operator/Arithmetic/Power.php b/src/Operator/Arithmetic/Power.php index 0fde741..a4751c3 100644 --- a/src/Operator/Arithmetic/Power.php +++ b/src/Operator/Arithmetic/Power.php @@ -4,30 +4,43 @@ namespace Tpetry\QueryExpressions\Operator\Arithmetic; -use Illuminate\Contracts\Database\Query\Expression; use Illuminate\Database\Grammar; use Tpetry\QueryExpressions\Concerns\IdentifiesDriver; use Tpetry\QueryExpressions\Concerns\StringizeExpression; -class Power implements Expression +class Power extends ArithmeticExpression { use IdentifiesDriver; use StringizeExpression; - public function __construct( - private readonly string|Expression $value1, - private readonly string|Expression $value2, - ) { + public function getValue(Grammar $grammar): string + { + return match ($this->identify($grammar)) { + 'mysql', 'sqlite', 'sqlsrv' => $this->buildPowerFunctionChain($grammar), + 'pgsql' => parent::getValue($grammar), + }; } - public function getValue(Grammar $grammar) + protected function buildPowerFunctionChain(Grammar $grammar): string { - $value1 = $this->stringize($grammar, $this->value1); - $value2 = $this->stringize($grammar, $this->value2); + $expressions = $this->expressions($grammar); - return match ($this->identify($grammar)) { - 'mysql', 'sqlite', 'sqlsrv' => "power({$value1}, {$value2})", - 'pgsql' => "({$value1} ^ {$value2})", - }; + // Build the initial expressions by using the two required parameters of the object. + $value0 = array_shift($expressions); + $value1 = array_shift($expressions); + $expression = "power({$value0}, {$value1})"; + + // For each remaining value call the power function again with the last result and the new value. + while (count($expressions) > 0) { + $value = array_shift($expressions); + $expression = "power({$expression}, $value)"; + } + + return $expression; + } + + protected function operator(): string + { + return '^'; } } diff --git a/src/Operator/Arithmetic/Subtract.php b/src/Operator/Arithmetic/Subtract.php index f8cfea2..fcaf903 100644 --- a/src/Operator/Arithmetic/Subtract.php +++ b/src/Operator/Arithmetic/Subtract.php @@ -4,9 +4,7 @@ namespace Tpetry\QueryExpressions\Operator\Arithmetic; -use Tpetry\QueryExpressions\Operator\VariableLengthOperatorExpression; - -class Subtract extends VariableLengthOperatorExpression +class Subtract extends ArithmeticExpression { protected function operator(): string { diff --git a/src/Operator/VariableLengthOperatorExpression.php b/src/Operator/VariableLengthOperatorExpression.php deleted file mode 100644 index 485c1da..0000000 --- a/src/Operator/VariableLengthOperatorExpression.php +++ /dev/null @@ -1,35 +0,0 @@ -values = $values; - } - - public function getValue(Grammar $grammar): string - { - $value = "{$this->stringize($grammar, $this->value1)} {$this->operator()} {$this->stringize($grammar, $this->value2)}"; - - foreach ($this->values as $additional) { - $value .= " {$this->operator()} {$this->stringize($grammar, $additional)}"; - } - - return "({$value})"; - } -} diff --git a/tests/Operator/Arithmetic/AddTest.php b/tests/Operator/Arithmetic/AddTest.php index be6d7d6..cb96789 100644 --- a/tests/Operator/Arithmetic/AddTest.php +++ b/tests/Operator/Arithmetic/AddTest.php @@ -45,102 +45,13 @@ ->toBeSqlite('(0 + "val")') ->toBeSqlsrv('(0 + [val])'); -it('can add many columns', function ($columns, $expectations) { - expect(new Add(...$columns)) - ->toBeExecutable(function (Blueprint $table) use ($columns) { - foreach ($columns as $column) { - $table->integer($column); - } - }) - ->toBeMysql($expectations['mysql']) - ->toBePgsql($expectations['pgsql']) - ->toBeSqlite($expectations['sqlite']) - ->toBeSqlsrv($expectations['sqlsrv']); -})->with([ - 'three' => [ - ['val1', 'val2', 'val3'], - [ - 'mysql' => '(`val1` + `val2` + `val3`)', - 'pgsql' => '("val1" + "val2" + "val3")', - 'sqlite' => '("val1" + "val2" + "val3")', - 'sqlsrv' => '([val1] + [val2] + [val3])', - ], - ], - 'eight' => [ - ['val1', 'val2', 'val3', 'val4', 'val5', 'val6', 'val7', 'val8'], - [ - 'mysql' => '(`val1` + `val2` + `val3` + `val4` + `val5` + `val6` + `val7` + `val8`)', - 'pgsql' => '("val1" + "val2" + "val3" + "val4" + "val5" + "val6" + "val7" + "val8")', - 'sqlite' => '("val1" + "val2" + "val3" + "val4" + "val5" + "val6" + "val7" + "val8")', - 'sqlsrv' => '([val1] + [val2] + [val3] + [val4] + [val5] + [val6] + [val7] + [val8])', - ], - ], -]); - -it('can add many expressions', function ($values, $expectations) { - $expressions = array_map(fn ($value) => new Expression($value), $values); - - expect(new Add(...$expressions)) - ->toBeExecutable() - ->toBeMysql($expectations['mysql']) - ->toBePgsql($expectations['pgsql']) - ->toBeSqlite($expectations['sqlite']) - ->toBeSqlsrv($expectations['sqlsrv']); -})->with([ - 'three' => [ - [1, 2, 3], - [ - 'mysql' => '(1 + 2 + 3)', - 'pgsql' => '(1 + 2 + 3)', - 'sqlite' => '(1 + 2 + 3)', - 'sqlsrv' => '(1 + 2 + 3)', - ], - ], - 'eight' => [ - [1, 2, 3, 4, 5, 6, 7, 8], - [ - 'mysql' => '(1 + 2 + 3 + 4 + 5 + 6 + 7 + 8)', - 'pgsql' => '(1 + 2 + 3 + 4 + 5 + 6 + 7 + 8)', - 'sqlite' => '(1 + 2 + 3 + 4 + 5 + 6 + 7 + 8)', - 'sqlsrv' => '(1 + 2 + 3 + 4 + 5 + 6 + 7 + 8)', - ], - ], -]); - -it('can add many expressions and columns', function (array $values, array $expectations) { - $expressions = array_map( - fn ($value) => is_int($value) - ? new Expression($value) - : $value, - $values - ); - - expect(new Add(...$expressions)) - ->toBeExecutable(function (Blueprint $table) { - $table->integer('val1'); - $table->integer('val2'); - }) - ->toBeMysql($expectations['mysql']) - ->toBePgsql($expectations['pgsql']) - ->toBeSqlite($expectations['sqlite']) - ->toBeSqlsrv($expectations['sqlsrv']); -})->with([ - 'expression/column/...' => [ - ['val1', 1, 'val2', 2], - [ - 'mysql' => '(`val1` + 1 + `val2` + 2)', - 'pgsql' => '("val1" + 1 + "val2" + 2)', - 'sqlite' => '("val1" + 1 + "val2" + 2)', - 'sqlsrv' => '([val1] + 1 + [val2] + 2)', - ], - ], - 'column/expression/...' => [ - [1, 'val1', 2, 'val2'], - [ - 'mysql' => '(1 + `val1` + 2 + `val2`)', - 'pgsql' => '(1 + "val1" + 2 + "val2")', - 'sqlite' => '(1 + "val1" + 2 + "val2")', - 'sqlsrv' => '(1 + [val1] + 2 + [val2])', - ], - ], -]); +it('can add variadic values') + ->expect(new Add(new Expression(0), 'val1', 'val2', new Expression(1))) + ->toBeExecutable(function (Blueprint $table) { + $table->integer('val1'); + $table->integer('val2'); + }) + ->toBeMysql('(0 + `val1` + `val2` + 1)') + ->toBePgsql('(0 + "val1" + "val2" + 1)') + ->toBeSqlite('(0 + "val1" + "val2" + 1)') + ->toBeSqlsrv('(0 + [val1] + [val2] + 1)'); diff --git a/tests/Operator/Arithmetic/DivideTest.php b/tests/Operator/Arithmetic/DivideTest.php index 0a46517..37a3378 100644 --- a/tests/Operator/Arithmetic/DivideTest.php +++ b/tests/Operator/Arithmetic/DivideTest.php @@ -45,102 +45,13 @@ ->toBeSqlite('(0 / "val")') ->toBeSqlsrv('(0 / [val])'); -it('can divide many columns', function ($columns, $expectations) { - expect(new Divide(...$columns)) - ->toBeExecutable(function (Blueprint $table) use ($columns) { - foreach ($columns as $column) { - $table->integer($column); - } - }) - ->toBeMysql($expectations['mysql']) - ->toBePgsql($expectations['pgsql']) - ->toBeSqlite($expectations['sqlite']) - ->toBeSqlsrv($expectations['sqlsrv']); -})->with([ - 'three' => [ - ['val1', 'val2', 'val3'], - [ - 'mysql' => '(`val1` / `val2` / `val3`)', - 'pgsql' => '("val1" / "val2" / "val3")', - 'sqlite' => '("val1" / "val2" / "val3")', - 'sqlsrv' => '([val1] / [val2] / [val3])', - ], - ], - 'eight' => [ - ['val1', 'val2', 'val3', 'val4', 'val5', 'val6', 'val7', 'val8'], - [ - 'mysql' => '(`val1` / `val2` / `val3` / `val4` / `val5` / `val6` / `val7` / `val8`)', - 'pgsql' => '("val1" / "val2" / "val3" / "val4" / "val5" / "val6" / "val7" / "val8")', - 'sqlite' => '("val1" / "val2" / "val3" / "val4" / "val5" / "val6" / "val7" / "val8")', - 'sqlsrv' => '([val1] / [val2] / [val3] / [val4] / [val5] / [val6] / [val7] / [val8])', - ], - ], -]); - -it('can divide many expressions', function ($values, $expectations) { - $expressions = array_map(fn ($value) => new Expression($value), $values); - - expect(new Divide(...$expressions)) - ->toBeExecutable() - ->toBeMysql($expectations['mysql']) - ->toBePgsql($expectations['pgsql']) - ->toBeSqlite($expectations['sqlite']) - ->toBeSqlsrv($expectations['sqlsrv']); -})->with([ - 'three' => [ - [1, 2, 3], - [ - 'mysql' => '(1 / 2 / 3)', - 'pgsql' => '(1 / 2 / 3)', - 'sqlite' => '(1 / 2 / 3)', - 'sqlsrv' => '(1 / 2 / 3)', - ], - ], - 'eight' => [ - [1, 2, 3, 4, 5, 6, 7, 8], - [ - 'mysql' => '(1 / 2 / 3 / 4 / 5 / 6 / 7 / 8)', - 'pgsql' => '(1 / 2 / 3 / 4 / 5 / 6 / 7 / 8)', - 'sqlite' => '(1 / 2 / 3 / 4 / 5 / 6 / 7 / 8)', - 'sqlsrv' => '(1 / 2 / 3 / 4 / 5 / 6 / 7 / 8)', - ], - ], -]); - -it('can divide many expressions and columns', function (array $values, array $expectations) { - $expressions = array_map( - fn ($value) => is_int($value) - ? new Expression($value) - : $value, - $values - ); - - expect(new Divide(...$expressions)) - ->toBeExecutable(function (Blueprint $table) { - $table->integer('val1'); - $table->integer('val2'); - }) - ->toBeMysql($expectations['mysql']) - ->toBePgsql($expectations['pgsql']) - ->toBeSqlite($expectations['sqlite']) - ->toBeSqlsrv($expectations['sqlsrv']); -})->with([ - 'expression/column/...' => [ - ['val1', 1, 'val2', 2], - [ - 'mysql' => '(`val1` / 1 / `val2` / 2)', - 'pgsql' => '("val1" / 1 / "val2" / 2)', - 'sqlite' => '("val1" / 1 / "val2" / 2)', - 'sqlsrv' => '([val1] / 1 / [val2] / 2)', - ], - ], - 'column/expression/...' => [ - [1, 'val1', 2, 'val2'], - [ - 'mysql' => '(1 / `val1` / 2 / `val2`)', - 'pgsql' => '(1 / "val1" / 2 / "val2")', - 'sqlite' => '(1 / "val1" / 2 / "val2")', - 'sqlsrv' => '(1 / [val1] / 2 / [val2])', - ], - ], -]); +it('can divide variadic values') + ->expect(new Divide(new Expression(0), 'val1', 'val2', new Expression(1))) + ->toBeExecutable(function (Blueprint $table) { + $table->integer('val1'); + $table->integer('val2'); + }) + ->toBeMysql('(0 / `val1` / `val2` / 1)') + ->toBePgsql('(0 / "val1" / "val2" / 1)') + ->toBeSqlite('(0 / "val1" / "val2" / 1)') + ->toBeSqlsrv('(0 / [val1] / [val2] / 1)'); diff --git a/tests/Operator/Arithmetic/ModuloTest.php b/tests/Operator/Arithmetic/ModuloTest.php index 1a679e4..4f78e07 100644 --- a/tests/Operator/Arithmetic/ModuloTest.php +++ b/tests/Operator/Arithmetic/ModuloTest.php @@ -45,102 +45,13 @@ ->toBeSqlite('(0 % "val")') ->toBeSqlsrv('(0 % [val])'); -it('can modulo many columns', function ($columns, $expectations) { - expect(new Modulo(...$columns)) - ->toBeExecutable(function (Blueprint $table) use ($columns) { - foreach ($columns as $column) { - $table->integer($column); - } - }) - ->toBeMysql($expectations['mysql']) - ->toBePgsql($expectations['pgsql']) - ->toBeSqlite($expectations['sqlite']) - ->toBeSqlsrv($expectations['sqlsrv']); -})->with([ - 'three' => [ - ['val1', 'val2', 'val3'], - [ - 'mysql' => '(`val1` % `val2` % `val3`)', - 'pgsql' => '("val1" % "val2" % "val3")', - 'sqlite' => '("val1" % "val2" % "val3")', - 'sqlsrv' => '([val1] % [val2] % [val3])', - ], - ], - 'eight' => [ - ['val1', 'val2', 'val3', 'val4', 'val5', 'val6', 'val7', 'val8'], - [ - 'mysql' => '(`val1` % `val2` % `val3` % `val4` % `val5` % `val6` % `val7` % `val8`)', - 'pgsql' => '("val1" % "val2" % "val3" % "val4" % "val5" % "val6" % "val7" % "val8")', - 'sqlite' => '("val1" % "val2" % "val3" % "val4" % "val5" % "val6" % "val7" % "val8")', - 'sqlsrv' => '([val1] % [val2] % [val3] % [val4] % [val5] % [val6] % [val7] % [val8])', - ], - ], -]); - -it('can modulo many expressions', function (array $values, array $expectations) { - $expressions = array_map(fn ($value) => new Expression($value), $values); - - expect(new Modulo(...$expressions)) - ->toBeExecutable() - ->toBeMysql($expectations['mysql']) - ->toBePgsql($expectations['pgsql']) - ->toBeSqlite($expectations['sqlite']) - ->toBeSqlsrv($expectations['sqlsrv']); -})->with([ - 'three' => [ - [1, 2, 3], - [ - 'mysql' => '(1 % 2 % 3)', - 'pgsql' => '(1 % 2 % 3)', - 'sqlite' => '(1 % 2 % 3)', - 'sqlsrv' => '(1 % 2 % 3)', - ], - ], - 'eight' => [ - [1, 2, 3, 4, 5, 6, 7, 8], - [ - 'mysql' => '(1 % 2 % 3 % 4 % 5 % 6 % 7 % 8)', - 'pgsql' => '(1 % 2 % 3 % 4 % 5 % 6 % 7 % 8)', - 'sqlite' => '(1 % 2 % 3 % 4 % 5 % 6 % 7 % 8)', - 'sqlsrv' => '(1 % 2 % 3 % 4 % 5 % 6 % 7 % 8)', - ], - ], -]); - -it('can modulo many expressions and columns', function (array $values, array $expectations) { - $expressions = array_map( - fn ($value) => is_int($value) - ? new Expression($value) - : $value, - $values - ); - - expect(new Modulo(...$expressions)) - ->toBeExecutable(function (Blueprint $table) { - $table->integer('val1'); - $table->integer('val2'); - }) - ->toBeMysql($expectations['mysql']) - ->toBePgsql($expectations['pgsql']) - ->toBeSqlite($expectations['sqlite']) - ->toBeSqlsrv($expectations['sqlsrv']); -})->with([ - 'expression/column/...' => [ - ['val1', 1, 'val2', 2], - [ - 'mysql' => '(`val1` % 1 % `val2` % 2)', - 'pgsql' => '("val1" % 1 % "val2" % 2)', - 'sqlite' => '("val1" % 1 % "val2" % 2)', - 'sqlsrv' => '([val1] % 1 % [val2] % 2)', - ], - ], - 'column/expression/...' => [ - [1, 'val1', 2, 'val2'], - [ - 'mysql' => '(1 % `val1` % 2 % `val2`)', - 'pgsql' => '(1 % "val1" % 2 % "val2")', - 'sqlite' => '(1 % "val1" % 2 % "val2")', - 'sqlsrv' => '(1 % [val1] % 2 % [val2])', - ], - ], -]); +it('can modulo variadic values') + ->expect(new Modulo(new Expression(0), 'val1', 'val2', new Expression(1))) + ->toBeExecutable(function (Blueprint $table) { + $table->integer('val1'); + $table->integer('val2'); + }) + ->toBeMysql('(0 % `val1` % `val2` % 1)') + ->toBePgsql('(0 % "val1" % "val2" % 1)') + ->toBeSqlite('(0 % "val1" % "val2" % 1)') + ->toBeSqlsrv('(0 % [val1] % [val2] % 1)'); diff --git a/tests/Operator/Arithmetic/MultiplyTest.php b/tests/Operator/Arithmetic/MultiplyTest.php index cd58c3f..bc1e013 100644 --- a/tests/Operator/Arithmetic/MultiplyTest.php +++ b/tests/Operator/Arithmetic/MultiplyTest.php @@ -45,102 +45,13 @@ ->toBeSqlite('(0 * "val")') ->toBeSqlsrv('(0 * [val])'); -it('can multiply many columns', function ($columns, $expectations) { - expect(new Multiply(...$columns)) - ->toBeExecutable(function (Blueprint $table) use ($columns) { - foreach ($columns as $column) { - $table->integer($column); - } - }) - ->toBeMysql($expectations['mysql']) - ->toBePgsql($expectations['pgsql']) - ->toBeSqlite($expectations['sqlite']) - ->toBeSqlsrv($expectations['sqlsrv']); -})->with([ - 'three' => [ - ['val1', 'val2', 'val3'], - [ - 'mysql' => '(`val1` * `val2` * `val3`)', - 'pgsql' => '("val1" * "val2" * "val3")', - 'sqlite' => '("val1" * "val2" * "val3")', - 'sqlsrv' => '([val1] * [val2] * [val3])', - ], - ], - 'eight' => [ - ['val1', 'val2', 'val3', 'val4', 'val5', 'val6', 'val7', 'val8'], - [ - 'mysql' => '(`val1` * `val2` * `val3` * `val4` * `val5` * `val6` * `val7` * `val8`)', - 'pgsql' => '("val1" * "val2" * "val3" * "val4" * "val5" * "val6" * "val7" * "val8")', - 'sqlite' => '("val1" * "val2" * "val3" * "val4" * "val5" * "val6" * "val7" * "val8")', - 'sqlsrv' => '([val1] * [val2] * [val3] * [val4] * [val5] * [val6] * [val7] * [val8])', - ], - ], -]); - -it('can multiply many expressions', function (array $values, array $expectations) { - $expressions = array_map(fn ($value) => new Expression($value), $values); - - expect(new Multiply(...$expressions)) - ->toBeExecutable() - ->toBeMysql($expectations['mysql']) - ->toBePgsql($expectations['pgsql']) - ->toBeSqlite($expectations['sqlite']) - ->toBeSqlsrv($expectations['sqlsrv']); -})->with([ - 'three' => [ - [1, 2, 3], - [ - 'mysql' => '(1 * 2 * 3)', - 'pgsql' => '(1 * 2 * 3)', - 'sqlite' => '(1 * 2 * 3)', - 'sqlsrv' => '(1 * 2 * 3)', - ], - ], - 'eight' => [ - [1, 2, 3, 4, 5, 6, 7, 8], - [ - 'mysql' => '(1 * 2 * 3 * 4 * 5 * 6 * 7 * 8)', - 'pgsql' => '(1 * 2 * 3 * 4 * 5 * 6 * 7 * 8)', - 'sqlite' => '(1 * 2 * 3 * 4 * 5 * 6 * 7 * 8)', - 'sqlsrv' => '(1 * 2 * 3 * 4 * 5 * 6 * 7 * 8)', - ], - ], -]); - -it('can multiply many expressions and columns', function (array $values, array $expectations) { - $expressions = array_map( - fn ($value) => is_int($value) - ? new Expression($value) - : $value, - $values - ); - - expect(new Multiply(...$expressions)) - ->toBeExecutable(function (Blueprint $table) { - $table->integer('val1'); - $table->integer('val2'); - }) - ->toBeMysql($expectations['mysql']) - ->toBePgsql($expectations['pgsql']) - ->toBeSqlite($expectations['sqlite']) - ->toBeSqlsrv($expectations['sqlsrv']); -})->with([ - 'expression/column/...' => [ - ['val1', 1, 'val2', 2], - [ - 'mysql' => '(`val1` * 1 * `val2` * 2)', - 'pgsql' => '("val1" * 1 * "val2" * 2)', - 'sqlite' => '("val1" * 1 * "val2" * 2)', - 'sqlsrv' => '([val1] * 1 * [val2] * 2)', - ], - ], - 'column/expression/...' => [ - [1, 'val1', 2, 'val2'], - [ - 'mysql' => '(1 * `val1` * 2 * `val2`)', - 'pgsql' => '(1 * "val1" * 2 * "val2")', - 'sqlite' => '(1 * "val1" * 2 * "val2")', - 'sqlsrv' => '(1 * [val1] * 2 * [val2])', - ], - ], -]); +it('can multiply variadic values') + ->expect(new Multiply(new Expression(0), 'val1', 'val2', new Expression(1))) + ->toBeExecutable(function (Blueprint $table) { + $table->integer('val1'); + $table->integer('val2'); + }) + ->toBeMysql('(0 * `val1` * `val2` * 1)') + ->toBePgsql('(0 * "val1" * "val2" * 1)') + ->toBeSqlite('(0 * "val1" * "val2" * 1)') + ->toBeSqlsrv('(0 * [val1] * [val2] * 1)'); diff --git a/tests/Operator/Arithmetic/PowerTest.php b/tests/Operator/Arithmetic/PowerTest.php index 838ebad..66c5b87 100644 --- a/tests/Operator/Arithmetic/PowerTest.php +++ b/tests/Operator/Arithmetic/PowerTest.php @@ -44,3 +44,14 @@ ->toBePgsql('(0 ^ "val")') ->toBeSqlite('power(0, "val")') ->toBeSqlsrv('power(0, [val])'); + +it('can power variadic values') + ->expect(new Power(new Expression(0), 'val1', 'val2', new Expression(1))) + ->toBeExecutable(function (Blueprint $table) { + $table->integer('val1'); + $table->integer('val2'); + }) + ->toBeMysql('power(power(power(0, `val1`), `val2`), 1)') + ->toBePgsql('(0 ^ "val1" ^ "val2" ^ 1)') + ->toBeSqlite('power(power(power(0, "val1"), "val2"), 1)') + ->toBeSqlsrv('power(power(power(0, [val1]), [val2]), 1)'); diff --git a/tests/Operator/Arithmetic/SubtractTest.php b/tests/Operator/Arithmetic/SubtractTest.php index 5626abb..e8ab26c 100644 --- a/tests/Operator/Arithmetic/SubtractTest.php +++ b/tests/Operator/Arithmetic/SubtractTest.php @@ -45,102 +45,13 @@ ->toBeSqlite('(0 - "val")') ->toBeSqlsrv('(0 - [val])'); -it('can subtract many columns', function ($columns, $expectations) { - expect(new Subtract(...$columns)) - ->toBeExecutable(function (Blueprint $table) use ($columns) { - foreach ($columns as $column) { - $table->integer($column); - } - }) - ->toBeMysql($expectations['mysql']) - ->toBePgsql($expectations['pgsql']) - ->toBeSqlite($expectations['sqlite']) - ->toBeSqlsrv($expectations['sqlsrv']); -})->with([ - 'three' => [ - ['val1', 'val2', 'val3'], - [ - 'mysql' => '(`val1` - `val2` - `val3`)', - 'pgsql' => '("val1" - "val2" - "val3")', - 'sqlite' => '("val1" - "val2" - "val3")', - 'sqlsrv' => '([val1] - [val2] - [val3])', - ], - ], - 'eight' => [ - ['val1', 'val2', 'val3', 'val4', 'val5', 'val6', 'val7', 'val8'], - [ - 'mysql' => '(`val1` - `val2` - `val3` - `val4` - `val5` - `val6` - `val7` - `val8`)', - 'pgsql' => '("val1" - "val2" - "val3" - "val4" - "val5" - "val6" - "val7" - "val8")', - 'sqlite' => '("val1" - "val2" - "val3" - "val4" - "val5" - "val6" - "val7" - "val8")', - 'sqlsrv' => '([val1] - [val2] - [val3] - [val4] - [val5] - [val6] - [val7] - [val8])', - ], - ], -]); - -it('can subtract many expressions', function (array $values, array $expectations) { - $expressions = array_map(fn ($value) => new Expression($value), $values); - - expect(new Subtract(...$expressions)) - ->toBeExecutable() - ->toBeMysql($expectations['mysql']) - ->toBePgsql($expectations['pgsql']) - ->toBeSqlite($expectations['sqlite']) - ->toBeSqlsrv($expectations['sqlsrv']); -})->with([ - 'three' => [ - [1, 2, 3], - [ - 'mysql' => '(1 - 2 - 3)', - 'pgsql' => '(1 - 2 - 3)', - 'sqlite' => '(1 - 2 - 3)', - 'sqlsrv' => '(1 - 2 - 3)', - ], - ], - 'eight' => [ - [1, 2, 3, 4, 5, 6, 7, 8], - [ - 'mysql' => '(1 - 2 - 3 - 4 - 5 - 6 - 7 - 8)', - 'pgsql' => '(1 - 2 - 3 - 4 - 5 - 6 - 7 - 8)', - 'sqlite' => '(1 - 2 - 3 - 4 - 5 - 6 - 7 - 8)', - 'sqlsrv' => '(1 - 2 - 3 - 4 - 5 - 6 - 7 - 8)', - ], - ], -]); - -it('can subtract many expressions and columns', function (array $values, array $expectations) { - $expressions = array_map( - fn ($value) => is_int($value) - ? new Expression($value) - : $value, - $values - ); - - expect(new Subtract(...$expressions)) - ->toBeExecutable(function (Blueprint $table) { - $table->integer('val1'); - $table->integer('val2'); - }) - ->toBeMysql($expectations['mysql']) - ->toBePgsql($expectations['pgsql']) - ->toBeSqlite($expectations['sqlite']) - ->toBeSqlsrv($expectations['sqlsrv']); -})->with([ - 'expression/column/...' => [ - ['val1', 1, 'val2', 2], - [ - 'mysql' => '(`val1` - 1 - `val2` - 2)', - 'pgsql' => '("val1" - 1 - "val2" - 2)', - 'sqlite' => '("val1" - 1 - "val2" - 2)', - 'sqlsrv' => '([val1] - 1 - [val2] - 2)', - ], - ], - 'column/expression/...' => [ - [1, 'val1', 2, 'val2'], - [ - 'mysql' => '(1 - `val1` - 2 - `val2`)', - 'pgsql' => '(1 - "val1" - 2 - "val2")', - 'sqlite' => '(1 - "val1" - 2 - "val2")', - 'sqlsrv' => '(1 - [val1] - 2 - [val2])', - ], - ], -]); +it('can subtract variadic values') + ->expect(new Subtract(new Expression(0), 'val1', 'val2', new Expression(1))) + ->toBeExecutable(function (Blueprint $table) { + $table->integer('val1'); + $table->integer('val2'); + }) + ->toBeMysql('(0 - `val1` - `val2` - 1)') + ->toBePgsql('(0 - "val1" - "val2" - 1)') + ->toBeSqlite('(0 - "val1" - "val2" - 1)') + ->toBeSqlsrv('(0 - [val1] - [val2] - 1)'); From 4d7162a1857854e7cd2bdcebafdfcee57d921f92 Mon Sep 17 00:00:00 2001 From: tpetry Date: Mon, 12 Feb 2024 17:21:44 +0100 Subject: [PATCH 5/5] removed changelog --- CHANGELOG.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a38c23..c812644 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,10 +5,6 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [Unreleased] -### Changed -* Arithmetic expressions `Add`, `Subtract`, `Multiply`, `Divide` and `Modulo` now accept variable number of additional arguments beyond the first two - ## [0.9.0] - 2023-11-30 ### Added * Case-when syntax