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

Fix bigint PHP_INT_MIN/PHP_INT_MAX string to int convert #6410

Open
wants to merge 7 commits into
base: 4.2.x
Choose a base branch
from
Open
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
11 changes: 7 additions & 4 deletions src/Types/BigIntType.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,18 @@
return $value;
}

if ($value > PHP_INT_MIN && $value < PHP_INT_MAX) {
return (int) $value;
}
derrabus marked this conversation as resolved.
Show resolved Hide resolved

assert(
is_string($value),
'DBAL assumes values outside of the integer range to be returned as string by the database driver.',
);

if (
($value > PHP_INT_MIN && $value < PHP_INT_MAX)
|| $value === (string) (int) $value

Check failure on line 57 in src/Types/BigIntType.php

View workflow job for this annotation

GitHub Actions / Static Analysis with Psalm (8.3)

TypeDoesNotContainType

src/Types/BigIntType.php:57:16: TypeDoesNotContainType: Type never for $value is never =string(1) (see https://psalm.dev/056)

Check failure on line 57 in src/Types/BigIntType.php

View workflow job for this annotation

GitHub Actions / Static Analysis with Psalm (8.3)

InvalidCast

src/Types/BigIntType.php:57:42: InvalidCast: never cannot be cast to int (see https://psalm.dev/103)
) {
return (int) $value;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

psalm is wrong here - vimeo/psalm#10995

tell me how to fix the CI

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@greg0ire any advice how to fix the psalm CI?

}

return $value;

Check failure on line 62 in src/Types/BigIntType.php

View workflow job for this annotation

GitHub Actions / Static Analysis with Psalm (8.3)

NoValue

src/Types/BigIntType.php:62:9: NoValue: All possible types for this return were invalidated - This may be dead code (see https://psalm.dev/179)
}
}
52 changes: 8 additions & 44 deletions tests/Functional/Types/BigIntTypeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@
use Doctrine\DBAL\Types\Types;
use Generator;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Constraint\IsIdentical;
use PHPUnit\Framework\Constraint\LogicalOr;

use const PHP_INT_MAX;
use const PHP_INT_MIN;
Expand All @@ -30,13 +28,13 @@ public function testSelectBigInt(string $sqlLiteral, int|string|null $expectedVa

$this->connection->executeStatement(<<<SQL
INSERT INTO bigint_type_test (id, my_integer)
VALUES (42, $sqlLiteral)
VALUES (1, $sqlLiteral)
SQL);

self::assertSame(
$expectedValue,
$this->connection->convertToPHPValue(
$this->connection->fetchOne('SELECT my_integer from bigint_type_test WHERE id = 42'),
$this->connection->fetchOne('SELECT my_integer from bigint_type_test'),
Types::BIGINT,
),
);
Expand All @@ -49,44 +47,10 @@ public static function provideBigIntLiterals(): Generator
yield 'null' => ['null', null];
yield 'positive number' => ['42', 42];
yield 'negative number' => ['-42', -42];

if (PHP_INT_SIZE < 8) {
// The following tests only work on 64bit systems.
return;
}

yield 'large positive number' => ['9223372036854775806', PHP_INT_MAX - 1];
yield 'large negative number' => ['-9223372036854775807', PHP_INT_MIN + 1];
}

#[DataProvider('provideBigIntEdgeLiterals')]
public function testSelectBigIntEdge(int $value): void
{
$table = new Table('bigint_type_test');
$table->addColumn('id', Types::SMALLINT, ['notnull' => true]);
$table->addColumn('my_integer', Types::BIGINT, ['notnull' => false]);
$table->setPrimaryKey(['id']);
$this->dropAndCreateTable($table);

$this->connection->executeStatement(<<<SQL
INSERT INTO bigint_type_test (id, my_integer)
VALUES (42, $value)
SQL);

self::assertThat(
$this->connection->convertToPHPValue(
$this->connection->fetchOne('SELECT my_integer from bigint_type_test WHERE id = 42'),
Types::BIGINT,
),
LogicalOr::fromConstraints(new IsIdentical($value), new IsIdentical((string) $value)),
);
}

/** @return Generator<string, array{int}> */
public static function provideBigIntEdgeLiterals(): Generator
{
yield 'max int' => [PHP_INT_MAX];
yield 'min int' => [PHP_INT_MIN];
yield 'large positive number' => [PHP_INT_SIZE === 4 ? '2147483646' : '9223372036854775806', PHP_INT_MAX - 1];
yield 'large negative number' => [PHP_INT_SIZE === 4 ? '-2147483647' : '-9223372036854775807', PHP_INT_MIN + 1];
yield 'largest positive number' => [PHP_INT_SIZE === 4 ? '2147483647' : '9223372036854775807', PHP_INT_MAX];
yield 'largest negative number' => [PHP_INT_SIZE === 4 ? '-2147483648' : '-9223372036854775808', PHP_INT_MIN];
}

public function testUnsignedBigIntOnMySQL(): void
Expand All @@ -104,13 +68,13 @@ public function testUnsignedBigIntOnMySQL(): void
// Insert (2 ** 64) - 1
$this->connection->executeStatement(<<<'SQL'
INSERT INTO bigint_type_test (id, my_integer)
VALUES (42, 0xFFFFFFFFFFFFFFFF)
VALUES (1, 0xFFFFFFFFFFFFFFFF)
SQL);

self::assertSame(
'18446744073709551615',
$this->connection->convertToPHPValue(
$this->connection->fetchOne('SELECT my_integer from bigint_type_test WHERE id = 42'),
$this->connection->fetchOne('SELECT my_integer from bigint_type_test'),
Types::BIGINT,
),
);
Expand Down
Loading