From c6bdad1b3dd06c08c60a55a7e208bcb7ca48c2ce Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Thu, 29 Dec 2022 15:40:18 +0100 Subject: [PATCH] Introduce a ArrayParameterType enum --- UPGRADE.md | 7 +++ .../data-retrieval-and-manipulation.rst | 8 +-- src/ArrayParameterType.php | 42 ++++++++++++++++ src/Connection.php | 23 ++++----- src/ExpandArrayParameters.php | 8 +-- .../Connection/ExpandArrayParametersTest.php | 50 +++++++++---------- tests/Functional/DataAccessTest.php | 6 +-- tests/Functional/NamedParametersTest.php | 16 +++--- tests/Query/QueryBuilderTest.php | 24 +++++++++ 9 files changed, 128 insertions(+), 56 deletions(-) create mode 100644 src/ArrayParameterType.php diff --git a/UPGRADE.md b/UPGRADE.md index 9e9d688942c..a2b36587d13 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -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 diff --git a/docs/en/reference/data-retrieval-and-manipulation.rst b/docs/en/reference/data-retrieval-and-manipulation.rst index 23fae97a01d..14179c431b2 100644 --- a/docs/en/reference/data-retrieval-and-manipulation.rst +++ b/docs/en/reference/data-retrieval-and-manipulation.rst @@ -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: @@ -261,7 +261,7 @@ the SQL and flattens the specified values into the set of parameters. Consider o 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 @@ -271,7 +271,7 @@ be specified as well: .. code-block:: php executeQuery('SELECT * FROM articles WHERE id IN (?, ?, ?, ?, ?, ?)', [1, 2, 3, 4, 5, 6], [ diff --git a/src/ArrayParameterType.php b/src/ArrayParameterType.php new file mode 100644 index 00000000000..18e0b44cd87 --- /dev/null +++ b/src/ArrayParameterType.php @@ -0,0 +1,42 @@ +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); @@ -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 */ diff --git a/tests/Connection/ExpandArrayParametersTest.php b/tests/Connection/ExpandArrayParametersTest.php index 784e8d96653..cb2c6c38934 100644 --- a/tests/Connection/ExpandArrayParametersTest.php +++ b/tests/Connection/ExpandArrayParametersTest.php @@ -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; @@ -20,7 +20,7 @@ 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], @@ -28,7 +28,7 @@ public static function dataExpandListParameters(): iterable '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], @@ -36,7 +36,7 @@ public static function dataExpandListParameters(): iterable '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], @@ -44,7 +44,7 @@ public static function dataExpandListParameters(): iterable '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], [ @@ -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], [ @@ -72,7 +72,7 @@ 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)', [], [], @@ -80,7 +80,7 @@ public static function dataExpandListParameters(): iterable '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)', [], [], @@ -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'], @@ -134,7 +134,7 @@ 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], @@ -142,7 +142,7 @@ public static function dataExpandListParameters(): iterable '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], @@ -150,7 +150,7 @@ public static function dataExpandListParameters(): iterable '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], @@ -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, ], @@ -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], [ @@ -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], [ @@ -221,7 +221,7 @@ 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)', [], [], @@ -229,7 +229,7 @@ public static function dataExpandListParameters(): iterable '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)', [], [], @@ -237,7 +237,7 @@ public static function dataExpandListParameters(): iterable [ '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)', [], [], @@ -245,7 +245,7 @@ public static function dataExpandListParameters(): iterable [ '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'], [ @@ -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], @@ -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], @@ -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], ], ]; } diff --git a/tests/Functional/DataAccessTest.php b/tests/Functional/DataAccessTest.php index 682f6df7720..2c1e7a89753 100644 --- a/tests/Functional/DataAccessTest.php +++ b/tests/Functional/DataAccessTest.php @@ -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; @@ -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(); @@ -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(); diff --git a/tests/Functional/NamedParametersTest.php b/tests/Functional/NamedParametersTest.php index e43498fd90a..c8655134252 100644 --- a/tests/Functional/NamedParametersTest.php +++ b/tests/Functional/NamedParametersTest.php @@ -2,7 +2,7 @@ namespace Doctrine\DBAL\Tests\Functional; -use Doctrine\DBAL\Connection; +use Doctrine\DBAL\ArrayParameterType; use Doctrine\DBAL\ParameterType; use Doctrine\DBAL\Schema\Table; use Doctrine\DBAL\Tests\FunctionalTestCase; @@ -26,7 +26,7 @@ public static function ticketProvider(): iterable ], [ 'foo' => ParameterType::INTEGER, - 'bar' => Connection::PARAM_INT_ARRAY, + 'bar' => ArrayParameterType::INTEGER, ], [ ['id' => 1, 'foo' => 1, 'bar' => 1], @@ -42,7 +42,7 @@ public static function ticketProvider(): iterable 'bar' => [1, 2, 3], ], [ - 'bar' => Connection::PARAM_INT_ARRAY, + 'bar' => ArrayParameterType::INTEGER, 'foo' => ParameterType::INTEGER, ], [ @@ -59,7 +59,7 @@ public static function ticketProvider(): iterable 'bar' => [1, 2, 3], ], [ - 'bar' => Connection::PARAM_INT_ARRAY, + 'bar' => ArrayParameterType::INTEGER, 'foo' => ParameterType::INTEGER, ], [ @@ -76,7 +76,7 @@ public static function ticketProvider(): iterable 'bar' => ['1', '2', '3'], ], [ - 'bar' => Connection::PARAM_STR_ARRAY, + 'bar' => ArrayParameterType::STRING, 'foo' => ParameterType::INTEGER, ], [ @@ -93,8 +93,8 @@ public static function ticketProvider(): iterable 'bar' => [1, 2, 3, 4], ], [ - 'bar' => Connection::PARAM_STR_ARRAY, - 'foo' => Connection::PARAM_INT_ARRAY, + 'bar' => ArrayParameterType::STRING, + 'foo' => ArrayParameterType::INTEGER, ], [ ['id' => 1, 'foo' => 1, 'bar' => 1], @@ -136,7 +136,7 @@ public static function ticketProvider(): iterable 'arg' => [1, 2], ], [ - 'arg' => Connection::PARAM_INT_ARRAY, + 'arg' => ArrayParameterType::INTEGER, ], [ ['id' => 3, 'foo' => 1, 'bar' => 3], diff --git a/tests/Query/QueryBuilderTest.php b/tests/Query/QueryBuilderTest.php index afce3009f55..8cbd8052dba 100644 --- a/tests/Query/QueryBuilderTest.php +++ b/tests/Query/QueryBuilderTest.php @@ -2,6 +2,7 @@ namespace Doctrine\DBAL\Tests\Query; +use Doctrine\DBAL\ArrayParameterType; use Doctrine\DBAL\Cache\QueryCacheProfile; use Doctrine\DBAL\Connection; use Doctrine\DBAL\ParameterType; @@ -915,6 +916,29 @@ public function testGetParameterTypes(): void ], $qb->getParameterTypes()); } + public function testArrayParameters(): void + { + $qb = new QueryBuilder($this->conn); + + $qb->select('*')->from('users'); + + self::assertSame([], $qb->getParameterTypes()); + + $qb->where('id IN (:ids)'); + $qb->setParameter('ids', [1, 2, 3], ArrayParameterType::INTEGER); + + $qb->andWhere('name IN (:names)'); + $qb->setParameter('names', ['john', 'jane'], ArrayParameterType::STRING); + + self::assertSame(ArrayParameterType::INTEGER, $qb->getParameterType('ids')); + self::assertSame(ArrayParameterType::STRING, $qb->getParameterType('names')); + + self::assertSame([ + 'ids' => ArrayParameterType::INTEGER, + 'names' => ArrayParameterType::STRING, + ], $qb->getParameterTypes()); + } + public function testJoinWithNonUniqueAliasThrowsException(): void { $qb = new QueryBuilder($this->conn);