From beb6d1c9dd0a24febc667d0ec315607f028a470d Mon Sep 17 00:00:00 2001 From: Italo Israel Baeza Cabrera Date: Tue, 24 Jun 2025 01:55:53 -0400 Subject: [PATCH] [12.x] Adds value check between two columns --- src/Illuminate/Database/Query/Builder.php | 57 ++++++++++++ .../Database/Query/Grammars/Grammar.php | 18 ++++ tests/Database/DatabaseQueryBuilderTest.php | 88 +++++++++++++++++++ 3 files changed, 163 insertions(+) diff --git a/src/Illuminate/Database/Query/Builder.php b/src/Illuminate/Database/Query/Builder.php index 1a97a0799c33..7c585a169533 100755 --- a/src/Illuminate/Database/Query/Builder.php +++ b/src/Illuminate/Database/Query/Builder.php @@ -1489,6 +1489,63 @@ public function orWhereNotBetweenColumns($column, array $values) return $this->whereNotBetweenColumns($column, $values, 'or'); } + /** + * Add a where between columns statement using a value to the query. + * + * @param mixed $value + * @param array{\Illuminate\Contracts\Database\Query\Expression|string, \Illuminate\Contracts\Database\Query\Expression|string} $columns + * @param string $boolean + * @param bool $not + * @return $this + */ + public function whereValueBetween($value, array $columns, $boolean = 'and', $not = false) + { + $type = 'valueBetween'; + + $this->wheres[] = compact('type', 'value', 'columns', 'boolean', 'not'); + + $this->addBinding($value, 'where'); + + return $this; + } + + /** + * Add an or where between columns statement using a value to the query. + * + * @param mixed $value + * @param array{\Illuminate\Contracts\Database\Query\Expression|string, \Illuminate\Contracts\Database\Query\Expression|string} $columns + * @return $this + */ + public function orWhereValueBetween($value, array $columns) + { + return $this->whereValueBetween($value, $columns, 'or'); + } + + /** + * Add a where not between columns statement using a value to the query. + * + * @param mixed $value + * @param array{\Illuminate\Contracts\Database\Query\Expression|string, \Illuminate\Contracts\Database\Query\Expression|string} $columns + * @param string $boolean + * @return $this + */ + public function whereValueNotBetween($value, array $columns, $boolean = 'and') + { + return $this->whereValueBetween($value, $columns, $boolean, true); + } + + /** + * Add an or where not between columns statement using a value to the query. + * + * @param mixed $value + * @param array{\Illuminate\Contracts\Database\Query\Expression|string, \Illuminate\Contracts\Database\Query\Expression|string} $columns + * @return $this + */ + public function orWhereValueNotBetween($value, array $columns) + { + return $this->whereValueNotBetween($value, $columns, 'or'); + } + /** * Add an "or where not null" clause to the query. * diff --git a/src/Illuminate/Database/Query/Grammars/Grammar.php b/src/Illuminate/Database/Query/Grammars/Grammar.php index ea1c44e00866..07d23d665a5c 100755 --- a/src/Illuminate/Database/Query/Grammars/Grammar.php +++ b/src/Illuminate/Database/Query/Grammars/Grammar.php @@ -455,6 +455,24 @@ protected function whereBetweenColumns(Builder $query, $where) return $this->wrap($where['column']).' '.$between.' '.$min.' and '.$max; } + /** + * Compile a "value between" where clause. + * + * @param \Illuminate\Database\Query\Builder $query + * @param array $where + * @return string + */ + protected function whereValueBetween(Builder $query, $where) + { + $between = $where['not'] ? 'not between' : 'between'; + + $min = $this->wrap(is_array($where['columns']) ? reset($where['columns']) : $where['columns'][0]); + + $max = $this->wrap(is_array($where['columns']) ? end($where['columns']) : $where['columns'][1]); + + return $this->parameter($where['value']).' '.$between.' '.$min.' and '.$max; + } + /** * Compile a "where date" clause. * diff --git a/tests/Database/DatabaseQueryBuilderTest.php b/tests/Database/DatabaseQueryBuilderTest.php index 51b91ebcb062..53629cdff191 100755 --- a/tests/Database/DatabaseQueryBuilderTest.php +++ b/tests/Database/DatabaseQueryBuilderTest.php @@ -1189,6 +1189,94 @@ public function testOrWhereNotBetweenColumns() $this->assertEquals([0 => 2], $builder->getBindings()); } + public function testWhereValueBetween() + { + $builder = $this->getBuilder(); + $builder->select('*')->from('users')->whereValueBetween('2020-01-01 19:30:00', ['created_at', 'updated_at']); + $this->assertSame('select * from "users" where ? between "created_at" and "updated_at"', $builder->toSql()); + $this->assertEquals([0 => '2020-01-01 19:30:00'], $builder->getBindings()); + + $builder = $this->getBuilder(); + $builder->select('*')->from('users')->whereValueBetween('2020-01-01 19:30:00', ['created_at', 'updated_at']); + $this->assertSame('select * from "users" where ? between "created_at" and "updated_at"', $builder->toSql()); + $this->assertEquals([0 => '2020-01-01 19:30:00'], $builder->getBindings()); + + $builder = $this->getBuilder(); + $builder->select('*')->from('users')->whereValueBetween('2020-01-01 19:30:00', [new Raw(1), new Raw(2)]); + $this->assertSame('select * from "users" where ? between 1 and 2', $builder->toSql()); + $this->assertEquals([0 => '2020-01-01 19:30:00'], $builder->getBindings()); + + $builder = $this->getBuilder(); + $builder->select('*')->from('users')->whereValueBetween(new Raw(1), ['created_at', 'updated_at']); + $this->assertSame('select * from "users" where 1 between "created_at" and "updated_at"', $builder->toSql()); + } + + public function testOrWhereValueBetween() + { + $builder = $this->getBuilder(); + $builder->select('*')->from('users')->where('id', 2)->orWhereValueBetween('2020-01-01 19:30:00', ['created_at', 'updated_at']); + $this->assertSame('select * from "users" where "id" = ? or ? between "created_at" and "updated_at"', $builder->toSql()); + $this->assertEquals([0 => 2, 1 => '2020-01-01 19:30:00'], $builder->getBindings()); + + $builder = $this->getBuilder(); + $builder->select('*')->from('users')->where('id', 2)->orWhereValueBetween('2020-01-01 19:30:00', ['created_at', 'updated_at']); + $this->assertSame('select * from "users" where "id" = ? or ? between "created_at" and "updated_at"', $builder->toSql()); + $this->assertEquals([0 => 2, 1 => '2020-01-01 19:30:00'], $builder->getBindings()); + + $builder = $this->getBuilder(); + $builder->select('*')->from('users')->where('id', 2)->orWhereValueBetween('2020-01-01 19:30:00', [new Raw(1), new Raw(2)]); + $this->assertSame('select * from "users" where "id" = ? or ? between 1 and 2', $builder->toSql()); + $this->assertEquals([0 => 2, 1 => '2020-01-01 19:30:00'], $builder->getBindings()); + + $builder = $this->getBuilder(); + $builder->select('*')->from('users')->where('id', 2)->orWhereValueBetween(new Raw(1), ['created_at', 'updated_at']); + $this->assertSame('select * from "users" where "id" = ? or 1 between "created_at" and "updated_at"', $builder->toSql()); + } + + public function testWhereValueNotBetween() + { + $builder = $this->getBuilder(); + $builder->select('*')->from('users')->whereValueNotBetween('2020-01-01 19:30:00', ['created_at', 'updated_at']); + $this->assertSame('select * from "users" where ? not between "created_at" and "updated_at"', $builder->toSql()); + $this->assertEquals([0 => '2020-01-01 19:30:00'], $builder->getBindings()); + + $builder = $this->getBuilder(); + $builder->select('*')->from('users')->whereValueNotBetween('2020-01-01 19:30:00', ['created_at', 'updated_at']); + $this->assertSame('select * from "users" where ? not between "created_at" and "updated_at"', $builder->toSql()); + $this->assertEquals([0 => '2020-01-01 19:30:00'], $builder->getBindings()); + + $builder = $this->getBuilder(); + $builder->select('*')->from('users')->whereValueNotBetween('2020-01-01 19:30:00', [new Raw(1), new Raw(2)]); + $this->assertSame('select * from "users" where ? not between 1 and 2', $builder->toSql()); + $this->assertEquals([0 => '2020-01-01 19:30:00'], $builder->getBindings()); + + $builder = $this->getBuilder(); + $builder->select('*')->from('users')->whereValueNotBetween(new Raw(1), ['created_at', 'updated_at']); + $this->assertSame('select * from "users" where 1 not between "created_at" and "updated_at"', $builder->toSql()); + } + + public function testOrWhereValueNotBetween() + { + $builder = $this->getBuilder(); + $builder->select('*')->from('users')->where('id', 2)->orWhereValueNotBetween('2020-01-01 19:30:00', ['created_at', 'updated_at']); + $this->assertSame('select * from "users" where "id" = ? or ? not between "created_at" and "updated_at"', $builder->toSql()); + $this->assertEquals([0 => 2, 1 => '2020-01-01 19:30:00'], $builder->getBindings()); + + $builder = $this->getBuilder(); + $builder->select('*')->from('users')->where('id', 2)->orWhereValueNotBetween('2020-01-01 19:30:00', ['created_at', 'updated_at']); + $this->assertSame('select * from "users" where "id" = ? or ? not between "created_at" and "updated_at"', $builder->toSql()); + $this->assertEquals([0 => 2, 1 => '2020-01-01 19:30:00'], $builder->getBindings()); + + $builder = $this->getBuilder(); + $builder->select('*')->from('users')->where('id', 2)->orWhereValueNotBetween('2020-01-01 19:30:00', [new Raw(1), new Raw(2)]); + $this->assertSame('select * from "users" where "id" = ? or ? not between 1 and 2', $builder->toSql()); + $this->assertEquals([0 => 2, 1 => '2020-01-01 19:30:00'], $builder->getBindings()); + + $builder = $this->getBuilder(); + $builder->select('*')->from('users')->where('id', 2)->orWhereValueNotBetween(new Raw(1), ['created_at', 'updated_at']); + $this->assertSame('select * from "users" where "id" = ? or 1 not between "created_at" and "updated_at"', $builder->toSql()); + } + public function testBasicOrWheres() { $builder = $this->getBuilder();