Skip to content

Commit

Permalink
Add support for escapeLike without % on any side (#346) (BC break)
Browse files Browse the repository at this point in the history
  • Loading branch information
Ashus authored and dg committed Nov 25, 2019
1 parent 9d4bef5 commit 294787a
Show file tree
Hide file tree
Showing 11 changed files with 24 additions and 14 deletions.
1 change: 1 addition & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ Three special modifiers are available for LIKE:
| `%like~` | the expression starts with a string
| `%~like` | the expression ends with a string
| `%~like~` | the expression contains a string
| `%like` | the expression matches a string

Search for names beginning with a string:

Expand Down
2 changes: 1 addition & 1 deletion src/Dibi/Drivers/FirebirdDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ public function escapeDateInterval(\DateInterval $value): string
public function escapeLike(string $value, int $pos): string
{
$value = addcslashes($this->escapeText($value), '%_\\');
return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'") . " ESCAPE '\\'";
return ($pos & 1 ? "'%" : "'") . $value . ($pos & 2 ? "%'" : "'") . " ESCAPE '\\'";
}


Expand Down
2 changes: 1 addition & 1 deletion src/Dibi/Drivers/MySqliDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ public function escapeDateInterval(\DateInterval $value): string
public function escapeLike(string $value, int $pos): string
{
$value = addcslashes(str_replace('\\', '\\\\', $value), "\x00\n\r\\'%_");
return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'");
return ($pos & 1 ? "'%" : "'") . $value . ($pos & 2 ? "%'" : "'");
}


Expand Down
2 changes: 1 addition & 1 deletion src/Dibi/Drivers/OdbcDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ public function escapeDateInterval(\DateInterval $value): string
public function escapeLike(string $value, int $pos): string
{
$value = strtr($value, ["'" => "''", '%' => '[%]', '_' => '[_]', '[' => '[[]']);
return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'");
return ($pos & 1 ? "'%" : "'") . $value . ($pos & 2 ? "%'" : "'");
}


Expand Down
2 changes: 1 addition & 1 deletion src/Dibi/Drivers/OracleDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ public function escapeLike(string $value, int $pos): string
{
$value = addcslashes(str_replace('\\', '\\\\', $value), "\x00\\%_");
$value = str_replace("'", "''", $value);
return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'");
return ($pos & 1 ? "'%" : "'") . $value . ($pos & 2 ? "%'" : "'");
}


Expand Down
10 changes: 5 additions & 5 deletions src/Dibi/Drivers/PdoDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -324,29 +324,29 @@ public function escapeLike(string $value, int $pos): string
switch ($this->driverName) {
case 'mysql':
$value = addcslashes(str_replace('\\', '\\\\', $value), "\x00\n\r\\'%_");
return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'");
return ($pos & 1 ? "'%" : "'") . $value . ($pos & 2 ? "%'" : "'");

case 'oci':
$value = addcslashes(str_replace('\\', '\\\\', $value), "\x00\\%_");
$value = str_replace("'", "''", $value);
return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'");
return ($pos & 1 ? "'%" : "'") . $value . ($pos & 2 ? "%'" : "'");

case 'pgsql':
$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 = strtr($value, ['%' => $bs . '%', '_' => $bs . '_', '\\' => '\\\\']);
return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'");
return ($pos & 1 ? "'%" : "'") . $value . ($pos & 2 ? "%'" : "'");

case 'sqlite':
$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 'mssql':
case 'dblib':
case 'sqlsrv':
$value = strtr($value, ["'" => "''", '%' => '[%]', '_' => '[_]', '[' => '[[]']);
return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'");
return ($pos & 1 ? "'%" : "'") . $value . ($pos & 2 ? "%'" : "'");

default:
throw new Dibi\NotImplementedException;
Expand Down
2 changes: 1 addition & 1 deletion src/Dibi/Drivers/PostgreDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ public function escapeLike(string $value, int $pos): string
$bs = pg_escape_string($this->connection, '\\'); // standard_conforming_strings = on/off
$value = pg_escape_string($this->connection, $value);
$value = strtr($value, ['%' => $bs . '%', '_' => $bs . '_', '\\' => '\\\\']);
return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'");
return ($pos & 1 ? "'%" : "'") . $value . ($pos & 2 ? "%'" : "'");
}


Expand Down
2 changes: 1 addition & 1 deletion src/Dibi/Drivers/SqliteDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ public function escapeDateInterval(\DateInterval $value): string
public function escapeLike(string $value, int $pos): string
{
$value = addcslashes($this->connection->escapeString($value), '%_\\');
return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'") . " ESCAPE '\\'";
return ($pos & 1 ? "'%" : "'") . $value . ($pos & 2 ? "%'" : "'") . " ESCAPE '\\'";
}


Expand Down
2 changes: 1 addition & 1 deletion src/Dibi/Drivers/SqlsrvDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ public function escapeDateInterval(\DateInterval $value): string
public function escapeLike(string $value, int $pos): string
{
$value = strtr($value, ["'" => "''", '%' => '[%]', '_' => '[_]', '[' => '[[]']);
return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'");
return ($pos & 1 ? "'%" : "'") . $value . ($pos & 2 ? "%'" : "'");
}


Expand Down
7 changes: 5 additions & 2 deletions src/Dibi/Translator.php
Original file line number Diff line number Diff line change
Expand Up @@ -415,12 +415,15 @@ public function formatValue($value, ?string $modifier): string
return (string) $value;

case 'like~': // LIKE string%
return $this->driver->escapeLike($value, 1);
return $this->driver->escapeLike($value, 2);

case '~like': // LIKE %string
return $this->driver->escapeLike($value, -1);
return $this->driver->escapeLike($value, 1);

case '~like~': // LIKE %string%
return $this->driver->escapeLike($value, 3);

case 'like': // LIKE string
return $this->driver->escapeLike($value, 0);

case 'and':
Expand Down
6 changes: 6 additions & 0 deletions tests/dibi/Translator.like.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,9 @@ Assert::truthy($conn->fetchSingle('SELECT ? LIKE %~like~', 'baa', 'aa'));
Assert::truthy($conn->fetchSingle('SELECT ? LIKE %~like~', 'aab', 'aa'));
Assert::falsey($conn->fetchSingle('SELECT ? LIKE %~like~', 'bba', '%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'));

0 comments on commit 294787a

Please sign in to comment.