Skip to content

Commit 8d2b91d

Browse files
committed
SqlPreprocessor: support for IN (?) [Closes #256]
1 parent 3a12769 commit 8d2b91d

File tree

2 files changed

+12
-2
lines changed

2 files changed

+12
-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

+5-1
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,10 @@ test('IN', function () use ($preprocessor) {
7979

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

8488

@@ -343,7 +347,7 @@ test('?values', function () use ($preprocessor) {
343347

344348
test('automatic detection failed', function () use ($preprocessor) {
345349
Assert::exception(function () use ($preprocessor) {
346-
$preprocessor->process(['INSERT INTO author (name) SELECT name FROM user WHERE id IN (?)', [11, 12]]);
350+
dump($preprocessor->process(['INSERT INTO author (name) SELECT name FROM user WHERE id ?', [11, 12]])); // invalid sql
347351
}, 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.');
348352
});
349353

0 commit comments

Comments
 (0)