Skip to content

Commit 769f3c4

Browse files
authored
fixed incorrect sql LIKE escaping for some db drivers while performing partial filter (#927)
1 parent 1b038a8 commit 769f3c4

File tree

2 files changed

+35
-2
lines changed

2 files changed

+35
-2
lines changed

src/Filters/FiltersPartial.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Spatie\QueryBuilder\Filters;
44

55
use Illuminate\Database\Eloquent\Builder;
6+
use Illuminate\Support\Facades\DB;
67

78
/**
89
* @template TModelClass of \Illuminate\Database\Eloquent\Model
@@ -47,7 +48,7 @@ protected function getWhereRawParameters($value, string $property): array
4748
$value = mb_strtolower((string) $value, 'UTF8');
4849

4950
return [
50-
"LOWER({$property}) LIKE ?",
51+
"LOWER({$property}) LIKE ?".self::maybeSpecifyEscapeChar(),
5152
['%'.self::escapeLike($value).'%'],
5253
];
5354
}
@@ -60,4 +61,13 @@ private static function escapeLike(string $value): string
6061
$value,
6162
);
6263
}
64+
65+
private static function maybeSpecifyEscapeChar(): string
66+
{
67+
if(!in_array(DB::getDriverName(), ["sqlite","pgsql","sqlsrv"])){
68+
return "";
69+
}
70+
71+
return " ESCAPE '\'";
72+
}
6373
}

tests/FilterTest.php

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use Illuminate\Support\Carbon;
66
use Illuminate\Support\Facades\DB;
77

8+
use Pest\Expectation;
89
use function PHPUnit\Framework\assertObjectHasProperty;
910

1011
use Spatie\QueryBuilder\AllowedFilter;
@@ -86,9 +87,31 @@
8687
->where(DB::raw('LOWER(`test_models`.`name`)'), 'LIKE', 'john')
8788
->toSql();
8889

89-
expect($queryBuilderSql)->toEqual($expectedSql);
90+
expect($queryBuilderSql)->toContain($expectedSql);
9091
});
9192

93+
it('specifies escape character in supported databases', function (string $dbDriver) {
94+
$fakeConnection = "test_{$dbDriver}";
95+
96+
DB::connectUsing($fakeConnection, [
97+
'driver' => $dbDriver,
98+
'database' => null,
99+
]);
100+
101+
DB::usingConnection($fakeConnection, function() use ($dbDriver){
102+
$request = new Request([
103+
'filter' => ['name' => 'to_find'],
104+
]);
105+
106+
$queryBuilderSql = QueryBuilder::for(TestModel::select('id', 'name'), $request)
107+
->allowedFilters('name', 'id')
108+
->toSql();
109+
110+
expect($queryBuilderSql)->when(in_array($dbDriver, ["sqlite","pgsql","sqlsrv"]), fn(Expectation $query) => $query->toContain("ESCAPE '\'"));
111+
expect($queryBuilderSql)->when($dbDriver === 'mysql', fn(Expectation $query) => $query->not->toContain("ESCAPE '\'"));
112+
});
113+
})->with(['sqlite', 'mysql', 'pgsql', 'sqlsrv']);
114+
92115
it('can filter results based on the existence of a property in an array', function () {
93116
$results = createQueryFromFilterRequest([
94117
'id' => '1,2',

0 commit comments

Comments
 (0)