Skip to content

Commit 0e43fd4

Browse files
updated
1 parent 1761511 commit 0e43fd4

5 files changed

Lines changed: 103 additions & 111 deletions

File tree

src/Database/Database.php

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,13 @@
2222
use Utopia\Database\Exception\Structure as StructureException;
2323
use Utopia\Database\Exception\Timeout as TimeoutException;
2424
use Utopia\Database\Exception\Type as TypeException;
25-
use Utopia\Database\Helpers\BigInt as BigIntHelper;
2625
use Utopia\Database\Helpers\ID;
2726
use Utopia\Database\Helpers\Permission;
2827
use Utopia\Database\Helpers\Role;
2928
use Utopia\Database\Validator\Attribute as AttributeValidator;
3029
use Utopia\Database\Validator\Authorization;
3130
use Utopia\Database\Validator\Authorization\Input;
31+
use Utopia\Database\Validator\BigInt as BigIntValidator;
3232
use Utopia\Database\Validator\Index as IndexValidator;
3333
use Utopia\Database\Validator\IndexDependency as IndexDependencyValidator;
3434
use Utopia\Database\Validator\PartialStructure;
@@ -2593,7 +2593,7 @@ protected function validateDefaultTypes(string $type, mixed $default): void
25932593
}
25942594
break;
25952595
case Database::VAR_BIGINT:
2596-
if ($defaultType !== 'integer') {
2596+
if ($defaultType !== 'integer' && $defaultType !== 'string') {
25972597
throw new DatabaseException('Default value ' . $default . ' does not match given type ' . $type);
25982598
}
25992599
break;
@@ -2920,13 +2920,13 @@ public function updateAttribute(string $collection, string $id, ?string $type =
29202920
}
29212921
break;
29222922
case self::VAR_BIGINT:
2923-
$sizeString = BigIntHelper::normalizeUnsignedString((string)$size);
2923+
$sizeString = BigIntValidator::normalizeUnsignedString((string)$size);
29242924
$limit = (!$signed && $this->adapter->getSupportForUnsignedBigInt())
2925-
? BigIntHelper::UNSIGNED_MAX
2926-
: BigIntHelper::SIGNED_MAX;
2925+
? BigIntValidator::UNSIGNED_MAX
2926+
: BigIntValidator::SIGNED_MAX;
29272927

2928-
if (BigIntHelper::compareUnsignedStrings($sizeString, $limit) > 0) {
2929-
throw new DatabaseException('Max size allowed for bigint is: ' . BigIntHelper::formatIntegerString($limit));
2928+
if (BigIntValidator::compareUnsignedStrings($sizeString, $limit) > 0) {
2929+
throw new DatabaseException('Max size allowed for bigint is: ' . BigIntValidator::formatIntegerString($limit));
29302930
}
29312931
break;
29322932
case self::VAR_FLOAT:
@@ -8969,7 +8969,7 @@ public function casting(Document $collection, Document $document): Document
89698969
$node = (int)$node;
89708970
break;
89718971
case self::VAR_BIGINT:
8972-
if (\is_string($node) && BigIntHelper::fitsPhpInt($node, $signed)) {
8972+
if (\is_string($node) && BigIntValidator::fitsPhpInt($node, $signed)) {
89738973
$node = (int)$node;
89748974
}
89758975
break;

src/Database/Helpers/BigInt.php

Lines changed: 0 additions & 93 deletions
This file was deleted.

src/Database/Validator/BigInt.php

Lines changed: 92 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,14 @@
33
namespace Utopia\Database\Validator;
44

55
use Utopia\Database\Database;
6-
use Utopia\Database\Helpers\BigInt as BigIntHelper;
76
use Utopia\Validator;
87

98
class BigInt extends Validator
109
{
10+
public const SIGNED_MIN = '-9223372036854775808';
11+
public const SIGNED_MAX = '9223372036854775807';
12+
public const UNSIGNED_MAX = '18446744073709551615';
13+
1114
public function __construct(
1215
private readonly bool $signed,
1316
private readonly bool $supportUnsigned64Bit = true
@@ -18,13 +21,13 @@ public function getDescription(): string
1821
{
1922
if ($this->signed) {
2023
return 'Value must be a valid signed 64-bit integer between ' .
21-
BigIntHelper::formatIntegerString(BigIntHelper::SIGNED_MIN) .
22-
' and ' . BigIntHelper::formatIntegerString(BigIntHelper::SIGNED_MAX);
24+
self::formatIntegerString(self::SIGNED_MIN) .
25+
' and ' . self::formatIntegerString(self::SIGNED_MAX);
2326
}
2427

25-
$max = $this->supportUnsigned64Bit ? BigIntHelper::UNSIGNED_MAX : BigIntHelper::SIGNED_MAX;
28+
$max = $this->supportUnsigned64Bit ? self::UNSIGNED_MAX : self::SIGNED_MAX;
2629
return 'Value must be a valid unsigned 64-bit integer between 0 and ' .
27-
BigIntHelper::formatIntegerString($max);
30+
self::formatIntegerString($max);
2831
}
2932

3033
public function isArray(): bool
@@ -47,6 +50,89 @@ public function isValid(mixed $value): bool
4750
return false;
4851
}
4952

50-
return BigIntHelper::fitsBigIntRange($value, $this->signed, $this->supportUnsigned64Bit);
53+
return self::fitsBigIntRange($value, $this->signed, $this->supportUnsigned64Bit);
54+
}
55+
56+
public static function isIntegerString(string $value, bool $signed = true): bool
57+
{
58+
return \preg_match($signed ? '/^-?\d+$/' : '/^\d+$/', $value) === 1;
59+
}
60+
61+
public static function fitsPhpInt(string $value, bool $signed = true): bool
62+
{
63+
if (!self::isIntegerString($value, $signed)) {
64+
return false;
65+
}
66+
67+
$phpMax = (string)\PHP_INT_MAX;
68+
$phpMinAbs = \ltrim((string)\PHP_INT_MIN, '-');
69+
70+
if ($signed && \str_starts_with($value, '-')) {
71+
$digits = self::normalizeUnsignedString(\substr($value, 1));
72+
return self::compareUnsignedStrings($digits, $phpMinAbs) <= 0;
73+
}
74+
75+
$digits = self::normalizeUnsignedString($value);
76+
return self::compareUnsignedStrings($digits, $phpMax) <= 0;
77+
}
78+
79+
public static function fitsBigIntRange(string $value, bool $signed, bool $supportUnsigned64Bit = true): bool
80+
{
81+
if (!self::isIntegerString($value, $signed)) {
82+
return false;
83+
}
84+
85+
if ($signed) {
86+
if (\str_starts_with($value, '-')) {
87+
$digits = self::normalizeUnsignedString(\substr($value, 1));
88+
$minAbs = \ltrim(\str_replace('-', '', self::SIGNED_MIN), '0');
89+
return self::compareUnsignedStrings($digits, $minAbs) <= 0;
90+
}
91+
92+
return self::compareUnsignedStrings($value, self::SIGNED_MAX) <= 0;
93+
}
94+
95+
$max = $supportUnsigned64Bit ? self::UNSIGNED_MAX : self::SIGNED_MAX;
96+
return self::compareUnsignedStrings($value, $max) <= 0;
97+
}
98+
99+
public static function normalizeUnsignedString(string $value): string
100+
{
101+
$value = \trim($value);
102+
$value = \ltrim($value, '0');
103+
return $value === '' ? '0' : $value;
104+
}
105+
106+
public static function compareUnsignedStrings(string $a, string $b): int
107+
{
108+
$a = self::normalizeUnsignedString($a);
109+
$b = self::normalizeUnsignedString($b);
110+
111+
$lenA = \strlen($a);
112+
$lenB = \strlen($b);
113+
if ($lenA < $lenB) {
114+
return -1;
115+
}
116+
if ($lenA > $lenB) {
117+
return 1;
118+
}
119+
if ($a === $b) {
120+
return 0;
121+
}
122+
123+
return $a < $b ? -1 : 1;
124+
}
125+
126+
public static function formatIntegerString(string $value): string
127+
{
128+
$negative = \str_starts_with($value, '-');
129+
if ($negative) {
130+
$value = \substr($value, 1);
131+
}
132+
133+
$value = self::normalizeUnsignedString($value);
134+
$formatted = \preg_replace('/\B(?=(\d{3})+(?!\d))/', ',', $value) ?? $value;
135+
136+
return $negative ? "-{$formatted}" : $formatted;
51137
}
52138
}

src/Database/Validator/Query/Filter.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ protected function isValidAttributeAndValues(string $attribute, array $values, s
157157
case Database::VAR_INTEGER:
158158
$size = $attributeSchema['size'] ?? 4;
159159
$signed = $attributeSchema['signed'] ?? true;
160-
$bits = ($attributeType === Database::VAR_BIGINT || $size >= 8) ? 64 : 32;
160+
$bits = $size >= 8 ? 64 : 32;
161161
// For 64-bit unsigned, use signed since PHP doesn't support true 64-bit unsigned
162162
$unsigned = !$signed && $bits < 64;
163163
$validator = new Integer(false, $bits, $unsigned);

src/Database/Validator/Structure.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
use Utopia\Database\Database;
88
use Utopia\Database\Document;
99
use Utopia\Database\Exception as DatabaseException;
10-
use Utopia\Database\Helpers\BigInt as BigIntHelper;
1110
use Utopia\Database\Operator;
1211
use Utopia\Database\Validator\Datetime as DatetimeValidator;
1312
use Utopia\Database\Validator\Operator as OperatorValidator;
@@ -365,7 +364,7 @@ protected function checkForInvalidAttributeValues(Document $document, array $str
365364
case Database::VAR_INTEGER:
366365
// Determine bit size based on attribute size in bytes
367366
// BIGINT is always 64-bit in SQL adapters; VAR_INTEGER uses size to decide.
368-
$bits = ($type === Database::VAR_BIGINT || $size >= 8) ? 64 : 32;
367+
$bits = $size >= 8 ? 64 : 32;
369368
// For 64-bit unsigned, use signed since PHP doesn't support true 64-bit unsigned
370369
// The Range validator will restrict to positive values only
371370
$unsigned = !$signed && $bits < 64;
@@ -464,7 +463,7 @@ protected function checkForInvalidAttributeValues(Document $document, array $str
464463

465464
public function isBigIntStringWithinPhpIntRange(string $value, bool $signed): bool
466465
{
467-
return BigIntHelper::fitsPhpInt($value, $signed);
466+
return BigInt::fitsPhpInt($value, $signed);
468467
}
469468

470469
/**

0 commit comments

Comments
 (0)