diff --git a/src/Query/BuilderWhere.php b/src/Query/BuilderWhere.php index 5fd3684..5aac70a 100644 --- a/src/Query/BuilderWhere.php +++ b/src/Query/BuilderWhere.php @@ -110,6 +110,18 @@ public function orWhereNotBoolean($column, bool $value): static return $this->orWhere($column, '!=', new Expression(var_export($value, true))); } + /** + * Add an "or where not like" clause to the query. + * + * @param Expression|string $column + * @param Expression|string $value + * @param bool $caseSensitive + */ + public function orWhereNotLike($column, $value, $caseSensitive = false): static + { + return $this->whereNotLike($column, $value, $caseSensitive, 'or'); + } + /** * Add a where all statement to the query. * @@ -178,7 +190,7 @@ public function whereIntegerArrayMatches($column, string $query): static } /** - * Add a "where month" statement to the query. + * Add a "where like" statement to the query. * * @param Expression|string $column * @param Expression|string $value @@ -235,4 +247,17 @@ public function whereNotBoolean($column, bool $value): static { return $this->where($column, '!=', new Expression(var_export($value, true))); } + + /** + * Add a "where not like" statement to the query. + * + * @param Expression|string $column + * @param Expression|string $value + * @param bool $caseSensitive + * @param string $boolean + */ + public function whereNotLike($column, $value, $caseSensitive = false, $boolean = 'and'): static + { + return $this->whereLike($column, $value, $caseSensitive, $boolean, true); + } } diff --git a/src/Query/GrammarWhere.php b/src/Query/GrammarWhere.php index 0c792b9..0f5acc7 100644 --- a/src/Query/GrammarWhere.php +++ b/src/Query/GrammarWhere.php @@ -46,14 +46,14 @@ public function whereAny(Builder $query, $where): string /** * Compile a "like" clause. * - * @param array{caseSensitive: bool, column: string, value: mixed} $where + * @param array{caseSensitive: bool, column: string, not: bool, value: mixed} $where */ public function whereLike(Builder $query, $where): string { - return match ($where['caseSensitive']) { - true => "{$this->wrap($where['column'])} like {$this->parameter($where['value'])}", - false => "{$this->wrap($where['column'])} ilike {$this->parameter($where['value'])}", - }; + $operator = $where['not'] ? 'not ' : ''; + $operator .= $where['caseSensitive'] ? 'like' : 'ilike'; + + return "{$this->wrap($where['column'])}::text {$operator} {$this->parameter($where['value'])}"; } /** diff --git a/tests/Query/WhereTest.php b/tests/Query/WhereTest.php index 7c7de50..79a1e53 100644 --- a/tests/Query/WhereTest.php +++ b/tests/Query/WhereTest.php @@ -99,7 +99,7 @@ public function testOrWhereLike(): void $this->getConnection()->table('example')->orWhereLike('str', 'OamekKIC', true)->orWhereLike('str', 'HmC3xURl', true)->get(); }); $this->assertEquals( - ['select * from "example" where "str" ilike ? or "str" ilike ?', 'select * from "example" where "str" like ? or "str" like ?'], + ['select * from "example" where "str"::text ilike ? or "str"::text ilike ?', 'select * from "example" where "str"::text like ? or "str"::text like ?'], array_column($queries, 'query'), ); $this->assertEquals( @@ -172,6 +172,24 @@ public function testOrWhereNotBoolean(): void ); } + public function testOrWhereNotLike(): void + { + $this->getConnection()->unprepared('CREATE TABLE example (str text)'); + + $queries = $this->withQueryLog(function (): void { + $this->getConnection()->table('example')->orWhereNotLike('str', 'AERLFW4s')->orWhereNotLike('str', 'sPtXxruW')->get(); + $this->getConnection()->table('example')->orWhereNotLike('str', 'EWnGRRc5', true)->orWhereNotLike('str', 'wihuWcph', true)->get(); + }); + $this->assertEquals( + ['select * from "example" where "str"::text not ilike ? or "str"::text not ilike ?', 'select * from "example" where "str"::text not like ? or "str"::text not like ?'], + array_column($queries, 'query'), + ); + $this->assertEquals( + [['AERLFW4s', 'sPtXxruW'], ['EWnGRRc5', 'wihuWcph']], + array_column($queries, 'bindings'), + ); + } + public function testWhereAllValues(): void { $this->getConnection()->unprepared('CREATE TABLE example (val text)'); @@ -258,7 +276,7 @@ public function testWhereLike(): void $this->getConnection()->table('example')->whereLike('str', 'IcuC5Cqz', true)->get(); }); $this->assertEquals( - ['select * from "example" where "str" ilike ?', 'select * from "example" where "str" like ?'], + ['select * from "example" where "str"::text ilike ?', 'select * from "example" where "str"::text like ?'], array_column($queries, 'query'), ); $this->assertEquals( @@ -330,4 +348,22 @@ public function testWhereNotBoolean(): void array_column($queries, 'query'), ); } + + public function testWhereNotLike(): void + { + $this->getConnection()->unprepared('CREATE TABLE example (str text)'); + + $queries = $this->withQueryLog(function (): void { + $this->getConnection()->table('example')->whereNotLike('str', 'mgb7DtKz')->get(); + $this->getConnection()->table('example')->whereNotLike('str', 'tpx6Bxpm', true)->get(); + }); + $this->assertEquals( + ['select * from "example" where "str"::text not ilike ?', 'select * from "example" where "str"::text not like ?'], + array_column($queries, 'query'), + ); + $this->assertEquals( + [['mgb7DtKz'], ['tpx6Bxpm']], + array_column($queries, 'bindings'), + ); + } }