Skip to content

Commit

Permalink
SqlPreprocessor: enables database parameters only for SELECT, INSERT,…
Browse files Browse the repository at this point in the history
… UPDATE, DELETE, REPLACE and EXPLAIN [Closes #211]
  • Loading branch information
dg committed Nov 20, 2018
1 parent 298fca9 commit 7c08500
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 8 deletions.
33 changes: 27 additions & 6 deletions src/Database/SqlPreprocessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,15 @@ class SqlPreprocessor
'GROUP BY' => 'order',
];

private const PARAMETRIC_COMMANDS = [
'SELECT' => 1,
'INSERT' => 1,
'UPDATE' => 1,
'DELETE' => 1,
'REPLACE' => 1,
'EXPLAIN' => 1,
];

/** @var Connection */
private $connection;

Expand All @@ -48,6 +57,9 @@ class SqlPreprocessor
/** @var int */
private $counter;

/** @var bool */
private $useParams;

/** @var string values|set|and|order */
private $arrayMode;

Expand All @@ -62,13 +74,14 @@ public function __construct(Connection $connection)
/**
* @return array of [sql, params]
*/
public function process(array $params): array
public function process(array $params, bool $useParams = false): array
{
$this->params = $params;
$this->counter = 0;
$prev = -1;
$this->remaining = [];
$this->arrayMode = null;
$this->useParams = $useParams;
$res = [];

while ($this->counter < count($params)) {
Expand All @@ -83,7 +96,7 @@ public function process(array $params): array
$this->arrayMode = null;
$res[] = Nette\Utils\Strings::replace(
$param,
'~\'[^\']*+\'|"[^"]*+"|\?[a-z]*|^\s*+(?:INSERT|REPLACE)\b|\b(?:SET|WHERE|HAVING|ORDER BY|GROUP BY|KEY UPDATE)(?=\s*\z|\s*\?)|/\*.*?\*/|--[^\n]*~si',
'~\'[^\']*+\'|"[^"]*+"|\?[a-z]*|^\s*+(?:SELECT|INSERT|UPDATE|DELETE|REPLACE|EXPLAIN)\b|\b(?:SET|WHERE|HAVING|ORDER BY|GROUP BY|KEY UPDATE)(?=\s*\z|\s*\?)|/\*.*?\*/|--[^\n]*~si',
[$this, 'callback']
);
} else {
Expand All @@ -110,7 +123,8 @@ public function callback(array $m): string

} else { // command
$cmd = ltrim(strtoupper($m));
$this->arrayMode = self::ARRAY_MODES[$cmd];
$this->arrayMode = self::ARRAY_MODES[$cmd] ?? null;
$this->useParams = isset(self::PARAMETRIC_COMMANDS[$cmd]) || $this->useParams;
return $m;
}
}
Expand All @@ -120,8 +134,15 @@ private function formatValue($value, string $mode = null): string
{
if (!$mode || $mode === 'auto') {
if (is_scalar($value) || is_resource($value)) {
$this->remaining[] = $value;
return '?';
if ($this->useParams) {
$this->remaining[] = $value;
return '?';
} else {
if (is_resource($value)) {
$value = stream_get_contents($value);
}
return $this->connection->quote($value);
}

} elseif ($value === null) {
return 'NULL';
Expand All @@ -132,7 +153,7 @@ private function formatValue($value, string $mode = null): string

} elseif ($value instanceof SqlLiteral) {
$prep = clone $this;
[$res, $params] = $prep->process(array_merge([$value->__toString()], $value->getParameters()));
[$res, $params] = $prep->process(array_merge([$value->__toString()], $value->getParameters()), $this->useParams);
$this->remaining = array_merge($this->remaining, $params);
return $res;

Expand Down
4 changes: 2 additions & 2 deletions tests/Database/SqlPreprocessor.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -309,8 +309,8 @@ test(function () use ($preprocessor) { // insert
[$sql, $params] = $preprocessor->process(['/* comment */ INSERT INTO author',
['name' => 'Catelyn Stark'],
]);
Assert::same(reformat('/* comment */ INSERT INTO author [name]=?'), $sql); // autodetection not used
Assert::same(['Catelyn Stark'], $params);
Assert::same(reformat("/* comment */ INSERT INTO author [name]='Catelyn Stark'"), $sql); // autodetection not used
Assert::same([], $params);
});


Expand Down

0 comments on commit 7c08500

Please sign in to comment.