Escape like pattern % and _ so that search containing these chars work like expected

This fixes issue #1075
This commit is contained in:
Jan Böhmer 2025-10-19 00:00:03 +02:00
parent 377feaf566
commit 5dbe4ba00b
3 changed files with 15 additions and 7 deletions

View file

@ -96,14 +96,15 @@ class TextConstraint extends AbstractConstraint
//The CONTAINS, LIKE, STARTS and ENDS operators use the LIKE operator, but we have to build the value string differently //The CONTAINS, LIKE, STARTS and ENDS operators use the LIKE operator, but we have to build the value string differently
$like_value = null; $like_value = null;
$escaped_value = str_replace(['%', '_'], ['\%', '\_'], $this->value);
if ($this->operator === 'LIKE') { if ($this->operator === 'LIKE') {
$like_value = $this->value; $like_value = $this->value; //Here we do not escape anything, as the user may provide % and _ wildcards
} elseif ($this->operator === 'STARTS') { } elseif ($this->operator === 'STARTS') {
$like_value = $this->value . '%'; $like_value = $escaped_value . '%';
} elseif ($this->operator === 'ENDS') { } elseif ($this->operator === 'ENDS') {
$like_value = '%' . $this->value; $like_value = '%' . $escaped_value;
} elseif ($this->operator === 'CONTAINS') { } elseif ($this->operator === 'CONTAINS') {
$like_value = '%' . $this->value . '%'; $like_value = '%' . $escaped_value . '%';
} }
if ($like_value !== null) { if ($like_value !== null) {

View file

@ -144,6 +144,8 @@ class PartSearchFilter implements FilterInterface
if ($this->regex) { if ($this->regex) {
$queryBuilder->setParameter('search_query', $this->keyword); $queryBuilder->setParameter('search_query', $this->keyword);
} else { } else {
//Escape % and _ characters in the keyword
$this->keyword = str_replace(['%', '_'], ['\%', '\_'], $this->keyword);
$queryBuilder->setParameter('search_query', '%' . $this->keyword . '%'); $queryBuilder->setParameter('search_query', '%' . $this->keyword . '%');
} }
} }

View file

@ -56,7 +56,6 @@ class ILike extends FunctionNode
{ {
$platform = $sqlWalker->getConnection()->getDatabasePlatform(); $platform = $sqlWalker->getConnection()->getDatabasePlatform();
//
if ($platform instanceof AbstractMySQLPlatform || $platform instanceof SQLitePlatform) { if ($platform instanceof AbstractMySQLPlatform || $platform instanceof SQLitePlatform) {
$operator = 'LIKE'; $operator = 'LIKE';
} elseif ($platform instanceof PostgreSQLPlatform) { } elseif ($platform instanceof PostgreSQLPlatform) {
@ -66,6 +65,12 @@ class ILike extends FunctionNode
throw new \RuntimeException('Platform ' . gettype($platform) . ' does not support case insensitive like expressions.'); throw new \RuntimeException('Platform ' . gettype($platform) . ' does not support case insensitive like expressions.');
} }
return '(' . $this->value->dispatch($sqlWalker) . ' ' . $operator . ' ' . $this->expr->dispatch($sqlWalker) . ')'; $escape = "";
if ($platform instanceof SQLitePlatform) {
//SQLite needs ESCAPE explicitly defined backslash as escape character
$escape = " ESCAPE '\\'";
}
return '(' . $this->value->dispatch($sqlWalker) . ' ' . $operator . ' ' . $this->expr->dispatch($sqlWalker) . $escape . ')';
} }
} }