diff --git a/dibi/drivers/DibiPdoDriver.php b/dibi/drivers/DibiPdoDriver.php index e0bc6d63..f049c011 100644 --- a/dibi/drivers/DibiPdoDriver.php +++ b/dibi/drivers/DibiPdoDriver.php @@ -318,8 +318,9 @@ class DibiPdoDriver extends DibiObject implements IDibiDriver, IDibiResultDriver return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'"); 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, array( '%' => '\\\\%', '_' => '\\\\_')); + $value = strtr($value, array('%' => $bs . '%', '_' => $bs . '_', '\\' => '\\\\')); return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'"); case 'sqlite': diff --git a/dibi/drivers/DibiPostgreDriver.php b/dibi/drivers/DibiPostgreDriver.php index 915f1f73..90eccfa5 100644 --- a/dibi/drivers/DibiPostgreDriver.php +++ b/dibi/drivers/DibiPostgreDriver.php @@ -310,8 +310,9 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver, IDibiResultDr */ public function escapeLike($value, $pos) { + $bs = pg_escape_string($this->connection, '\\'); // standard_conforming_strings = on/off $value = pg_escape_string($this->connection, $value); - $value = strtr($value, array( '%' => '\\\\%', '_' => '\\\\_')); + $value = strtr($value, array('%' => $bs . '%', '_' => $bs . '_', '\\' => '\\\\')); return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'"); } diff --git a/tests/dibi/DibiTranslator.phpt b/tests/dibi/DibiTranslator.phpt index fce89076..659c55db 100644 --- a/tests/dibi/DibiTranslator.phpt +++ b/tests/dibi/DibiTranslator.phpt @@ -198,15 +198,36 @@ Assert::same( // like -if ($config['driver'] !== 'sqlite') { // sqlite2 +$args = array( + "SELECT * FROM products WHERE (title LIKE %like~ AND title LIKE %~like) OR title LIKE %~like~", + 'C', + 'r', + "a\n%_\\'\"" +); + +if ($config['system'] === 'pgsql') { + $conn->query('SET escape_string_warning = off'); // do not log warnings + + $conn->query('SET standard_conforming_strings = off'); + Assert::same( + "SELECT * FROM products WHERE (title LIKE 'C%' AND title LIKE '%r') OR title LIKE '%a\n\\\\%\\\\_\\\\\\\\''\"%'", + $conn->translate($args[0], $args[1], $args[2], $args[3]) + ); + + $conn->query('SET standard_conforming_strings = on'); + Assert::same( + "SELECT * FROM products WHERE (title LIKE 'C%' AND title LIKE '%r') OR title LIKE '%a\n\\%\\_\\\\''\"%'", + $conn->translate($args[0], $args[1], $args[2], $args[3]) + ); + +} elseif ($config['driver'] !== 'sqlite') { // sqlite2 Assert::same( reformat(array( 'sqlite' => "SELECT * FROM products WHERE (title LIKE 'C%' ESCAPE '\\' AND title LIKE '%r' ESCAPE '\\') OR title LIKE '%a\n\\%\\_\\\\''\"%' ESCAPE '\\'", 'odbc' => "SELECT * FROM products WHERE (title LIKE 'C%' AND title LIKE '%r') OR title LIKE '%a\n[%][_]\\''\"%'", - 'pgsql' => "SELECT * FROM products WHERE (title LIKE 'C%' AND title LIKE '%r') OR title LIKE '%a\n\\\\%\\\\_\\''\"%'", "SELECT * FROM products WHERE (title LIKE 'C%' AND title LIKE '%r') OR title LIKE '%a\\n\\%\\_\\\\\\\\\'\"%'", )), - $conn->translate("SELECT * FROM products WHERE (title LIKE %like~ AND title LIKE %~like) OR title LIKE %~like~", 'C', 'r', "a\n%_\\'\"") + $conn->translate($args[0], $args[1], $args[2], $args[3]) ); }