API Platform version(s) affected: 4.3.10
(api-platform/doctrine-orm / api-platform/symfony)
Description
ApiPlatform\Doctrine\Orm\Filter\PartialSearchFilter generates SQL LIKE expressions with ESCAPE '\'.
On Oracle this fails with:
ORA-01425: escape character must be character string of length 1
In the executed SQL the escape clause appears as ESCAPE '\\' / ESCAPE '\\\\' (depending on logging), which Oracle rejects because the escape character is not a single-character string.
This affects both case-sensitive and case-insensitive modes, since both append the same ESCAPE '\' clause.
How to reproduce
- Use API Platform 4.3.x with Doctrine ORM on an Oracle database.
- Configure a collection operation with
PartialSearchFilter:
use ApiPlatform\Doctrine\Orm\Filter\PartialSearchFilter;
use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Metadata\QueryParameter;
new GetCollection(
uriTemplate: '/items',
parameters: [
'name' => new QueryParameter(
filter: new PartialSearchFilter(),
property: 'name',
),
],
)
- Call:
- Observe the generated SQL containing something like:
LOWER(o.name) LIKE LOWER(:name_p1) ESCAPE '\\'
and Oracle raising ORA-01425.
Relevant code in PartialSearchFilter:
$field.' LIKE :'.$parameterName.' ESCAPE \'\\\''
// and
'LOWER('.$field.') LIKE LOWER(:'.$parameterName.') ESCAPE \'\\\''
with:
private function formatLikeValue(string $value): string
{
return '%'.addcslashes($value, '\\%_').'%';
}
Possible Solution
Make the escape character configurable (constructor option), and/or use a DB-agnostic escape character that Oracle accepts (e.g. !), updating both:
- the
ESCAPE '...' SQL clause
formatLikeValue() escaping of %, _, and the escape character itself
Example approach:
public function __construct(
private readonly bool $caseSensitive = false,
private readonly string $escapeCharacter = '\\',
) {}
Then for Oracle consumers:
new PartialSearchFilter(escapeCharacter: '!')
Alternatively, detect the database platform and choose a safe default escape character for Oracle.
Additional Context
- Database: Oracle
- Error:
Doctrine\DBAL\Exception\DriverException wrapping ORA-01425
- Workaround used locally: custom filter based on
PartialSearchFilter, replacing \ with ! as escape character in both the SQL ESCAPE clause and value escaping.
- Same issue likely impacts any environment where
ESCAPE '\' is not treated as a single-character literal.
API Platform version(s) affected: 4.3.10
(
api-platform/doctrine-orm/api-platform/symfony)Description
ApiPlatform\Doctrine\Orm\Filter\PartialSearchFiltergenerates SQLLIKEexpressions withESCAPE '\'.On Oracle this fails with:
In the executed SQL the escape clause appears as
ESCAPE '\\'/ESCAPE '\\\\'(depending on logging), which Oracle rejects because the escape character is not a single-character string.This affects both case-sensitive and case-insensitive modes, since both append the same
ESCAPE '\'clause.How to reproduce
PartialSearchFilter:and Oracle raising
ORA-01425.Relevant code in
PartialSearchFilter:with:
Possible Solution
Make the escape character configurable (constructor option), and/or use a DB-agnostic escape character that Oracle accepts (e.g.
!), updating both:ESCAPE '...'SQL clauseformatLikeValue()escaping of%,_, and the escape character itselfExample approach:
Then for Oracle consumers:
Alternatively, detect the database platform and choose a safe default escape character for Oracle.
Additional Context
Doctrine\DBAL\Exception\DriverExceptionwrappingORA-01425PartialSearchFilter, replacing\with!as escape character in both the SQLESCAPEclause and value escaping.ESCAPE '\'is not treated as a single-character literal.