Skip to content

Commit

Permalink
Merge branch '3.3.x' into 4.0.x
Browse files Browse the repository at this point in the history
* 3.3.x:
  PHPStan 1.4.0
  PHPStan 1.4.0
  Remove parsing server version from the mysqli driver
  Fix coding style errors
  Implement requested changes. Change assert equals to same and revert back testJsonStringConvertsToPHPValue method.
  Fix JSON Dbal type to properly encode whole number float values, preserving zero fractions.
  Adding the constant PARAM_ASCII_ARRAY to Doctrine\DBAL\Connection
  Enforce consistent constructor in dynamically instantiated classes
  Bump to 2.13.8-dev
  Release 2.13.7
  Remove trailing comma
  Document $lockMode value range
  Remove assets used for testing Dumper
  • Loading branch information
derrabus committed Jan 17, 2022
2 parents 27a7c5b + e839cec commit 07c7297
Show file tree
Hide file tree
Showing 16 changed files with 84 additions and 124 deletions.
2 changes: 1 addition & 1 deletion composer.json
Expand Up @@ -41,7 +41,7 @@
"require-dev": {
"doctrine/coding-standard": "9.0.0",
"jetbrains/phpstorm-stubs": "2021.1",
"phpstan/phpstan": "1.3.0",
"phpstan/phpstan": "1.4.0",
"phpstan/phpstan-phpunit": "1.0.0",
"phpstan/phpstan-strict-rules": "1.1.0",
"phpunit/phpunit": "9.5.11",
Expand Down
56 changes: 11 additions & 45 deletions phpstan.neon.dist
Expand Up @@ -8,16 +8,6 @@ parameters:
checkMissingIterableValueType: false
checkGenericClassInNonGenericObjectType: false
ignoreErrors:
# Requires a release of https://github.com/JetBrains/phpstorm-stubs/pull/553
-
message: '~^Call to function assert\(\) with true will always evaluate to true\.$~'
path: src/Driver/PDO/Connection.php

# Requires a release of https://github.com/JetBrains/phpstorm-stubs/pull/923
-
message: '~^Instanceof between PDOStatement and PDOStatement will always evaluate to true\.$~'
path: src/Driver/PDO/Connection.php

# Requires a release of https://github.com/JetBrains/phpstorm-stubs/pull/1158
-
message: '~^Strict comparison using === between string and null will always evaluate to false\.$~'
Expand Down Expand Up @@ -50,26 +40,8 @@ parameters:
-
message: '~^Variable method call on .*~'
paths:
- src/Schema/AbstractSchemaManager.php
- src/Schema/Column.php

# Temporaily suppressed during up-merging an upgrade to PHPStan 0.12.33
-
message: '~^Parameter #1 \$expected of static method PHPUnit\\Framework\\Assert::assertInstanceOf\(\) expects class-string<Doctrine\\DBAL\\Connection&PHPUnit\\Framework\\MockObject\\MockObject>, class-string<Doctrine\\DBAL\\Connection>&class-string<PHPUnit\\Framework\\MockObject\\MockObject> given\.$~'
path: %currentWorkingDirectory%/tests/DriverManagerTest.php

# Unlike Psalm, PHPStan doesn't understand the shape of the parse_str() return value
-
message: '~^Parameter #1 \$scheme of static method Doctrine\\DBAL\\DriverManager::parseDatabaseUrlScheme\(\) expects string\|null, int\|string\|null given\.$~'
paths:
- src/DriverManager.php

# https://github.com/phpstan/phpstan-src/pull/692
-
message: '~^Parameter #2 \$count of function array_fill expects int<0, max>, int given\.~'
paths:
- %currentWorkingDirectory%/src/Driver/Mysqli/Statement.php

# TODO: remove this once the support for PHP 7 is dropped
-
message: '~^Strict comparison using !== between int and false will always evaluate to true\.$~'
Expand All @@ -83,7 +55,7 @@ parameters:
-
message: '~Template type T of method Doctrine\\DBAL\\DriverManager::getConnection\(\) is not referenced in a parameter\.~'
paths:
- src/DriverManager.ph
- src/DriverManager.php

-
message: '~Method Doctrine\\DBAL\\DriverManager::createDriver\(\) should return Doctrine\\DBAL\\Driver but returns object\.~'
Expand All @@ -101,35 +73,29 @@ parameters:
paths:
- src/Driver/Mysqli/Result.php

-
message: '~Method Doctrine\\DBAL\\Driver\\Mysqli\\Connection::exec\(\) should return int but returns int\|string\.~'
paths:
- src/Driver/Mysqli/Connection.php

# Requires a release of https://github.com/phpstan/phpstan-src/pull/719
-
message: '~Strict comparison using === between non-empty-string and false will always evaluate to false\.~'
path: src/Driver/PDO/Connection.php

# The schema manager isn't initialized if the test is skipped
-
message: '~Strict comparison using === between Doctrine\\DBAL\\Schema\\AbstractSchemaManager and null will always evaluate to false\.~'
path: tests/Functional/Schema/SchemaManagerFunctionalTestCase.php

# Removing the (int) cast will make Psalm unhappy.
-
message: '~^Parameter #1 \$message of class Doctrine\\DBAL\\Driver\\Mysqli\\Exception\\ConnectionFailed constructor expects string, string\|null given\.$~'
message: '~^Casting to int something that''s already int\.$~'
paths:
- src/Driver/Mysqli/Exception/ConnectionError.php
- src/Driver/Mysqli/Exception/ConnectionFailed.php
- src/Driver/Mysqli/Exception/InvalidCharset.php
- src/Driver/Mysqli/Exception/StatementError.php

-
message: '~^Cannot use array destructuring on array\|null\.$~'
message: '~^Unable to resolve the template type T in call to method Doctrine\\DBAL\\Portability\\Converter\:\:compose\(\)$~'
paths:
- src/Driver/PDO/Connection.php
- src/Portability/Converter.php

# These properties are accessed via var_dump()
# We're testing with invalid input.
-
message: '~Property Doctrine\\DBAL\\Tests\\Tools\\TestAsset\\.*::\$.* is never read, only written\.~'
path: tests/Tools/TestAsset/*.php
message: '~^Parameter #2 \$lockMode of method Doctrine\\DBAL\\Platforms\\AbstractPlatform\:\:appendLockHint\(\) expects 0\|1\|2\|4, 128 given\.$~'
path: tests/Platforms/AbstractPlatformTestCase.php

includes:
- vendor/phpstan/phpstan-phpunit/extension.neon
Expand Down
12 changes: 6 additions & 6 deletions psalm.xml.dist
Expand Up @@ -107,6 +107,12 @@
<file name="src/Driver/OCI8/Connection.php"/>
</errorLevel>
</ImplementedReturnTypeMismatch>
<InvalidArgument>
<errorLevel type="suppress">
<!-- We're testing with invalid input here. -->
<file name="tests/Platforms/AbstractPlatformTestCase.php"/>
</errorLevel>
</InvalidArgument>
<InvalidDocblock>
<errorLevel type="suppress">
<!-- See https://github.com/vimeo/psalm/issues/5472 -->
Expand Down Expand Up @@ -196,12 +202,6 @@
<referencedClass name="Doctrine\DBAL\Portability\T"/>
</errorLevel>
</UndefinedDocblockClass>
<UnsafeInstantiation>
<errorLevel type="suppress">
<!-- See https://github.com/doctrine/dbal/issues/4511 -->
<file name="src/DriverManager.php"/>
</errorLevel>
</UnsafeInstantiation>
<InvalidReturnType>
<errorLevel type="suppress">
<!-- lastInsertId has a return type that does not match the one defined in the interface-->
Expand Down
12 changes: 11 additions & 1 deletion src/Connection.php
Expand Up @@ -46,6 +46,7 @@
* configuration, emulated transaction nesting, lazy connecting and more.
*
* @psalm-import-type Params from DriverManager
* @psalm-consistent-constructor
*/
class Connection implements ServerVersionProvider
{
Expand All @@ -59,6 +60,11 @@ class Connection implements ServerVersionProvider
*/
public const PARAM_STR_ARRAY = ParameterType::STRING + self::ARRAY_PARAM_OFFSET;

/**
* 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.
*/
Expand Down Expand Up @@ -1453,7 +1459,11 @@ private function needsArrayParameterConversion(array $params, array $types): boo
}

foreach ($types as $type) {
if ($type === self::PARAM_INT_ARRAY || $type === self::PARAM_STR_ARRAY) {
if (
$type === self::PARAM_INT_ARRAY
|| $type === self::PARAM_STR_ARRAY
|| $type === self::PARAM_ASCII_STR_ARRAY
) {
return true;
}
}
Expand Down
22 changes: 1 addition & 21 deletions src/Driver/Mysqli/Connection.php
Expand Up @@ -10,9 +10,6 @@
use mysqli;
use mysqli_sql_exception;

use function floor;
use function stripos;

final class Connection implements ConnectionInterface
{
/**
Expand All @@ -30,26 +27,9 @@ public function __construct(mysqli $connection)
$this->connection = $connection;
}

/**
* {@inheritdoc}
*
* The server version detection includes a special case for MariaDB
* to support '5.5.5-' prefixed versions introduced in Maria 10+
*
* @link https://jira.mariadb.org/browse/MDEV-4088
*/
public function getServerVersion(): string
{
$serverInfos = $this->connection->get_server_info();
if (stripos($serverInfos, 'mariadb') !== false) {
return $serverInfos;
}

$majorVersion = floor($this->connection->server_version / 10000);
$minorVersion = floor(($this->connection->server_version - $majorVersion * 10000) / 100);
$patchVersion = floor($this->connection->server_version - $majorVersion * 10000 - $minorVersion * 100);

return $majorVersion . '.' . $minorVersion . '.' . $patchVersion;
return $this->connection->get_server_info();
}

public function prepare(string $sql): Statement
Expand Down
2 changes: 1 addition & 1 deletion src/Driver/PDO/PgSQL/Driver.php
Expand Up @@ -28,7 +28,7 @@ public function connect(array $params): Connection
$this->constructPdoDsn($params),
$params['user'] ?? '',
$params['password'] ?? '',
$driverOptions,
$driverOptions
);
} catch (PDOException $exception) {
throw Exception::new($exception);
Expand Down
6 changes: 5 additions & 1 deletion src/ExpandArrayParameters.php
Expand Up @@ -97,7 +97,11 @@ private function acceptParameter(int|string $key, mixed $value): void

$type = $this->originalTypes[$key];

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

return;
Expand Down
1 change: 1 addition & 0 deletions src/Platforms/AbstractPlatform.php
Expand Up @@ -776,6 +776,7 @@ public function getForUpdateSQL(): string
*
* @param string $fromClause The FROM clause to append the hint for the given lock mode to
* @param int $lockMode One of the Doctrine\DBAL\LockMode::* constants
* @psalm-param LockMode::* $lockMode
*/
public function appendLockHint(string $fromClause, int $lockMode): string
{
Expand Down
2 changes: 2 additions & 0 deletions src/Platforms/Keywords/KeywordList.php
Expand Up @@ -10,6 +10,8 @@

/**
* Abstract interface for a SQL reserved keyword dictionary.
*
* @psalm-consistent-constructor
*/
abstract class KeywordList
{
Expand Down
3 changes: 2 additions & 1 deletion src/Types/JsonType.php
Expand Up @@ -14,6 +14,7 @@
use function json_encode;
use function stream_get_contents;

use const JSON_PRESERVE_ZERO_FRACTION;
use const JSON_THROW_ON_ERROR;

/**
Expand All @@ -36,7 +37,7 @@ public function convertToDatabaseValue(mixed $value, AbstractPlatform $platform)
}

try {
return json_encode($value, JSON_THROW_ON_ERROR);
return json_encode($value, JSON_THROW_ON_ERROR | JSON_PRESERVE_ZERO_FRACTION);
} catch (JsonException $e) {
throw SerializationFailed::new($value, 'json', $e->getMessage(), $e);
}
Expand Down
25 changes: 20 additions & 5 deletions tests/Connection/ExpandArrayParametersTest.php
Expand Up @@ -98,18 +98,25 @@ 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 = ?',
[1 => ['bar1', 'bar2'], 2 => true, 0 => [1, 2, 3]],
[2 => ParameterType::BOOLEAN, 1 => Connection::PARAM_STR_ARRAY, 0 => Connection::PARAM_INT_ARRAY],
'SELECT * FROM Foo WHERE foo IN (?, ?, ?) AND bar IN (?, ?) AND baz = ?',
[1, 2, 3, 'bar1', 'bar2', true],
'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,
2 => ParameterType::BOOLEAN,
1 => Connection::PARAM_STR_ARRAY,
0 => Connection::PARAM_INT_ARRAY,
],
'SELECT * FROM Foo WHERE foo IN (?, ?, ?) AND bar IN (?, ?) AND baz = ? AND bax IN (?, ?)',
[1, 2, 3, 'bar1', 'bar2', true, 'bax1', 'bax2'],
[
ParameterType::INTEGER,
ParameterType::INTEGER,
ParameterType::INTEGER,
ParameterType::STRING,
ParameterType::STRING,
ParameterType::BOOLEAN,
ParameterType::ASCII,
ParameterType::ASCII,
],
],
'Named: Very simple with param int' => [
Expand Down Expand Up @@ -231,6 +238,14 @@ 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],
'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'],
Expand Down
2 changes: 2 additions & 0 deletions tests/Platforms/SQLServerPlatformTestCase.php
Expand Up @@ -1776,6 +1776,8 @@ public function testAlterTableWithSchemaSameColumnComments(): void
}

/**
* @psalm-param LockMode::* $lockMode
*
* @dataProvider getLockHints
*/
public function testAppendsLockHint(int $lockMode, string $lockHint): void
Expand Down
14 changes: 0 additions & 14 deletions tests/Tools/TestAsset/ChildClass.php

This file was deleted.

14 changes: 0 additions & 14 deletions tests/Tools/TestAsset/ChildWithSameAttributesClass.php

This file was deleted.

14 changes: 0 additions & 14 deletions tests/Tools/TestAsset/ParentClass.php

This file was deleted.

21 changes: 21 additions & 0 deletions tests/Types/JsonTest.php
Expand Up @@ -100,6 +100,27 @@ public function testRequiresSQLCommentHint(): void
self::assertTrue($this->type->requiresSQLCommentHint($this->platform));
}

public function testPHPNullValueConvertsToJsonNull(): void
{
self::assertNull($this->type->convertToDatabaseValue(null, $this->platform));
}

public function testPHPValueConvertsToJsonString(): void
{
$source = ['foo' => 'bar', 'bar' => 'foo'];
$databaseValue = $this->type->convertToDatabaseValue($source, $this->platform);

self::assertSame('{"foo":"bar","bar":"foo"}', $databaseValue);
}

public function testPHPFloatValueConvertsToJsonString(): void
{
$source = ['foo' => 11.4, 'bar' => 10.0];
$databaseValue = $this->type->convertToDatabaseValue($source, $this->platform);

self::assertSame('{"foo":11.4,"bar":10.0}', $databaseValue);
}

public function testSerializationFailure(): void
{
$object = (object) [];
Expand Down

0 comments on commit 07c7297

Please sign in to comment.