Skip to content

Commit

Permalink
fixed incorrect sql LIKE escaping for some db drivers while performin…
Browse files Browse the repository at this point in the history
…g partial filter (#927)
  • Loading branch information
Talpx1 authored May 10, 2024
1 parent 1b038a8 commit 769f3c4
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 2 deletions.
12 changes: 11 additions & 1 deletion src/Filters/FiltersPartial.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Spatie\QueryBuilder\Filters;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\DB;

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

return [
"LOWER({$property}) LIKE ?",
"LOWER({$property}) LIKE ?".self::maybeSpecifyEscapeChar(),
['%'.self::escapeLike($value).'%'],
];
}
Expand All @@ -60,4 +61,13 @@ private static function escapeLike(string $value): string
$value,
);
}

private static function maybeSpecifyEscapeChar(): string
{
if(!in_array(DB::getDriverName(), ["sqlite","pgsql","sqlsrv"])){
return "";
}

return " ESCAPE '\'";
}
}
25 changes: 24 additions & 1 deletion tests/FilterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;

use Pest\Expectation;
use function PHPUnit\Framework\assertObjectHasProperty;

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

expect($queryBuilderSql)->toEqual($expectedSql);
expect($queryBuilderSql)->toContain($expectedSql);
});

it('specifies escape character in supported databases', function (string $dbDriver) {
$fakeConnection = "test_{$dbDriver}";

DB::connectUsing($fakeConnection, [
'driver' => $dbDriver,
'database' => null,
]);

DB::usingConnection($fakeConnection, function() use ($dbDriver){
$request = new Request([
'filter' => ['name' => 'to_find'],
]);

$queryBuilderSql = QueryBuilder::for(TestModel::select('id', 'name'), $request)
->allowedFilters('name', 'id')
->toSql();

expect($queryBuilderSql)->when(in_array($dbDriver, ["sqlite","pgsql","sqlsrv"]), fn(Expectation $query) => $query->toContain("ESCAPE '\'"));
expect($queryBuilderSql)->when($dbDriver === 'mysql', fn(Expectation $query) => $query->not->toContain("ESCAPE '\'"));
});
})->with(['sqlite', 'mysql', 'pgsql', 'sqlsrv']);

it('can filter results based on the existence of a property in an array', function () {
$results = createQueryFromFilterRequest([
'id' => '1,2',
Expand Down

0 comments on commit 769f3c4

Please sign in to comment.