Skip to content

Commit c3cc31a

Browse files
committed
SqlPreprocessor: support for IN (?) [Closes #256]
1 parent 74f4554 commit c3cc31a

File tree

2 files changed

+13
-2
lines changed

2 files changed

+13
-2
lines changed

src/Database/SqlPreprocessor.php

+7-1
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ public function process(array $params, bool $useParams = false): array
103103
$this->arrayMode = null;
104104
$res[] = Nette\Utils\Strings::replace(
105105
$param,
106-
'~\'[^\']*+\'|"[^"]*+"|\?[a-z]*|^\s*+(?:\(?\s*SELECT|INSERT|UPDATE|DELETE|REPLACE|EXPLAIN)\b|\b(?:SET|WHERE|HAVING|ORDER BY|GROUP BY|KEY UPDATE)(?=\s*$|\s*\?)|/\*.*?\*/|--[^\n]*~Dsi',
106+
'~\'[^\']*+\'|"[^"]*+"|\?[a-z]*|^\s*+(?:\(?\s*SELECT|INSERT|UPDATE|DELETE|REPLACE|EXPLAIN)\b|\b(?:SET|WHERE|HAVING|ORDER BY|GROUP BY|KEY UPDATE)(?=\s*$|\s*\?)|\bIN\s+\(\?\)|/\*.*?\*/|--[^\n]*~Dsi',
107107
\Closure::fromCallable([$this, 'callback'])
108108
);
109109
} else {
@@ -127,6 +127,12 @@ private function callback(array $m): string
127127
} elseif ($m[0] === "'" || $m[0] === '"' || $m[0] === '/' || $m[0] === '-') { // string or comment
128128
return $m;
129129

130+
} elseif (substr($m, -3) === '(?)') { // IN (?)
131+
if ($this->counter >= count($this->params)) {
132+
throw new Nette\InvalidArgumentException('There are more placeholders than passed parameters.');
133+
}
134+
return 'IN (' . $this->formatValue($this->params[$this->counter++], self::MODE_LIST) . ')';
135+
130136
} else { // command
131137
$cmd = ltrim(strtoupper($m), "\t\n\r (");
132138
$this->arrayMode = self::ARRAY_MODES[$cmd] ?? null;

tests/Database/SqlPreprocessor.phpt

+6-1
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,11 @@ test('IN', function () use ($preprocessor) {
8080

8181
Assert::same(reformat('SELECT id FROM author WHERE ([a] IN (NULL, ?, ?, ?)) AND (1=0) AND ([c] NOT IN (NULL, ?, ?, ?))'), $sql);
8282
Assert::same([1, 2, 3, 1, 2, 3], $params);
83+
84+
85+
[$sql, $params] = $preprocessor->process(['SELECT * FROM table WHERE ? AND id IN (?) AND ?', ['a' => 111], [3, 4], ['b' => 222]]);
86+
Assert::same(reformat('SELECT * FROM table WHERE ([a] = ?) AND id IN (?, ?) AND ([b] = ?)'), $sql);
87+
Assert::same([111, 3, 4, 222], $params);
8388
});
8489

8590

@@ -349,7 +354,7 @@ test('?values', function () use ($preprocessor) {
349354

350355
test('automatic detection failed', function () use ($preprocessor) {
351356
Assert::exception(function () use ($preprocessor) {
352-
$preprocessor->process(['INSERT INTO author (name) SELECT name FROM user WHERE id IN (?)', [11, 12]]);
357+
dump($preprocessor->process(['INSERT INTO author (name) SELECT name FROM user WHERE id ?', [11, 12]])); // invalid sql
353358
}, Nette\InvalidArgumentException::class, 'Automaticaly detected multi-insert, but values aren\'t array. If you need try to change mode like "?[and|or|set|values|order|list]". Mode "values" was used.');
354359
});
355360

0 commit comments

Comments
 (0)