Skip to content

Commit 4c3258b

Browse files
committed
Unify impl. for whole int range
1 parent dcbddf3 commit 4c3258b

File tree

2 files changed

+46
-10
lines changed

2 files changed

+46
-10
lines changed

src/Types/BigIntType.php

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@
1010
use function assert;
1111
use function is_int;
1212
use function is_string;
13-
14-
use const PHP_INT_MAX;
15-
use const PHP_INT_MIN;
13+
use function preg_replace;
14+
use function rtrim;
15+
use function strpos;
16+
use function substr;
1617

1718
/**
1819
* Type that attempts to map a database BIGINT to a PHP int.
@@ -47,18 +48,21 @@ public function convertToPHPValue(mixed $value, AbstractPlatform $platform): int
4748
return $value;
4849
}
4950

50-
if (
51-
($value > PHP_INT_MIN && $value < PHP_INT_MAX)
52-
|| $value === (string) (int) $value
53-
) {
54-
return (int) $value;
55-
}
56-
5751
assert(
5852
is_string($value),
5953
'DBAL assumes values outside of the integer range to be returned as string by the database driver.',
6054
);
6155

56+
// workaround https://github.com/php/php-src/issues/14345
57+
$dotPos = strpos($value, '.');
58+
if ($dotPos !== false && rtrim(substr($value, $dotPos + 1), '0') === '') {
59+
$value = substr($value, 0, $dotPos);
60+
}
61+
62+
if (preg_replace('~^(\+|-(?=0+$))|(?<=^|^[+\-])0+(?=\d)~', '', $value) === (string) (int) $value) {
63+
return (int) $value;
64+
}
65+
6266
return $value;
6367
}
6468
}

tests/Functional/Types/BigIntTypeTest.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
use Generator;
1212
use PHPUnit\Framework\Attributes\DataProvider;
1313

14+
use function str_starts_with;
15+
use function substr;
16+
1417
use const PHP_INT_MAX;
1518
use const PHP_INT_MIN;
1619
use const PHP_INT_SIZE;
@@ -38,6 +41,30 @@ public function testSelectBigInt(string $sqlLiteral, int|string|null $expectedVa
3841
Types::BIGINT,
3942
),
4043
);
44+
45+
if ($expectedValue === null) {
46+
return;
47+
}
48+
49+
self::assertSame(
50+
$expectedValue,
51+
$this->connection->convertToPHPValue(
52+
$sqlLiteral . '.00',
53+
Types::BIGINT,
54+
),
55+
);
56+
57+
$startsWithSign = str_starts_with($sqlLiteral, '-') || str_starts_with($sqlLiteral, '+');
58+
59+
self::assertSame(
60+
$expectedValue,
61+
$this->connection->convertToPHPValue(
62+
($startsWithSign ? substr($sqlLiteral, 0, 1) : '')
63+
. '00'
64+
. ($startsWithSign ? substr($sqlLiteral, 1) : $sqlLiteral),
65+
Types::BIGINT,
66+
),
67+
);
4168
}
4269

4370
/** @return Generator<string, array{string, int|string|null}> */
@@ -53,6 +80,11 @@ public static function provideBigIntLiterals(): Generator
5380
yield 'large negative number' => [PHP_INT_SIZE === 4 ? '-2147483647' : '-9223372036854775807', PHP_INT_MIN + 1];
5481
yield 'largest positive number' => [PHP_INT_SIZE === 4 ? '2147483647' : '9223372036854775807', PHP_INT_MAX];
5582
yield 'largest negative number' => [PHP_INT_SIZE === 4 ? '-2147483648' : '-9223372036854775808', PHP_INT_MIN];
83+
84+
yield 'plus largest positive number' => [
85+
PHP_INT_SIZE === 4 ? '+2147483647' : '+9223372036854775807',
86+
PHP_INT_MAX,
87+
];
5688
}
5789

5890
public function testUnsignedBigIntOnMySQL(): void

0 commit comments

Comments
 (0)