Surplus 'N' in front of string param
TumaMilan opened this issue · comments
Version: 4.2.6 (but from 4.1.x)
Bug Description
When using N in front of SQL string param, calling query()
adds another N, so result is NN'param'. SqlsrvDriver only.
Steps To Reproduce
Using sqlsrv driver:
$this->db->query("SELECT * FROM table WHERE N'A' = N'A'");
(where $this->db
is Dibi\Connection
)
The resulting SQL is SELECT * FROM table WHERE NN'A' = NN'A'
and SQL server notices Wrong syntax near text A (translated from Czech error description)
Expected Behavior
No conversion of right SQL code.
Possible Solution
I have no direct solution. From version DIBI 4.1 is added N to function escapeText()
of SqlsrvDriver.php. But escaping of escaped text does waste. Specifically this issue has origin in function cb()
, callback of preg_replace_callback
of function translate()
of Translator.php. Calling
} elseif ($matches[3]) { // SQL strings: '...'
return $this->driver->escapeText(str_replace("''", "'", $matches[4]));
} ...
adds another N in front (behind) of existing N.
Unfortunately I can't make it work by not using 'N'. The query is part of contribute datagrid and is managed by him. Not this query, of course:)
I suggest
- not using 'N' (at least optionally)
- edit regex to ignore N' (N + apostrophe)
Thanks
Milan Tůma
Hm, I've commented it this afternoon but comment is missing - maybe didn't submit the form.
You wrote ...escaping of escaped text does waste...
thats corrent. If you are 100% sure that SQL injection cannot occure, e.g. the SQL string cames from $sql = $connection->translate()
, you should use %SQL
modifier:
$sql = $db->translate('SELECT * FROM table WHERE ? = ?', 'A', 'A');
$db->query('%SQL', $sql); # dibi does not touch it
But must be 100% sure, otherwise it's an SQL injection gateway.
Unfortunately I can't make it work by not using 'N'. The query is part of contribute datagrid
Can you link the specific query that's causing problem?
If you are 100% sure that SQL injection cannot occure, e.g. the SQL string cames from
$sql = $connection->translate()
, you should use%SQL
modifier:
I cannot do any changes to source of Ublaboo datagrid. The algorythm of questioning is automatic. The query is translated twice. Issue is only on combination UblabooDatagrid->Dibi Fluent->MSSQL
Ublaboo datagrid
Sorry, Ublaboo datagrid renamed to Contribute datagrid. But not totally, so it is little confusing 😁
Can you link the specific query that's causing problem?
I'm afraid I don't understand you. If you mean SQL query, so any query containing apostrophe. Any text value. Datagrid does 2 translations of query, second pass destroys the query. I can't influence this.
I tried to change the regex and callback in Translator.php to identify N before apostrophe. But it is not easy and can't guarantee full functionality of function translate()
. I decided to extend class SqlsrvDriver
with my SqlsrvsitmpDriver
:
<?php
declare(strict_types=1);
namespace Dibi\Drivers;
class SqlsrvsitmpDriver extends SqlsrvDriver implements \Dibi\Driver
{
public function escapeText(string $value): string
{
return "'" . str_replace("'", "''", $value) . "'"; // N removed
}
}
and in configuration use
dibi:
driver: sqlsrvsitmp
Removing N could be parametric - for example by new item in dibi options (UseNvarchar = false
) in configuration. This setting would consume __construct()
method of driver class and pass it to method escapeText(string $value)
by local field. But for my use case is it not necessary.
Milan Tůma