1
0
mirror of https://github.com/dg/dibi.git synced 2025-08-04 13:17:58 +02:00

Add support for escapeLike without % on any side (#346) (BC break)

This commit is contained in:
Ashus
2019-11-25 13:53:33 +01:00
committed by David Grudl
parent 9d4bef53d3
commit 294787a26e
11 changed files with 24 additions and 14 deletions

View File

@@ -199,6 +199,7 @@ Three special modifiers are available for LIKE:
| `%like~` | the expression starts with a string | `%like~` | the expression starts with a string
| `%~like` | the expression ends with a string | `%~like` | the expression ends with a string
| `%~like~` | the expression contains a string | `%~like~` | the expression contains a string
| `%like` | the expression matches a string
Search for names beginning with a string: Search for names beginning with a string:

View File

@@ -271,7 +271,7 @@ class FirebirdDriver implements Dibi\Driver
public function escapeLike(string $value, int $pos): string public function escapeLike(string $value, int $pos): string
{ {
$value = addcslashes($this->escapeText($value), '%_\\'); $value = addcslashes($this->escapeText($value), '%_\\');
return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'") . " ESCAPE '\\'"; return ($pos & 1 ? "'%" : "'") . $value . ($pos & 2 ? "%'" : "'") . " ESCAPE '\\'";
} }

View File

@@ -317,7 +317,7 @@ class MySqliDriver implements Dibi\Driver
public function escapeLike(string $value, int $pos): string public function escapeLike(string $value, int $pos): string
{ {
$value = addcslashes(str_replace('\\', '\\\\', $value), "\x00\n\r\\'%_"); $value = addcslashes(str_replace('\\', '\\\\', $value), "\x00\n\r\\'%_");
return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'"); return ($pos & 1 ? "'%" : "'") . $value . ($pos & 2 ? "%'" : "'");
} }

View File

@@ -250,7 +250,7 @@ class OdbcDriver implements Dibi\Driver
public function escapeLike(string $value, int $pos): string public function escapeLike(string $value, int $pos): string
{ {
$value = strtr($value, ["'" => "''", '%' => '[%]', '_' => '[_]', '[' => '[[]']); $value = strtr($value, ["'" => "''", '%' => '[%]', '_' => '[_]', '[' => '[[]']);
return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'"); return ($pos & 1 ? "'%" : "'") . $value . ($pos & 2 ? "%'" : "'");
} }

View File

@@ -270,7 +270,7 @@ class OracleDriver implements Dibi\Driver
{ {
$value = addcslashes(str_replace('\\', '\\\\', $value), "\x00\\%_"); $value = addcslashes(str_replace('\\', '\\\\', $value), "\x00\\%_");
$value = str_replace("'", "''", $value); $value = str_replace("'", "''", $value);
return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'"); return ($pos & 1 ? "'%" : "'") . $value . ($pos & 2 ? "%'" : "'");
} }

View File

@@ -324,29 +324,29 @@ class PdoDriver implements Dibi\Driver
switch ($this->driverName) { switch ($this->driverName) {
case 'mysql': case 'mysql':
$value = addcslashes(str_replace('\\', '\\\\', $value), "\x00\n\r\\'%_"); $value = addcslashes(str_replace('\\', '\\\\', $value), "\x00\n\r\\'%_");
return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'"); return ($pos & 1 ? "'%" : "'") . $value . ($pos & 2 ? "%'" : "'");
case 'oci': case 'oci':
$value = addcslashes(str_replace('\\', '\\\\', $value), "\x00\\%_"); $value = addcslashes(str_replace('\\', '\\\\', $value), "\x00\\%_");
$value = str_replace("'", "''", $value); $value = str_replace("'", "''", $value);
return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'"); return ($pos & 1 ? "'%" : "'") . $value . ($pos & 2 ? "%'" : "'");
case 'pgsql': case 'pgsql':
$bs = substr($this->connection->quote('\\', PDO::PARAM_STR), 1, -1); // standard_conforming_strings = on/off $bs = substr($this->connection->quote('\\', PDO::PARAM_STR), 1, -1); // standard_conforming_strings = on/off
$value = substr($this->connection->quote($value, PDO::PARAM_STR), 1, -1); $value = substr($this->connection->quote($value, PDO::PARAM_STR), 1, -1);
$value = strtr($value, ['%' => $bs . '%', '_' => $bs . '_', '\\' => '\\\\']); $value = strtr($value, ['%' => $bs . '%', '_' => $bs . '_', '\\' => '\\\\']);
return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'"); return ($pos & 1 ? "'%" : "'") . $value . ($pos & 2 ? "%'" : "'");
case 'sqlite': case 'sqlite':
$value = addcslashes(substr($this->connection->quote($value, PDO::PARAM_STR), 1, -1), '%_\\'); $value = addcslashes(substr($this->connection->quote($value, PDO::PARAM_STR), 1, -1), '%_\\');
return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'") . " ESCAPE '\\'"; return ($pos & 1 ? "'%" : "'") . $value . ($pos & 2 ? "%'" : "'") . " ESCAPE '\\'";
case 'odbc': case 'odbc':
case 'mssql': case 'mssql':
case 'dblib': case 'dblib':
case 'sqlsrv': case 'sqlsrv':
$value = strtr($value, ["'" => "''", '%' => '[%]', '_' => '[_]', '[' => '[[]']); $value = strtr($value, ["'" => "''", '%' => '[%]', '_' => '[_]', '[' => '[[]']);
return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'"); return ($pos & 1 ? "'%" : "'") . $value . ($pos & 2 ? "%'" : "'");
default: default:
throw new Dibi\NotImplementedException; throw new Dibi\NotImplementedException;

View File

@@ -318,7 +318,7 @@ class PostgreDriver implements Dibi\Driver
$bs = pg_escape_string($this->connection, '\\'); // standard_conforming_strings = on/off $bs = pg_escape_string($this->connection, '\\'); // standard_conforming_strings = on/off
$value = pg_escape_string($this->connection, $value); $value = pg_escape_string($this->connection, $value);
$value = strtr($value, ['%' => $bs . '%', '_' => $bs . '_', '\\' => '\\\\']); $value = strtr($value, ['%' => $bs . '%', '_' => $bs . '_', '\\' => '\\\\']);
return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'"); return ($pos & 1 ? "'%" : "'") . $value . ($pos & 2 ? "%'" : "'");
} }

View File

@@ -254,7 +254,7 @@ class SqliteDriver implements Dibi\Driver
public function escapeLike(string $value, int $pos): string public function escapeLike(string $value, int $pos): string
{ {
$value = addcslashes($this->connection->escapeString($value), '%_\\'); $value = addcslashes($this->connection->escapeString($value), '%_\\');
return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'") . " ESCAPE '\\'"; return ($pos & 1 ? "'%" : "'") . $value . ($pos & 2 ? "%'" : "'") . " ESCAPE '\\'";
} }

View File

@@ -243,7 +243,7 @@ class SqlsrvDriver implements Dibi\Driver
public function escapeLike(string $value, int $pos): string public function escapeLike(string $value, int $pos): string
{ {
$value = strtr($value, ["'" => "''", '%' => '[%]', '_' => '[_]', '[' => '[[]']); $value = strtr($value, ["'" => "''", '%' => '[%]', '_' => '[_]', '[' => '[[]']);
return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'"); return ($pos & 1 ? "'%" : "'") . $value . ($pos & 2 ? "%'" : "'");
} }

View File

@@ -415,12 +415,15 @@ final class Translator
return (string) $value; return (string) $value;
case 'like~': // LIKE string% case 'like~': // LIKE string%
return $this->driver->escapeLike($value, 1); return $this->driver->escapeLike($value, 2);
case '~like': // LIKE %string case '~like': // LIKE %string
return $this->driver->escapeLike($value, -1); return $this->driver->escapeLike($value, 1);
case '~like~': // LIKE %string% case '~like~': // LIKE %string%
return $this->driver->escapeLike($value, 3);
case 'like': // LIKE string
return $this->driver->escapeLike($value, 0); return $this->driver->escapeLike($value, 0);
case 'and': case 'and':

View File

@@ -71,3 +71,9 @@ Assert::truthy($conn->fetchSingle('SELECT ? LIKE %~like~', 'baa', 'aa'));
Assert::truthy($conn->fetchSingle('SELECT ? LIKE %~like~', 'aab', 'aa')); Assert::truthy($conn->fetchSingle('SELECT ? LIKE %~like~', 'aab', 'aa'));
Assert::falsey($conn->fetchSingle('SELECT ? LIKE %~like~', 'bba', '%a')); Assert::falsey($conn->fetchSingle('SELECT ? LIKE %~like~', 'bba', '%a'));
Assert::truthy($conn->fetchSingle('SELECT ? LIKE %~like~', 'b%a', '%a')); Assert::truthy($conn->fetchSingle('SELECT ? LIKE %~like~', 'b%a', '%a'));
// matches
Assert::truthy($conn->fetchSingle('SELECT ? LIKE %like', 'a', 'a'));
Assert::falsey($conn->fetchSingle('SELECT ? LIKE %like', 'a', 'aa'));
Assert::falsey($conn->fetchSingle('SELECT ? LIKE %like', 'a', 'b'));