Skip to content

Commit 3538dd7

Browse files
committed
SqlPreprocessor: enables database parameters only for SELECT, INSERT, UPDATE, DELETE, REPLACE and EXPLAIN [Closes #211]
1 parent 0bbb26b commit 3538dd7

File tree

2 files changed

+29
-8
lines changed

2 files changed

+29
-8
lines changed

src/Database/SqlPreprocessor.php

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,15 @@ class SqlPreprocessor
3333
'GROUP BY' => 'order',
3434
];
3535

36+
private const PARAMETRIC_COMMANDS = [
37+
'SELECT' => 1,
38+
'INSERT' => 1,
39+
'UPDATE' => 1,
40+
'DELETE' => 1,
41+
'REPLACE' => 1,
42+
'EXPLAIN' => 1,
43+
];
44+
3645
/** @var Connection */
3746
private $connection;
3847

@@ -48,6 +57,9 @@ class SqlPreprocessor
4857
/** @var int */
4958
private $counter;
5059

60+
/** @var bool */
61+
private $useParams;
62+
5163
/** @var string values|set|and|order */
5264
private $arrayMode;
5365

@@ -62,13 +74,14 @@ public function __construct(Connection $connection)
6274
/**
6375
* @return array of [sql, params]
6476
*/
65-
public function process(array $params): array
77+
public function process(array $params, bool $useParams = false): array
6678
{
6779
$this->params = $params;
6880
$this->counter = 0;
6981
$prev = -1;
7082
$this->remaining = [];
7183
$this->arrayMode = null;
84+
$this->useParams = $useParams;
7285
$res = [];
7386

7487
while ($this->counter < count($params)) {
@@ -83,7 +96,7 @@ public function process(array $params): array
8396
$this->arrayMode = null;
8497
$res[] = Nette\Utils\Strings::replace(
8598
$param,
86-
'~\'[^\']*+\'|"[^"]*+"|\?[a-z]*|^\s*+(?:INSERT|REPLACE)\b|\b(?:SET|WHERE|HAVING|ORDER BY|GROUP BY|KEY UPDATE)(?=\s*\z|\s*\?)|/\*.*?\*/|--[^\n]*~si',
99+
'~\'[^\']*+\'|"[^"]*+"|\?[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',
87100
[$this, 'callback']
88101
);
89102
} else {
@@ -110,7 +123,8 @@ public function callback(array $m): string
110123

111124
} else { // command
112125
$cmd = ltrim(strtoupper($m));
113-
$this->arrayMode = self::ARRAY_MODES[$cmd];
126+
$this->arrayMode = self::ARRAY_MODES[$cmd] ?? null;
127+
$this->useParams = isset(self::PARAMETRIC_COMMANDS[$cmd]) || $this->useParams;
114128
return $m;
115129
}
116130
}
@@ -120,8 +134,15 @@ private function formatValue($value, string $mode = null): string
120134
{
121135
if (!$mode || $mode === 'auto') {
122136
if (is_scalar($value) || is_resource($value)) {
123-
$this->remaining[] = $value;
124-
return '?';
137+
if ($this->useParams) {
138+
$this->remaining[] = $value;
139+
return '?';
140+
} else {
141+
if (is_resource($value)) {
142+
$value = stream_get_contents($value);
143+
}
144+
return $this->connection->quote($value);
145+
}
125146

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

133154
} elseif ($value instanceof SqlLiteral) {
134155
$prep = clone $this;
135-
[$res, $params] = $prep->process(array_merge([$value->__toString()], $value->getParameters()));
156+
[$res, $params] = $prep->process(array_merge([$value->__toString()], $value->getParameters()), $this->useParams);
136157
$this->remaining = array_merge($this->remaining, $params);
137158
return $res;
138159

tests/Database/SqlPreprocessor.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -309,8 +309,8 @@ test(function () use ($preprocessor) { // insert
309309
[$sql, $params] = $preprocessor->process(['/* comment */ INSERT INTO author',
310310
['name' => 'Catelyn Stark'],
311311
]);
312-
Assert::same(reformat('/* comment */ INSERT INTO author [name]=?'), $sql); // autodetection not used
313-
Assert::same(['Catelyn Stark'], $params);
312+
Assert::same(reformat("/* comment */ INSERT INTO author [name]='Catelyn Stark'"), $sql); // autodetection not used
313+
Assert::same([], $params);
314314
});
315315

316316

0 commit comments

Comments
 (0)