diff --git a/UPGRADE.md b/UPGRADE.md index 04db4a8abfa..ff780860156 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -8,6 +8,10 @@ awareness about deprecated code. # Upgrade to 4.0 +## Removed `Connection::PARAM_*_ARRAY` constants + +Use the enum `ArrayParameterType` instead. + ## Disallowed partial version numbers in ``serverVersion`` The ``serverVersion`` connection parameter must consist of 3 numbers: @@ -853,6 +857,13 @@ The following methods have been removed. | `QueryCacheProfile` | `setResultCacheDriver()` | `setResultCache()` | | `QueryCacheProfile` | `getResultCacheDriver()` | `getResultCache()` | +# 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/src/ArrayParameterType.php b/src/ArrayParameterType.php new file mode 100644 index 00000000000..6e3877746d2 --- /dev/null +++ b/src/ArrayParameterType.php @@ -0,0 +1,33 @@ + ParameterType::INTEGER, + self::STRING => ParameterType::STRING, + self::ASCII => ParameterType::ASCII, + }; + } +} diff --git a/src/Cache/QueryCacheProfile.php b/src/Cache/QueryCacheProfile.php index 07a804d5926..b085f6cab0a 100644 --- a/src/Cache/QueryCacheProfile.php +++ b/src/Cache/QueryCacheProfile.php @@ -5,8 +5,7 @@ namespace Doctrine\DBAL\Cache; use Doctrine\DBAL\Cache\Exception\NoCacheKey; -use Doctrine\DBAL\ParameterType; -use Doctrine\DBAL\Types\Type; +use Doctrine\DBAL\Connection; use Psr\Cache\CacheItemPoolInterface; use function hash; @@ -17,6 +16,8 @@ * Query Cache Profile handles the data relevant for query caching. * * It is a value object, setter methods return NEW instances. + * + * @psalm-import-type WrapperParameterType from Connection */ class QueryCacheProfile { @@ -50,9 +51,9 @@ public function getCacheKey(): string /** * Generates the real cache key from query, params, types and connection parameters. * - * @param list|array $params - * @param array|array $types - * @param array $connectionParams + * @param list|array $params + * @param array $connectionParams + * @psalm-param array|array $types * * @return array{string, string} */ diff --git a/src/Connection.php b/src/Connection.php index d3ebcea929d..b703cdd4801 100644 --- a/src/Connection.php +++ b/src/Connection.php @@ -43,25 +43,12 @@ * configuration, emulated transaction nesting, lazy connecting and more. * * @psalm-import-type Params from DriverManager + * @psalm-type WrapperParameterType = string|Type|ParameterType|ArrayParameterType + * @psalm-type WrapperParameterTypeArray = array|array * @psalm-consistent-constructor */ class Connection implements ServerVersionProvider { - /** - * Represents an array of integers to be expanded by Doctrine SQL parsing. - */ - final public const PARAM_INT_ARRAY = 101; - - /** - * Represents an array of strings to be expanded by Doctrine SQL parsing. - */ - final public const PARAM_STR_ARRAY = 102; - - /** - * Represents an array of ascii strings to be expanded by Doctrine SQL parsing. - */ - final public const PARAM_ASCII_STR_ARRAY = 117; - /** * The wrapped driver connection. */ @@ -284,8 +271,8 @@ public function setAutoCommit(bool $autoCommit): void * Prepares and executes an SQL query and returns the first row of the result * as an associative array. * - * @param list|array $params - * @param array|array $types + * @param list|array $params + * @psalm-param WrapperParameterTypeArray $types * * @return array|false False is returned if no rows are found. * @@ -300,8 +287,8 @@ public function fetchAssociative(string $query, array $params = [], array $types * Prepares and executes an SQL query and returns the first row of the result * as a numerically indexed array. * - * @param list|array $params - * @param array|array $types + * @param list|array $params + * @psalm-param WrapperParameterTypeArray $types * * @return list|false False is returned if no rows are found. * @@ -316,8 +303,8 @@ public function fetchNumeric(string $query, array $params = [], array $types = [ * Prepares and executes an SQL query and returns the value of a single column * of the first row of the result. * - * @param list|array $params - * @param array|array $types + * @param list|array $params + * @psalm-param WrapperParameterTypeArray $types * * @return mixed|false False is returned if no rows are found. * @@ -379,8 +366,8 @@ private function addCriteriaCondition( * * Table expression and columns are not escaped and are not safe for user-input. * - * @param array $criteria - * @param array|array $types + * @param array $criteria + * @param array|array $types * * @return int|string The number of affected rows. * @@ -445,9 +432,9 @@ public function getTransactionIsolation(): TransactionIsolationLevel * * Table expression and columns are not escaped and are not safe for user-input. * - * @param array $data - * @param array $criteria - * @param array|array $types + * @param array $data + * @param array $criteria + * @param array|array $types * * @return int|string The number of affected rows. * @@ -483,8 +470,8 @@ public function update(string $table, array $data, array $criteria = [], array $ * * Table expression and columns are not escaped and are not safe for user-input. * - * @param array $data - * @param array|array $types + * @param array $data + * @param array|array $types * * @return int|string The number of affected rows. * @@ -517,10 +504,10 @@ public function insert(string $table, array $data, array $types = []): int|strin /** * Extract ordered type list from an ordered column list and type map. * - * @param array $columns - * @param array|array $types + * @param array $columns + * @param array|array $types * - * @return array|array + * @return array|array */ private function extractTypeValues(array $columns, array $types): array { @@ -564,8 +551,8 @@ public function quote(string $value): string /** * Prepares and executes an SQL query and returns the result as an array of numeric arrays. * - * @param list|array $params - * @param array|array $types + * @param list|array $params + * @psalm-param WrapperParameterTypeArray $types * * @return list> * @@ -579,8 +566,8 @@ public function fetchAllNumeric(string $query, array $params = [], array $types /** * Prepares and executes an SQL query and returns the result as an array of associative arrays. * - * @param list|array $params - * @param array|array $types + * @param list|array $params + * @psalm-param WrapperParameterTypeArray $types * * @return list> * @@ -595,8 +582,8 @@ public function fetchAllAssociative(string $query, array $params = [], array $ty * Prepares and executes an SQL query and returns the result as an associative array with the keys * mapped to the first column and the values mapped to the second column. * - * @param list|array $params - * @param array|array $types + * @param list|array $params + * @psalm-param WrapperParameterTypeArray $types * * @return array * @@ -612,8 +599,8 @@ public function fetchAllKeyValue(string $query, array $params = [], array $types * to the first column and the values being an associative array representing the rest of the columns * and their values. * - * @param list|array $params - * @param array|array $types + * @param list|array $params + * @psalm-param WrapperParameterTypeArray $types * * @return array> * @@ -627,8 +614,8 @@ public function fetchAllAssociativeIndexed(string $query, array $params = [], ar /** * Prepares and executes an SQL query and returns the result as an array of the first column values. * - * @param list|array $params - * @param array|array $types + * @param list|array $params + * @psalm-param WrapperParameterTypeArray $types * * @return list * @@ -642,8 +629,8 @@ public function fetchFirstColumn(string $query, array $params = [], array $types /** * Prepares and executes an SQL query and returns the result as an iterator over rows represented as numeric arrays. * - * @param list|array $params - * @param array|array $types + * @param list|array $params + * @psalm-param WrapperParameterTypeArray $types * * @return Traversable> * @@ -658,8 +645,8 @@ public function iterateNumeric(string $query, array $params = [], array $types = * Prepares and executes an SQL query and returns the result as an iterator over rows represented * as associative arrays. * - * @param list|array $params - * @param array|array $types + * @param list|array $params + * @psalm-param WrapperParameterTypeArray $types * * @return Traversable> * @@ -674,8 +661,8 @@ public function iterateAssociative(string $query, array $params = [], array $typ * Prepares and executes an SQL query and returns the result as an iterator with the keys * mapped to the first column and the values mapped to the second column. * - * @param list|array $params - * @param array|array $types + * @param list|array $params + * @psalm-param WrapperParameterTypeArray $types * * @return Traversable * @@ -691,9 +678,8 @@ public function iterateKeyValue(string $query, array $params = [], array $types * to the first column and the values being an associative array representing the rest of the columns * and their values. * - * @param string $query SQL query - * @param list|array $params - * @param array|array $types + * @param list|array $params + * @psalm-param WrapperParameterTypeArray $types * * @return Traversable> * @@ -707,8 +693,8 @@ public function iterateAssociativeIndexed(string $query, array $params = [], arr /** * Prepares and executes an SQL query and returns the result as an iterator over the first column values. * - * @param list|array $params - * @param array|array $types + * @param list|array $params + * @psalm-param WrapperParameterTypeArray $types * * @return Traversable * @@ -744,8 +730,8 @@ public function prepare(string $sql): Statement * * If the query is parametrized, a prepared statement is used. * - * @param list|array $params - * @param array|array $types + * @param list|array $params + * @psalm-param WrapperParameterTypeArray $types * * @throws Exception */ @@ -783,8 +769,8 @@ public function executeQuery( /** * Executes a caching query. * - * @param list|array $params - * @param array|array $types + * @param list|array $params + * @psalm-param WrapperParameterTypeArray $types * * @throws CacheException * @throws Exception @@ -838,8 +824,8 @@ public function executeCacheQuery(string $sql, array $params, array $types, Quer * * This method supports PDO binding types as well as DBAL mapping types. * - * @param list|array $params - * @param array|array $types + * @param list|array $params + * @psalm-param WrapperParameterTypeArray $types * * @throws Exception */ @@ -1290,8 +1276,8 @@ public function createQueryBuilder(): QueryBuilder /** * @internal * - * @param list|array $params - * @param array|array $types + * @param list|array $params + * @psalm-param WrapperParameterTypeArray $types */ final public function convertExceptionDuringQuery( Driver\Exception $e, @@ -1309,8 +1295,8 @@ final public function convertException(Driver\Exception $e): DriverException } /** - * @param array|array $params - * @param array|array $types + * @param array|array $params + * @psalm-param WrapperParameterTypeArray $types * * @return array{ * string, @@ -1327,7 +1313,7 @@ private function expandArrayParameters(string $sql, array $params, array $types) $needsConversion = true; } else { foreach ($types as $key => $type) { - if (is_int($type)) { + if ($type instanceof ArrayParameterType) { $needsConversion = true; break; } @@ -1371,8 +1357,8 @@ private function handleDriverException( * * @deprecated This API is deprecated and will be removed after 2022 * - * @param array|array $params - * @param array|array $types + * @param array|array $params + * @psalm-param WrapperParameterTypeArray $types * * @throws Exception */ diff --git a/src/ExpandArrayParameters.php b/src/ExpandArrayParameters.php index 7062eda12d2..0efd3fd5f7f 100644 --- a/src/ExpandArrayParameters.php +++ b/src/ExpandArrayParameters.php @@ -14,9 +14,9 @@ use function array_key_exists; use function count; use function implode; -use function is_int; use function substr; +/** @psalm-import-type WrapperParameterTypeArray from Connection */ final class ExpandArrayParameters implements Visitor { private int $originalParameterIndex = 0; @@ -31,11 +31,13 @@ final class ExpandArrayParameters implements Visitor private array $convertedTypes = []; /** - * @param array|array $parameters - * @param array|array $types + * @param array|array $parameters + * @psalm-param WrapperParameterTypeArray $types */ - public function __construct(private readonly array $parameters, private readonly array $types) - { + public function __construct( + private readonly array $parameters, + private readonly array $types, + ) { } public function acceptPositionalParameter(string $sql): void @@ -90,7 +92,7 @@ private function acceptParameter(int|string $key, mixed $value): void $type = $this->types[$key]; - if (! is_int($type)) { + if (! $type instanceof ArrayParameterType) { $this->appendTypedParameter([$value], $type); return; @@ -102,12 +104,7 @@ private function acceptParameter(int|string $key, mixed $value): void return; } - $this->appendTypedParameter($value, match ($type) { - Connection::PARAM_INT_ARRAY => ParameterType::INTEGER, - Connection::PARAM_STR_ARRAY => ParameterType::STRING, - Connection::PARAM_ASCII_STR_ARRAY => ParameterType::ASCII, - default => throw InvalidParameterType::new($type), - }); + $this->appendTypedParameter($value, ArrayParameterType::toElementParameterType($type)); } /** @return array */ diff --git a/src/Query.php b/src/Query.php index ee89fbdb35f..b673ba889df 100644 --- a/src/Query.php +++ b/src/Query.php @@ -4,18 +4,17 @@ namespace Doctrine\DBAL; -use Doctrine\DBAL\Types\Type; - /** * An SQL query together with its bound parameters. * * @psalm-immutable + * @psalm-import-type WrapperParameterType from Connection */ final class Query { /** - * @param array $params - * @param array $types + * @param array $params + * @psalm-param array $types * * @psalm-suppress ImpurePropertyAssignment */ @@ -37,7 +36,7 @@ public function getParams(): array return $this->params; } - /** @return array */ + /** @psalm-return array */ public function getTypes(): array { return $this->types; diff --git a/src/Query/QueryBuilder.php b/src/Query/QueryBuilder.php index 6ea28cd6ec8..65df44a7ac6 100644 --- a/src/Query/QueryBuilder.php +++ b/src/Query/QueryBuilder.php @@ -4,6 +4,7 @@ namespace Doctrine\DBAL\Query; +use Doctrine\DBAL\ArrayParameterType; use Doctrine\DBAL\Cache\QueryCacheProfile; use Doctrine\DBAL\Connection; use Doctrine\DBAL\Exception; @@ -15,7 +16,6 @@ use Doctrine\DBAL\Result; use Doctrine\DBAL\Statement; use Doctrine\DBAL\Types\Type; -use Doctrine\Deprecations\Deprecation; use function array_key_exists; use function array_keys; @@ -35,6 +35,9 @@ * The query builder does no validation whatsoever if certain features even work with the * underlying database vendor. Limit queries and joins are NOT applied to UPDATE and DELETE statements * even if some vendors such as MySQL support it. + * + * @psalm-import-type WrapperParameterType from Connection + * @psalm-import-type WrapperParameterTypeArray from Connection */ class QueryBuilder { @@ -53,7 +56,7 @@ class QueryBuilder /** * The parameter type map of this query. * - * @var array|array + * @psalm-var WrapperParameterTypeArray */ private array $types = []; @@ -345,16 +348,16 @@ public function getSQL(): string * ->setParameter('user_id', 1); * * - * @param int|string $key Parameter position or name - * @param mixed $value Parameter value - * @param string|ParameterType|Type $type Parameter type + * @param int|string $key Parameter position or name + * @param mixed $value Parameter value + * @psalm-param WrapperParameterType $type Parameter type * * @return $this This QueryBuilder instance. */ public function setParameter( int|string $key, mixed $value, - string|ParameterType|Type $type = ParameterType::STRING, + string|ParameterType|Type|ArrayParameterType $type = ParameterType::STRING, ): self { $this->params[$key] = $value; $this->types[$key] = $type; @@ -376,8 +379,8 @@ public function setParameter( * )); * * - * @param list|array $params - * @param array|array $types + * @param list|array $params + * @psalm-param WrapperParameterTypeArray $types * * @return $this This QueryBuilder instance. */ @@ -414,7 +417,7 @@ public function getParameter(string|int $key): mixed /** * Gets all defined query parameter types for the query being constructed indexed by parameter index or name. * - * @return array|array + * @psalm-return WrapperParameterTypeArray */ public function getParameterTypes(): array { @@ -425,10 +428,8 @@ public function getParameterTypes(): array * Gets a (previously set) query parameter type of the query being constructed. * * @param int|string $key The key of the bound parameter type - * - * @return int|string|ParameterType|Type The value of the bound parameter type */ - public function getParameterType(int|string $key): int|string|ParameterType|Type + public function getParameterType(int|string $key): string|ParameterType|Type|ArrayParameterType { return $this->types[$key] ?? ParameterType::STRING; } @@ -1311,7 +1312,7 @@ public function __toString(): string */ public function createNamedParameter( mixed $value, - string|ParameterType|Type $type = ParameterType::STRING, + string|ParameterType|Type|ArrayParameterType $type = ParameterType::STRING, ?string $placeHolder = null, ): string { if ($placeHolder === null) { @@ -1343,7 +1344,7 @@ public function createNamedParameter( */ public function createPositionalParameter( mixed $value, - string|ParameterType|Type $type = ParameterType::STRING, + string|ParameterType|Type|ArrayParameterType $type = ParameterType::STRING, ): string { $this->setParameter($this->boundCounter, $value, $type); $this->boundCounter++; diff --git a/tests/Connection/ExpandArrayParametersTest.php b/tests/Connection/ExpandArrayParametersTest.php index fca6c84c08f..27e7c330c72 100644 --- a/tests/Connection/ExpandArrayParametersTest.php +++ b/tests/Connection/ExpandArrayParametersTest.php @@ -6,6 +6,7 @@ use Doctrine\DBAL\ArrayParameters\Exception\MissingNamedParameter; use Doctrine\DBAL\ArrayParameters\Exception\MissingPositionalParameter; +use Doctrine\DBAL\ArrayParameterType; use Doctrine\DBAL\Connection; use Doctrine\DBAL\ExpandArrayParameters; use Doctrine\DBAL\ParameterType; @@ -13,16 +14,26 @@ use Doctrine\DBAL\Types\Type; use PHPUnit\Framework\TestCase; +/** @psalm-import-type WrapperParameterTypeArray from Connection */ class ExpandArrayParametersTest extends TestCase { - /** @return mixed[][] */ + /** + * @psalm-return iterable|array, + * WrapperParameterTypeArray, + * string, + * array|array, + * array|array, + * }> + */ public static function dataExpandListParameters(): iterable { return [ '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], @@ -30,7 +41,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], @@ -38,7 +49,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], @@ -46,7 +57,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], [ @@ -60,7 +71,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], [ @@ -74,7 +85,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)', [], [], @@ -82,7 +93,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)', [], [], @@ -99,10 +110,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'], @@ -136,7 +147,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], @@ -144,7 +155,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], @@ -152,7 +163,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], @@ -161,7 +172,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, ], @@ -178,7 +189,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], [ @@ -200,7 +211,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], [ @@ -223,7 +234,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)', [], [], @@ -231,7 +242,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)', [], [], @@ -239,7 +250,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)', [], [], @@ -247,7 +258,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'], [ @@ -259,7 +270,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], @@ -307,7 +318,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], @@ -316,10 +327,10 @@ public static function dataExpandListParameters(): iterable } /** - * @param array|array $params - * @param array|array $types - * @param list $expectedParams - * @param array $expectedTypes + * @param array|array $params + * @param array|array $expectedParams + * @param array|array $expectedTypes + * @psalm-param WrapperParameterTypeArray $types * * @dataProvider dataExpandListParameters */ @@ -338,7 +349,13 @@ public function testExpandListParameters( self::assertEquals($expectedTypes, $types, 'Types dont match'); } - /** @return mixed[][] */ + /** + * @return list, + * array + * }> + */ public static function missingNamedParameterProvider(): iterable { return [ @@ -355,19 +372,19 @@ 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], ], ]; } /** - * @param array|array $params - * @param array|array $types + * @param array $params + * @param array $types * * @dataProvider missingNamedParameterProvider */ @@ -379,7 +396,7 @@ public function testMissingNamedParameter(string $query, array $params, array $t } /** - * @param array|array $params + * @param list $params * * @dataProvider missingPositionalParameterProvider */ @@ -390,7 +407,7 @@ public function testMissingPositionalParameter(string $query, array $params): vo $this->expandArrayParameters($query, $params, []); } - /** @return mixed[][] */ + /** @return iterable}> */ public static function missingPositionalParameterProvider(): iterable { return [ @@ -406,10 +423,10 @@ public static function missingPositionalParameterProvider(): iterable } /** - * @param array|array $params - * @param array|array $types + * @param array|array $params + * @psalm-param WrapperParameterTypeArray $types * - * @return array{string, list, array} + * @return array{string, list, array} */ private function expandArrayParameters(string $sql, array $params, array $types): array { diff --git a/tests/Functional/DataAccessTest.php b/tests/Functional/DataAccessTest.php index 5a7fd403490..47bc5c323fa 100644 --- a/tests/Functional/DataAccessTest.php +++ b/tests/Functional/DataAccessTest.php @@ -5,7 +5,7 @@ namespace Doctrine\DBAL\Tests\Functional; use DateTime; -use Doctrine\DBAL\Connection; +use Doctrine\DBAL\ArrayParameterType; use Doctrine\DBAL\ParameterType; use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Platforms\SQLitePlatform; @@ -275,7 +275,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(); @@ -285,7 +285,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 cff5346792f..c7f5732f6a0 100644 --- a/tests/Functional/NamedParametersTest.php +++ b/tests/Functional/NamedParametersTest.php @@ -4,6 +4,7 @@ namespace Doctrine\DBAL\Tests\Functional; +use Doctrine\DBAL\ArrayParameterType; use Doctrine\DBAL\Connection; use Doctrine\DBAL\ParameterType; use Doctrine\DBAL\Schema\Table; @@ -14,9 +15,17 @@ use const CASE_LOWER; +/** @psalm-import-type WrapperParameterType from Connection */ class NamedParametersTest extends FunctionalTestCase { - /** @return iterable> */ + /** + * @psalm-return iterable, + * array, + * list>, + * }> + */ public static function ticketProvider(): iterable { return [ @@ -28,7 +37,7 @@ public static function ticketProvider(): iterable ], [ 'foo' => ParameterType::INTEGER, - 'bar' => Connection::PARAM_INT_ARRAY, + 'bar' => ArrayParameterType::INTEGER, ], [ ['id' => 1, 'foo' => 1, 'bar' => 1], @@ -44,7 +53,7 @@ public static function ticketProvider(): iterable 'bar' => [1, 2, 3], ], [ - 'bar' => Connection::PARAM_INT_ARRAY, + 'bar' => ArrayParameterType::INTEGER, 'foo' => ParameterType::INTEGER, ], [ @@ -61,7 +70,7 @@ public static function ticketProvider(): iterable 'bar' => [1, 2, 3], ], [ - 'bar' => Connection::PARAM_INT_ARRAY, + 'bar' => ArrayParameterType::INTEGER, 'foo' => ParameterType::INTEGER, ], [ @@ -78,7 +87,7 @@ public static function ticketProvider(): iterable 'bar' => ['1', '2', '3'], ], [ - 'bar' => Connection::PARAM_STR_ARRAY, + 'bar' => ArrayParameterType::STRING, 'foo' => ParameterType::INTEGER, ], [ @@ -95,8 +104,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], @@ -138,7 +147,7 @@ public static function ticketProvider(): iterable 'arg' => [1, 2], ], [ - 'arg' => Connection::PARAM_INT_ARRAY, + 'arg' => ArrayParameterType::INTEGER, ], [ ['id' => 3, 'foo' => 1, 'bar' => 3], @@ -200,9 +209,9 @@ protected function setUp(): void } /** - * @param mixed[] $params - * @param int[] $types - * @param int[] $expected + * @param array $params + * @param list> $expected + * @psalm-param array $types * * @dataProvider ticketProvider */ diff --git a/tests/Query/QueryBuilderTest.php b/tests/Query/QueryBuilderTest.php index 3988bbaa794..0153f7f4820 100644 --- a/tests/Query/QueryBuilderTest.php +++ b/tests/Query/QueryBuilderTest.php @@ -4,6 +4,7 @@ namespace Doctrine\DBAL\Tests\Query; +use Doctrine\DBAL\ArrayParameterType; use Doctrine\DBAL\Cache\QueryCacheProfile; use Doctrine\DBAL\Connection; use Doctrine\DBAL\ParameterType; @@ -11,11 +12,11 @@ use Doctrine\DBAL\Query\QueryBuilder; use Doctrine\DBAL\Query\QueryException; use Doctrine\DBAL\Result; -use Doctrine\DBAL\Types\Type; use Doctrine\DBAL\Types\Types; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; +/** @psalm-import-type WrapperParameterTypeArray from Connection */ class QueryBuilderTest extends TestCase { /** @var Connection&MockObject */ @@ -799,6 +800,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); @@ -816,8 +840,8 @@ public function testJoinWithNonUniqueAliasThrowsException(): void } /** - * @param list|array $parameters - * @param array|array $parameterTypes + * @param list|array $parameters + * @psalm-param WrapperParameterTypeArray $parameterTypes * * @dataProvider fetchProvider */ @@ -851,8 +875,8 @@ public function testFetchAssociative( } /** - * @param list|array $parameters - * @param array|array $parameterTypes + * @param list|array $parameters + * @psalm-param WrapperParameterTypeArray $parameterTypes * * @dataProvider fetchProvider */ @@ -886,8 +910,8 @@ public function testFetchNumeric( } /** - * @param list|array $parameters - * @param array|array $parameterTypes + * @param list|array $parameters + * @param WrapperParameterTypeArray $parameterTypes * * @dataProvider fetchProvider */ @@ -921,8 +945,8 @@ public function testFetchOne( } /** - * @param list|array $parameters - * @param array|array $parameterTypes + * @param list|array $parameters + * @psalm-param WrapperParameterTypeArray $parameterTypes * * @dataProvider fetchProvider */ @@ -967,8 +991,8 @@ public function testFetchAllAssociative( } /** - * @param list|array $parameters - * @param array|array $parameterTypes + * @param list|array $parameters + * @psalm-param WrapperParameterTypeArray $parameterTypes * * @dataProvider fetchProvider */ @@ -1013,8 +1037,8 @@ public function testFetchAllNumeric( } /** - * @param list|array $parameters - * @param array|array $parameterTypes + * @param list|array $parameters + * @psalm-param WrapperParameterTypeArray $parameterTypes * * @dataProvider fetchProvider */ @@ -1059,8 +1083,8 @@ public function testFetchAllKeyValue( } /** - * @param list|array $parameters - * @param array|array $parameterTypes + * @param list|array $parameters + * @psalm-param WrapperParameterTypeArray $parameterTypes * * @dataProvider fetchProvider */ @@ -1109,8 +1133,8 @@ public function testFetchAllAssociativeIndexed( } /** - * @param list|array $parameters - * @param array|array $parameterTypes + * @param list|array $parameters + * @psalm-param WrapperParameterTypeArray $parameterTypes * * @dataProvider fetchProvider */ @@ -1155,14 +1179,14 @@ public function testFetchFirstColumn( } /** - * @return iterable< + * @psalm-return iterable< * string, * array{ * string, * string, * string, * list|array, - * array|array, + * WrapperParameterTypeArray, * string * }> */ @@ -1206,8 +1230,8 @@ public static function fetchProvider(): iterable } /** - * @param list|array $params - * @param array|array $types + * @param list|array $params + * @psalm-param WrapperParameterTypeArray $types * * @dataProvider fetchProvider */ @@ -1240,8 +1264,8 @@ public function testExecuteQuery( } /** - * @param list|array $parameters - * @param array|array $parameterTypes + * @param list|array $parameters + * @psalm-param WrapperParameterTypeArray $parameterTypes * * @dataProvider fetchProvider */