Skip to content

Commit

Permalink
Merge pull request doctrine#6134 from shyim/add-binary-array-type
Browse files Browse the repository at this point in the history
Add binary array type
  • Loading branch information
derrabus authored Aug 28, 2023
2 parents 36a5136 + 504462e commit 4117fec
Show file tree
Hide file tree
Showing 7 changed files with 404 additions and 6 deletions.
4 changes: 3 additions & 1 deletion docs/en/reference/data-retrieval-and-manipulation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -253,10 +253,12 @@ SQL injection possibilities if not handled carefully.
Doctrine DBAL implements a very powerful parsing process that will make this kind of prepared
statement possible natively in the binding type system.
The parsing necessarily comes with a performance overhead, but only if you really use a list of parameters.
There are two special binding types that describe a list of integers or strings:
There are four special binding types that describe a list of integers, regular, ascii or binary strings:

- ``\Doctrine\DBAL\ArrayParameterType::INTEGER``
- ``\Doctrine\DBAL\ArrayParameterType::STRING``
- ``\Doctrine\DBAL\ArrayParameterType::ASCII``
- ``\Doctrine\DBAL\ArrayParameterType::BINARY``

Using one of these constants as a type you can activate the SQLParser inside Doctrine that rewrites
the SQL and flattens the specified values into the set of parameters. Consider our previous example:
Expand Down
7 changes: 6 additions & 1 deletion src/ArrayParameterType.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,17 @@ final class ArrayParameterType
*/
public const ASCII = ParameterType::ASCII + Connection::ARRAY_PARAM_OFFSET;

/**
* Represents an array of ascii strings to be expanded by Doctrine SQL parsing.
*/
public const BINARY = ParameterType::BINARY + Connection::ARRAY_PARAM_OFFSET;

/**
* @internal
*
* @psalm-param self::* $type
*
* @psalm-return ParameterType::INTEGER|ParameterType::STRING|ParameterType::ASCII
* @psalm-return ParameterType::INTEGER|ParameterType::STRING|ParameterType::ASCII|ParameterType::BINARY
*/
public static function toElementParameterType(int $type): int
{
Expand Down
1 change: 1 addition & 0 deletions src/Connection.php
Original file line number Diff line number Diff line change
Expand Up @@ -1919,6 +1919,7 @@ private function needsArrayParameterConversion(array $params, array $types): boo
$type === ArrayParameterType::INTEGER
|| $type === ArrayParameterType::STRING
|| $type === ArrayParameterType::ASCII
|| $type === ArrayParameterType::BINARY
) {
return true;
}
Expand Down
1 change: 1 addition & 0 deletions src/ExpandArrayParameters.php
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ private function acceptParameter($key, $value): void
$type !== ArrayParameterType::INTEGER
&& $type !== ArrayParameterType::STRING
&& $type !== ArrayParameterType::ASCII
&& $type !== ArrayParameterType::BINARY
) {
$this->appendTypedParameter([$value], $type);

Expand Down
36 changes: 32 additions & 4 deletions tests/Connection/ExpandArrayParametersTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
use Doctrine\DBAL\Types\Type;
use PHPUnit\Framework\TestCase;

use function hex2bin;

class ExpandArrayParametersTest extends TestCase
{
/** @return mixed[][] */
Expand Down Expand Up @@ -94,16 +96,24 @@ public static function dataExpandListParameters(): iterable
[1 => ParameterType::STRING, 2 => ParameterType::STRING],
],
'Positional: explicit keys for array params and array types' => [
'SELECT * FROM Foo WHERE foo IN (?) AND bar IN (?) AND baz = ? AND bax IN (?)',
[1 => ['bar1', 'bar2'], 2 => true, 0 => [1, 2, 3], ['bax1', 'bax2']],
'SELECT * FROM Foo WHERE foo IN (?) AND bar IN (?) AND baz = ? AND bax IN (?) AND bay IN (?)',
[
1 => ['bar1', 'bar2'],
2 => true,
0 => [1, 2, 3],
['bax1', 'bax2'],
4 => [hex2bin('DEADBEEF'), hex2bin('C0DEF00D')],
],
[
4 => ArrayParameterType::BINARY,
3 => ArrayParameterType::ASCII,
2 => ParameterType::BOOLEAN,
1 => ArrayParameterType::STRING,
0 => ArrayParameterType::INTEGER,
],
'SELECT * FROM Foo WHERE foo IN (?, ?, ?) AND bar IN (?, ?) AND baz = ? AND bax IN (?, ?)',
[1, 2, 3, 'bar1', 'bar2', true, 'bax1', 'bax2'],
'SELECT * FROM Foo WHERE foo IN (?, ?, ?) AND bar IN (?, ?) AND baz = ? AND bax IN (?, ?) ' .
'AND bay IN (?, ?)',
[1, 2, 3, 'bar1', 'bar2', true, 'bax1', 'bax2', hex2bin('DEADBEEF'), hex2bin('C0DEF00D')],
[
ParameterType::INTEGER,
ParameterType::INTEGER,
Expand All @@ -113,6 +123,8 @@ public static function dataExpandListParameters(): iterable
ParameterType::BOOLEAN,
ParameterType::ASCII,
ParameterType::ASCII,
ParameterType::BINARY,
ParameterType::BINARY,
],
],
'Named: Very simple with param int' => [
Expand Down Expand Up @@ -310,6 +322,22 @@ public static function dataExpandListParameters(): iterable
['foo', 'bar', 'baz'],
[1 => ParameterType::STRING, ParameterType::STRING],
],
'Named: Binary array with explicit types' => [
'SELECT * FROM Foo WHERE foo IN (:foo) OR bar IN (:bar)',
[
'foo' => [hex2bin('DEADBEEF'), hex2bin('C0DEF00D')],
'bar' => [hex2bin('DEADBEEF'), hex2bin('C0DEF00D')],
],
['foo' => ArrayParameterType::BINARY, 'bar' => ArrayParameterType::BINARY],
'SELECT * FROM Foo WHERE foo IN (?, ?) OR bar IN (?, ?)',
[hex2bin('DEADBEEF'), hex2bin('C0DEF00D'), hex2bin('DEADBEEF'), hex2bin('C0DEF00D')],
[
ParameterType::BINARY,
ParameterType::BINARY,
ParameterType::BINARY,
ParameterType::BINARY,
],
],
];
}

Expand Down
Loading

0 comments on commit 4117fec

Please sign in to comment.