Skip to content

Commit

Permalink
Merge pull request #5838 from derrabus/improvement/array-parameter-type
Browse files Browse the repository at this point in the history
Introduce a `ArrayParameterType` enum
  • Loading branch information
derrabus authored Dec 29, 2022
2 parents 63e513c + c6bdad1 commit 7e0d352
Show file tree
Hide file tree
Showing 9 changed files with 128 additions and 56 deletions.
7 changes: 7 additions & 0 deletions UPGRADE.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ awareness about deprecated code.
- Use of our low-overhead runtime deprecation API, details:
https://github.com/doctrine/deprecations/

# Upgrade to 3.6

## Deprecated `Connection::PARAM_*_ARRAY` constants

Use the corresponding constants on `ArrayParameterType` instead. Please be aware that
`ArrayParameterType` will be a native enum type in DBAL 4.

# Upgrade to 3.5

## Deprecated extension via Doctrine Event Manager
Expand Down
8 changes: 4 additions & 4 deletions docs/en/reference/data-retrieval-and-manipulation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -250,8 +250,8 @@ 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:

- ``\Doctrine\DBAL\Connection::PARAM_INT_ARRAY``
- ``\Doctrine\DBAL\Connection::PARAM_STR_ARRAY``
- ``\Doctrine\DBAL\ArrayParameterType::INTEGER``
- ``\Doctrine\DBAL\ArrayParameterType::STRING``

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 All @@ -261,7 +261,7 @@ the SQL and flattens the specified values into the set of parameters. Consider o
<?php
$stmt = $conn->executeQuery('SELECT * FROM articles WHERE id IN (?)',
[[1, 2, 3, 4, 5, 6]],
[\Doctrine\DBAL\Connection::PARAM_INT_ARRAY]
[\Doctrine\DBAL\ArrayParameterType::INTEGER]
);
The SQL statement passed to ``Connection#executeQuery`` is not the one actually passed to the
Expand All @@ -271,7 +271,7 @@ be specified as well:
.. code-block:: php
<?php
// Same SQL WITHOUT usage of Doctrine\DBAL\Connection::PARAM_INT_ARRAY
// Same SQL WITHOUT usage of Doctrine\DBAL\ArrayParameterType::INTEGER
$stmt = $conn->executeQuery('SELECT * FROM articles WHERE id IN (?, ?, ?, ?, ?, ?)',
[1, 2, 3, 4, 5, 6],
[
Expand Down
42 changes: 42 additions & 0 deletions src/ArrayParameterType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

namespace Doctrine\DBAL;

final class ArrayParameterType
{
/**
* Represents an array of ints to be expanded by Doctrine SQL parsing.
*/
public const INTEGER = ParameterType::INTEGER + self::ARRAY_PARAM_OFFSET;

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

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

/**
* Offset by which PARAM_* constants are detected as arrays of the param type.
*/
private const ARRAY_PARAM_OFFSET = 100;

/**
* @internal
*
* @psalm-param self::INTEGER|self::STRING|self::ASCII $type
*
* @psalm-return ParameterType::INTEGER|ParameterType::STRING|ParameterType::ASCII
*/
public static function toElementParameterType(int $type): int
{
return $type - self::ARRAY_PARAM_OFFSET;
}

private function __construct()
{
}
}
23 changes: 11 additions & 12 deletions src/Connection.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,25 +50,24 @@ class Connection
{
/**
* Represents an array of ints to be expanded by Doctrine SQL parsing.
*
* @deprecated Use {@see ArrayParameterType::INTEGER} instead.
*/
public const PARAM_INT_ARRAY = ParameterType::INTEGER + self::ARRAY_PARAM_OFFSET;
public const PARAM_INT_ARRAY = ArrayParameterType::INTEGER;

/**
* Represents an array of strings to be expanded by Doctrine SQL parsing.
*
* @deprecated Use {@see ArrayParameterType::STRING} instead.
*/
public const PARAM_STR_ARRAY = ParameterType::STRING + self::ARRAY_PARAM_OFFSET;
public const PARAM_STR_ARRAY = ArrayParameterType::STRING;

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

/**
* Offset by which PARAM_* constants are detected as arrays of the param type.
*
* @internal Should be used only within the wrapper layer.
* @deprecated Use {@see ArrayParameterType::ASCII} instead.
*/
public const ARRAY_PARAM_OFFSET = 100;
public const PARAM_ASCII_STR_ARRAY = ArrayParameterType::ASCII;

/**
* The wrapped driver connection.
Expand Down Expand Up @@ -1888,9 +1887,9 @@ private function needsArrayParameterConversion(array $params, array $types): boo

foreach ($types as $type) {
if (
$type === self::PARAM_INT_ARRAY
|| $type === self::PARAM_STR_ARRAY
|| $type === self::PARAM_ASCII_STR_ARRAY
$type === ArrayParameterType::INTEGER
|| $type === ArrayParameterType::STRING
|| $type === ArrayParameterType::ASCII
) {
return true;
}
Expand Down
8 changes: 4 additions & 4 deletions src/ExpandArrayParameters.php
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,9 @@ private function acceptParameter($key, $value): void
$type = $this->originalTypes[$key];

if (
$type !== Connection::PARAM_INT_ARRAY
&& $type !== Connection::PARAM_STR_ARRAY
&& $type !== Connection::PARAM_ASCII_STR_ARRAY
$type !== ArrayParameterType::INTEGER
&& $type !== ArrayParameterType::STRING
&& $type !== ArrayParameterType::ASCII
) {
$this->appendTypedParameter([$value], $type);

Expand All @@ -113,7 +113,7 @@ private function acceptParameter($key, $value): void
return;
}

$this->appendTypedParameter($value, $type - Connection::ARRAY_PARAM_OFFSET);
$this->appendTypedParameter($value, ArrayParameterType::toElementParameterType($type));
}

/** @return array<int,Type|int|string|null> */
Expand Down
50 changes: 25 additions & 25 deletions tests/Connection/ExpandArrayParametersTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

use Doctrine\DBAL\ArrayParameters\Exception\MissingNamedParameter;
use Doctrine\DBAL\ArrayParameters\Exception\MissingPositionalParameter;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\ArrayParameterType;
use Doctrine\DBAL\ExpandArrayParameters;
use Doctrine\DBAL\ParameterType;
use Doctrine\DBAL\SQL\Parser;
Expand All @@ -20,31 +20,31 @@ public static function dataExpandListParameters(): iterable
'Positional: Very simple with one needle' => [
'SELECT * FROM Foo WHERE foo IN (?)',
[[1, 2, 3]],
[Connection::PARAM_INT_ARRAY],
[ArrayParameterType::INTEGER],
'SELECT * FROM Foo WHERE foo IN (?, ?, ?)',
[1, 2, 3],
[ParameterType::INTEGER, ParameterType::INTEGER, ParameterType::INTEGER],
],
'Positional: One non-list before d one after list-needle' => [
'SELECT * FROM Foo WHERE foo = ? AND bar IN (?)',
['string', [1, 2, 3]],
[ParameterType::STRING, Connection::PARAM_INT_ARRAY],
[ParameterType::STRING, ArrayParameterType::INTEGER],
'SELECT * FROM Foo WHERE foo = ? AND bar IN (?, ?, ?)',
['string', 1, 2, 3],
[ParameterType::STRING, ParameterType::INTEGER, ParameterType::INTEGER, ParameterType::INTEGER],
],
'Positional: One non-list after list-needle' => [
'SELECT * FROM Foo WHERE bar IN (?) AND baz = ?',
[[1, 2, 3], 'foo'],
[Connection::PARAM_INT_ARRAY, ParameterType::STRING],
[ArrayParameterType::INTEGER, ParameterType::STRING],
'SELECT * FROM Foo WHERE bar IN (?, ?, ?) AND baz = ?',
[1, 2, 3, 'foo'],
[ParameterType::INTEGER, ParameterType::INTEGER, ParameterType::INTEGER, ParameterType::STRING],
],
'Positional: One non-list before and one after list-needle' => [
'SELECT * FROM Foo WHERE foo = ? AND bar IN (?) AND baz = ?',
[1, [1, 2, 3], 4],
[ParameterType::INTEGER, Connection::PARAM_INT_ARRAY, ParameterType::INTEGER],
[ParameterType::INTEGER, ArrayParameterType::INTEGER, ParameterType::INTEGER],
'SELECT * FROM Foo WHERE foo = ? AND bar IN (?, ?, ?) AND baz = ?',
[1, 1, 2, 3, 4],
[
Expand All @@ -58,7 +58,7 @@ public static function dataExpandListParameters(): iterable
'Positional: Two lists' => [
'SELECT * FROM Foo WHERE foo IN (?, ?)',
[[1, 2, 3], [4, 5]],
[Connection::PARAM_INT_ARRAY, Connection::PARAM_INT_ARRAY],
[ArrayParameterType::INTEGER, ArrayParameterType::INTEGER],
'SELECT * FROM Foo WHERE foo IN (?, ?, ?, ?, ?)',
[1, 2, 3, 4, 5],
[
Expand All @@ -72,15 +72,15 @@ public static function dataExpandListParameters(): iterable
'Positional: Empty "integer" array (DDC-1978)' => [
'SELECT * FROM Foo WHERE foo IN (?)',
[[]],
[Connection::PARAM_INT_ARRAY],
[ArrayParameterType::INTEGER],
'SELECT * FROM Foo WHERE foo IN (NULL)',
[],
[],
],
'Positional: Empty "str" array (DDC-1978)' => [
'SELECT * FROM Foo WHERE foo IN (?)',
[[]],
[Connection::PARAM_STR_ARRAY],
[ArrayParameterType::STRING],
'SELECT * FROM Foo WHERE foo IN (NULL)',
[],
[],
Expand All @@ -97,10 +97,10 @@ public static function dataExpandListParameters(): iterable
'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']],
[
3 => Connection::PARAM_ASCII_STR_ARRAY,
3 => ArrayParameterType::ASCII,
2 => ParameterType::BOOLEAN,
1 => Connection::PARAM_STR_ARRAY,
0 => Connection::PARAM_INT_ARRAY,
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'],
Expand Down Expand Up @@ -134,23 +134,23 @@ public static function dataExpandListParameters(): iterable
'Named: Very simple with one needle' => [
'SELECT * FROM Foo WHERE foo IN (:foo)',
['foo' => [1, 2, 3]],
['foo' => Connection::PARAM_INT_ARRAY],
['foo' => ArrayParameterType::INTEGER],
'SELECT * FROM Foo WHERE foo IN (?, ?, ?)',
[1, 2, 3],
[ParameterType::INTEGER, ParameterType::INTEGER, ParameterType::INTEGER],
],
'Named: One non-list before d one after list-needle' => [
'SELECT * FROM Foo WHERE foo = :foo AND bar IN (:bar)',
['foo' => 'string', 'bar' => [1, 2, 3]],
['foo' => ParameterType::STRING, 'bar' => Connection::PARAM_INT_ARRAY],
['foo' => ParameterType::STRING, 'bar' => ArrayParameterType::INTEGER],
'SELECT * FROM Foo WHERE foo = ? AND bar IN (?, ?, ?)',
['string', 1, 2, 3],
[ParameterType::STRING, ParameterType::INTEGER, ParameterType::INTEGER, ParameterType::INTEGER],
],
'Named: One non-list after list-needle' => [
'SELECT * FROM Foo WHERE bar IN (:bar) AND baz = :baz',
['bar' => [1, 2, 3], 'baz' => 'foo'],
['bar' => Connection::PARAM_INT_ARRAY, 'baz' => ParameterType::STRING],
['bar' => ArrayParameterType::INTEGER, 'baz' => ParameterType::STRING],
'SELECT * FROM Foo WHERE bar IN (?, ?, ?) AND baz = ?',
[1, 2, 3, 'foo'],
[ParameterType::INTEGER, ParameterType::INTEGER, ParameterType::INTEGER, ParameterType::STRING],
Expand All @@ -159,7 +159,7 @@ public static function dataExpandListParameters(): iterable
'SELECT * FROM Foo WHERE foo = :foo AND bar IN (:bar) AND baz = :baz',
['bar' => [1, 2, 3],'foo' => 1, 'baz' => 4],
[
'bar' => Connection::PARAM_INT_ARRAY,
'bar' => ArrayParameterType::INTEGER,
'foo' => ParameterType::INTEGER,
'baz' => ParameterType::INTEGER,
],
Expand All @@ -176,7 +176,7 @@ public static function dataExpandListParameters(): iterable
'Named: Two lists' => [
'SELECT * FROM Foo WHERE foo IN (:a, :b)',
['b' => [4, 5],'a' => [1, 2, 3]],
['a' => Connection::PARAM_INT_ARRAY, 'b' => Connection::PARAM_INT_ARRAY],
['a' => ArrayParameterType::INTEGER, 'b' => ArrayParameterType::INTEGER],
'SELECT * FROM Foo WHERE foo IN (?, ?, ?, ?, ?)',
[1, 2, 3, 4, 5],
[
Expand All @@ -198,7 +198,7 @@ public static function dataExpandListParameters(): iterable
'Named: With the same name arg' => [
'SELECT * FROM Foo WHERE foo IN (:arg) AND NOT bar IN (:arg)',
['arg' => [1, 2, 3]],
['arg' => Connection::PARAM_INT_ARRAY],
['arg' => ArrayParameterType::INTEGER],
'SELECT * FROM Foo WHERE foo IN (?, ?, ?) AND NOT bar IN (?, ?, ?)',
[1, 2, 3, 1, 2, 3],
[
Expand All @@ -221,31 +221,31 @@ public static function dataExpandListParameters(): iterable
'Named: Empty "integer" array (DDC-1978)' => [
'SELECT * FROM Foo WHERE foo IN (:foo)',
['foo' => []],
['foo' => Connection::PARAM_INT_ARRAY],
['foo' => ArrayParameterType::INTEGER],
'SELECT * FROM Foo WHERE foo IN (NULL)',
[],
[],
],
'Named: Two empty "str" array (DDC-1978)' => [
'SELECT * FROM Foo WHERE foo IN (:foo) OR bar IN (:bar)',
['foo' => [], 'bar' => []],
['foo' => Connection::PARAM_STR_ARRAY, 'bar' => Connection::PARAM_STR_ARRAY],
['foo' => ArrayParameterType::STRING, 'bar' => ArrayParameterType::STRING],
'SELECT * FROM Foo WHERE foo IN (NULL) OR bar IN (NULL)',
[],
[],
],
[
'SELECT * FROM Foo WHERE foo IN (:foo) OR bar IN (:bar)',
['foo' => [], 'bar' => []],
['foo' => Connection::PARAM_ASCII_STR_ARRAY, 'bar' => Connection::PARAM_ASCII_STR_ARRAY],
['foo' => ArrayParameterType::ASCII, 'bar' => ArrayParameterType::ASCII],
'SELECT * FROM Foo WHERE foo IN (NULL) OR bar IN (NULL)',
[],
[],
],
[
'SELECT * FROM Foo WHERE foo IN (:foo) OR bar = :bar OR baz = :baz',
['foo' => [1, 2], 'bar' => 'bar', 'baz' => 'baz'],
['foo' => Connection::PARAM_INT_ARRAY, 'baz' => 'string'],
['foo' => ArrayParameterType::INTEGER, 'baz' => 'string'],
'SELECT * FROM Foo WHERE foo IN (?, ?) OR bar = ? OR baz = ?',
[1, 2, 'bar', 'baz'],
[
Expand All @@ -257,7 +257,7 @@ public static function dataExpandListParameters(): iterable
[
'SELECT * FROM Foo WHERE foo IN (:foo) OR bar = :bar',
['foo' => [1, 2], 'bar' => 'bar'],
['foo' => Connection::PARAM_INT_ARRAY],
['foo' => ArrayParameterType::INTEGER],
'SELECT * FROM Foo WHERE foo IN (?, ?) OR bar = ?',
[1, 2, 'bar'],
[ParameterType::INTEGER, ParameterType::INTEGER],
Expand Down Expand Up @@ -305,7 +305,7 @@ public static function dataExpandListParameters(): iterable
[
'SELECT NULL FROM dummy WHERE ? IN (?)',
['foo', ['bar', 'baz']],
[1 => Connection::PARAM_STR_ARRAY],
[1 => ArrayParameterType::STRING],
'SELECT NULL FROM dummy WHERE ? IN (?, ?)',
['foo', 'bar', 'baz'],
[1 => ParameterType::STRING, ParameterType::STRING],
Expand Down Expand Up @@ -353,12 +353,12 @@ public static function missingNamedParameterProvider(): iterable
[
'SELECT * FROM foo WHERE bar = :param',
[],
['bar' => Connection::PARAM_INT_ARRAY],
['bar' => ArrayParameterType::INTEGER],
],
[
'SELECT * FROM foo WHERE bar = :param',
['bar' => 'value'],
['bar' => Connection::PARAM_INT_ARRAY],
['bar' => ArrayParameterType::INTEGER],
],
];
}
Expand Down
6 changes: 3 additions & 3 deletions tests/Functional/DataAccessTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace Doctrine\DBAL\Tests\Functional;

use DateTime;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\ArrayParameterType;
use Doctrine\DBAL\ParameterType;
use Doctrine\DBAL\Platforms\SqlitePlatform;
use Doctrine\DBAL\Platforms\TrimMode;
Expand Down Expand Up @@ -306,7 +306,7 @@ public function testNativeArrayListSupport(): void
$result = $this->connection->executeQuery(
'SELECT test_int FROM fetch_table WHERE test_int IN (?)',
[[100, 101, 102, 103, 104]],
[Connection::PARAM_INT_ARRAY],
[ArrayParameterType::INTEGER],
);

$data = $result->fetchAllNumeric();
Expand All @@ -316,7 +316,7 @@ public function testNativeArrayListSupport(): void
$result = $this->connection->executeQuery(
'SELECT test_int FROM fetch_table WHERE test_string IN (?)',
[['foo100', 'foo101', 'foo102', 'foo103', 'foo104']],
[Connection::PARAM_STR_ARRAY],
[ArrayParameterType::STRING],
);

$data = $result->fetchAllNumeric();
Expand Down
Loading

0 comments on commit 7e0d352

Please sign in to comment.