Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce a ArrayParameterType enum #5839

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions UPGRADE.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
23 changes: 6 additions & 17 deletions src/ArrayParameterType.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,41 +4,30 @@

namespace Doctrine\DBAL;

use Doctrine\DBAL\ArrayParameters\Exception\InvalidParameterType;

final class ArrayParameterType
enum ArrayParameterType
{
/**
* Represents an array of ints to be expanded by Doctrine SQL parsing.
*/
public const INTEGER = 101;
case INTEGER;

/**
* Represents an array of strings to be expanded by Doctrine SQL parsing.
*/
public const STRING = 102;
case STRING;

/**
* Represents an array of ascii strings to be expanded by Doctrine SQL parsing.
*/
public const ASCII = 117;
case ASCII;

/**
* @internal
*
* @psalm-param self::INTEGER|self::STRING|self::ASCII $type
*/
public static function toElementParameterType(int $type): ParameterType
/** @internal */
public static function toElementParameterType(self $type): ParameterType
{
return match ($type) {
self::INTEGER => ParameterType::INTEGER,
self::STRING => ParameterType::STRING,
self::ASCII => ParameterType::ASCII,
default => throw InvalidParameterType::new($type),
};
}

private function __construct()
{
}
}
11 changes: 6 additions & 5 deletions src/Cache/QueryCacheProfile.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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
{
Expand Down Expand Up @@ -50,9 +51,9 @@ public function getCacheKey(): string
/**
* Generates the real cache key from query, params, types and connection parameters.
*
* @param list<mixed>|array<string, mixed> $params
* @param array<int, int|string|ParameterType|Type>|array<string, int|string|ParameterType|Type> $types
* @param array<string, mixed> $connectionParams
* @param list<mixed>|array<string, mixed> $params
* @param array<string, mixed> $connectionParams
* @psalm-param array<int, WrapperParameterType>|array<string, WrapperParameterType> $types
*
* @return array{string, string}
*/
Expand Down
122 changes: 51 additions & 71 deletions src/Connection.php

Large diffs are not rendered by default.

17 changes: 9 additions & 8 deletions src/ExpandArrayParameters.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -31,11 +31,13 @@ final class ExpandArrayParameters implements Visitor
private array $convertedTypes = [];

/**
* @param array<int, mixed>|array<string, mixed> $parameters
* @param array<int,int|string|ParameterType|Type>|array<string,int|string|ParameterType|Type> $types
* @param array<int, mixed>|array<string, mixed> $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
Expand Down Expand Up @@ -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;
Expand All @@ -102,8 +104,7 @@ private function acceptParameter(int|string $key, mixed $value): void
return;
}

/** @psalm-suppress ArgumentTypeCoercion */
$this->appendTypedParameter($value, ArrayParameterType::toElementParameterType($type)); // @phpstan-ignore-line
$this->appendTypedParameter($value, ArrayParameterType::toElementParameterType($type));
}

/** @return array<int,string|ParameterType|Type> */
Expand Down
9 changes: 4 additions & 5 deletions src/Query.php
Original file line number Diff line number Diff line change
Expand Up @@ -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<mixed> $params
* @param array<int|string|ParameterType|Type> $types
* @param array<mixed> $params
* @psalm-param array<WrapperParameterType> $types
*
* @psalm-suppress ImpurePropertyAssignment
*/
Expand All @@ -37,7 +36,7 @@ public function getParams(): array
return $this->params;
}

/** @return array<int|string|ParameterType|Type> */
/** @psalm-return array<WrapperParameterType> */
public function getTypes(): array
{
return $this->types;
Expand Down
28 changes: 13 additions & 15 deletions src/Query/QueryBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -35,6 +35,8 @@
* 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 WrapperParameterTypeArray from Connection
*/
class QueryBuilder
{
Expand All @@ -48,12 +50,12 @@ class QueryBuilder
*
* @var list<mixed>|array<string, mixed>
*/
private $params = [];
private array $params = [];

/**
* The parameter type map of this query.
*
* @var array<int, int|string|ParameterType|Type>|array<string, int|string|ParameterType|Type>
* @psalm-var WrapperParameterTypeArray
*/
private array $types = [];

Expand Down Expand Up @@ -345,16 +347,14 @@ public function getSQL(): string
* ->setParameter('user_id', 1);
* </code>
*
* @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
*
* @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;
Expand All @@ -376,8 +376,8 @@ public function setParameter(
* ));
* </code>
*
* @param list<mixed>|array<string, mixed> $params
* @param array<int, int|string|ParameterType|Type>|array<string, int|string|ParameterType|Type> $types
* @param list<mixed>|array<string, mixed> $params
* @psalm-param WrapperParameterTypeArray $types
*
* @return $this This QueryBuilder instance.
*/
Expand Down Expand Up @@ -414,7 +414,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<int, int|string|ParameterType|Type>|array<string, int|string|ParameterType|Type>
* @psalm-return WrapperParameterTypeArray
*/
public function getParameterTypes(): array
{
Expand All @@ -425,10 +425,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;
}
Expand Down Expand Up @@ -1311,7 +1309,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) {
Expand Down Expand Up @@ -1343,7 +1341,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++;
Expand Down
43 changes: 30 additions & 13 deletions tests/Connection/ExpandArrayParametersTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,26 @@
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;
use Doctrine\DBAL\SQL\Parser;
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{
* string,
* array<string, mixed>|array<int, mixed>,
* WrapperParameterTypeArray,
* string,
* array<string, mixed>|array<int, mixed>,
* array<string, string|Type|ParameterType>|array<int, string|Type|ParameterType>,
* }>
*/
public static function dataExpandListParameters(): iterable
{
return [
Expand Down Expand Up @@ -316,10 +327,10 @@ public static function dataExpandListParameters(): iterable
}

/**
* @param array<int, mixed>|array<string, mixed> $params
* @param array<int, int|string|Type>|array<string, int|string|Type> $types
* @param list<mixed> $expectedParams
* @param array<int,Type|int|string> $expectedTypes
* @param array<int, mixed>|array<string, mixed> $params
* @param array<int, mixed>|array<string, mixed> $expectedParams
* @param array<int, string|Type|ParameterType>|array<string, string|Type|ParameterType> $expectedTypes
* @psalm-param WrapperParameterTypeArray $types
*
* @dataProvider dataExpandListParameters
*/
Expand All @@ -338,7 +349,13 @@ public function testExpandListParameters(
self::assertEquals($expectedTypes, $types, 'Types dont match');
}

/** @return mixed[][] */
/**
* @return list<array{
* string,
* array<string, mixed>,
* array<string, ArrayParameterType>
* }>
*/
public static function missingNamedParameterProvider(): iterable
{
return [
Expand Down Expand Up @@ -366,8 +383,8 @@ public static function missingNamedParameterProvider(): iterable
}

/**
* @param array<int, mixed>|array<string, mixed> $params
* @param array<int, int|string|Type>|array<string, int|string|Type> $types
* @param array<string, mixed> $params
* @param array<string, ArrayParameterType> $types
*
* @dataProvider missingNamedParameterProvider
*/
Expand All @@ -379,7 +396,7 @@ public function testMissingNamedParameter(string $query, array $params, array $t
}

/**
* @param array<int, mixed>|array<string, mixed> $params
* @param list<mixed> $params
*
* @dataProvider missingPositionalParameterProvider
*/
Expand All @@ -390,7 +407,7 @@ public function testMissingPositionalParameter(string $query, array $params): vo
$this->expandArrayParameters($query, $params, []);
}

/** @return mixed[][] */
/** @return iterable<string, array{string, list<mixed>}> */
public static function missingPositionalParameterProvider(): iterable
{
return [
Expand All @@ -406,10 +423,10 @@ public static function missingPositionalParameterProvider(): iterable
}

/**
* @param array<int, mixed>|array<string, mixed> $params
* @param array<int, int|string|Type>|array<string, int|string|Type> $types
* @param array<int, mixed>|array<string, mixed> $params
* @psalm-param WrapperParameterTypeArray $types
*
* @return array{string, list<mixed>, array<int,string|ParameterType|Type>}
* @return array{string, list<mixed>, array<string|ParameterType|Type>}
*/
private function expandArrayParameters(string $sql, array $params, array $types): array
{
Expand Down
Loading