diff --git a/src/Types/BigIntType.php b/src/Types/BigIntType.php index 77bcea65988..e2206257275 100644 --- a/src/Types/BigIntType.php +++ b/src/Types/BigIntType.php @@ -10,9 +10,10 @@ use function assert; use function is_int; use function is_string; - -use const PHP_INT_MAX; -use const PHP_INT_MIN; +use function preg_replace; +use function rtrim; +use function strpos; +use function substr; /** * Type that attempts to map a database BIGINT to a PHP int. @@ -47,18 +48,21 @@ public function convertToPHPValue(mixed $value, AbstractPlatform $platform): int return $value; } - if ( - ($value > PHP_INT_MIN && $value < PHP_INT_MAX) - || $value === (string) (int) $value - ) { - return (int) $value; - } - assert( is_string($value), 'DBAL assumes values outside of the integer range to be returned as string by the database driver.', ); + // workaround https://github.com/php/php-src/issues/14345 + $dotPos = strpos($value, '.'); + if ($dotPos !== false && rtrim(substr($value, $dotPos + 1), '0') === '') { + $value = substr($value, 0, $dotPos); + } + + if (preg_replace('~^(\+|-(?=0+$))|(?<=^|^[+\-])0+(?=\d$)~', '', $value) === (string) (int) $value) { + return (int) $value; + } + return $value; } } diff --git a/tests/Functional/Types/BigIntTypeTest.php b/tests/Functional/Types/BigIntTypeTest.php index d07f480df20..3789db4dd30 100644 --- a/tests/Functional/Types/BigIntTypeTest.php +++ b/tests/Functional/Types/BigIntTypeTest.php @@ -11,6 +11,9 @@ use Generator; use PHPUnit\Framework\Attributes\DataProvider; +use function str_starts_with; +use function substr; + use const PHP_INT_MAX; use const PHP_INT_MIN; use const PHP_INT_SIZE; @@ -38,6 +41,30 @@ public function testSelectBigInt(string $sqlLiteral, int|string|null $expectedVa Types::BIGINT, ), ); + + if ($expectedValue === null) { + return; + } + + self::assertSame( + $expectedValue, + $this->connection->convertToPHPValue( + $sqlLiteral . '.00', + Types::BIGINT, + ), + ); + + $startsWithSign = str_starts_with($sqlLiteral, '-') || str_starts_with($sqlLiteral, '+'); + + self::assertSame( + $expectedValue, + $this->connection->convertToPHPValue( + ($startsWithSign ? substr($sqlLiteral, 0, 1) : '') + . '00' + . ($startsWithSign ? substr($sqlLiteral, 1) : $sqlLiteral), + Types::BIGINT, + ), + ); } /** @return Generator */ @@ -53,6 +80,11 @@ public static function provideBigIntLiterals(): Generator 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]; + + yield 'plus largest positive number' => [ + PHP_INT_SIZE === 4 ? '+2147483647' : '+9223372036854775807', + PHP_INT_MAX, + ]; } public function testUnsignedBigIntOnMySQL(): void