Skip to content
Open
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
af321ee
Implement BIGINT support across database adapters and add getLimitFor…
ArnabChatterjee20k Mar 27, 2026
3137084
Add support for VAR_BIGINT in Database and Attribute classes
ArnabChatterjee20k Mar 27, 2026
b5c7447
Add tests for BIGINT attribute handling and validation limits
ArnabChatterjee20k Mar 27, 2026
bd14576
Update getLimitForBigInt method to return 4294967295 for Mongo and SQ…
ArnabChatterjee20k Mar 27, 2026
acfeae1
updated bigint mongo
ArnabChatterjee20k Mar 27, 2026
07358a5
Enhance BIGINT handling in MariaDB and SQL adapters
ArnabChatterjee20k Mar 27, 2026
909d8a5
Add VAR_BIGINT to Database class attribute types
ArnabChatterjee20k Mar 27, 2026
f2acd8c
Enhance BIGINT size limit validation in Database class
ArnabChatterjee20k Mar 27, 2026
602eefc
Refine BIGINT handling in Structure and Filter validators
ArnabChatterjee20k Mar 27, 2026
14828d9
Refine BIGINT type determination in Postgres adapter
ArnabChatterjee20k Mar 27, 2026
080de0e
Remove BIGINT size limit validation from Database and Validator classes
ArnabChatterjee20k Mar 30, 2026
73e917e
Add support for VAR_BIGINT in Database class and corresponding tests
ArnabChatterjee20k Mar 30, 2026
ef5c779
updated tests
ArnabChatterjee20k Mar 30, 2026
4490a49
big int validator for attribute
ArnabChatterjee20k Mar 30, 2026
4c5aeb1
updated
ArnabChatterjee20k Mar 30, 2026
8137486
updated attribute validator
ArnabChatterjee20k Mar 30, 2026
b87cf3a
updated
ArnabChatterjee20k Mar 30, 2026
ad89dab
Merge remote-tracking branch 'origin/main' into big-init
ArnabChatterjee20k Apr 1, 2026
5ee5d1b
Add support for unsigned big integers in database adapters and valida…
ArnabChatterjee20k Apr 8, 2026
38e31f4
updated
ArnabChatterjee20k Apr 8, 2026
cafb353
updated
ArnabChatterjee20k Apr 8, 2026
dbe3537
Refactor attribute size handling in database adapters to support both…
ArnabChatterjee20k Apr 8, 2026
ba45e22
Enhance attribute validation to support string type for big integers
ArnabChatterjee20k Apr 8, 2026
75a7f28
Refactor attribute size handling to enforce integer type across datab…
ArnabChatterjee20k Apr 8, 2026
946b841
updated
ArnabChatterjee20k Apr 8, 2026
fafacee
updated
ArnabChatterjee20k Apr 8, 2026
fe3bf72
updated
ArnabChatterjee20k Apr 8, 2026
d3282bc
updated
ArnabChatterjee20k Apr 8, 2026
1761511
updated the type for big int validator
ArnabChatterjee20k Apr 9, 2026
0e43fd4
updated
ArnabChatterjee20k Apr 9, 2026
9c3defb
fix: align bigint handling and validator refactors from PR feedback
Copilot Apr 16, 2026
ae10b94
fix: keep filter supportForAttributes mutability unchanged
Copilot Apr 16, 2026
a58547e
refactor: centralize bigint size normalization and extend coverage
Copilot Apr 16, 2026
7315ba2
fixed the attribute ordering
ArnabChatterjee20k Apr 16, 2026
6ff2d7b
updated
ArnabChatterjee20k Apr 16, 2026
602f0cd
updated
ArnabChatterjee20k Apr 16, 2026
89013ff
updated pool
ArnabChatterjee20k Apr 16, 2026
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
7 changes: 7 additions & 0 deletions src/Database/Adapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -880,6 +880,13 @@ abstract public function getLimitForString(): int;
*/
abstract public function getLimitForInt(): int;

/**
* Get max BIGINT limit
*
* @return int
*/
abstract public function getLimitForBigInt(): int;

/**
* Get maximum attributes limit.
*
Expand Down
6 changes: 5 additions & 1 deletion src/Database/Adapter/MariaDB.php
Original file line number Diff line number Diff line change
Expand Up @@ -1734,6 +1734,10 @@ protected function getSQLType(string $type, int $size, bool $signed = true, bool

return 'INT' . $signed;

case Database::VAR_BIGINT:
$signed = ($signed) ? '' : ' UNSIGNED';
return 'BIGINT' . $signed;
Comment thread
coderabbitai[bot] marked this conversation as resolved.

case Database::VAR_FLOAT:
$signed = ($signed) ? '' : ' UNSIGNED';
return 'DOUBLE' . $signed;
Expand All @@ -1748,7 +1752,7 @@ protected function getSQLType(string $type, int $size, bool $signed = true, bool
return 'DATETIME(3)';

default:
throw new DatabaseException('Unknown type: ' . $type . '. Must be one of ' . Database::VAR_STRING . ', ' . Database::VAR_VARCHAR . ', ' . Database::VAR_TEXT . ', ' . Database::VAR_MEDIUMTEXT . ', ' . Database::VAR_LONGTEXT . ', ' . Database::VAR_INTEGER . ', ' . Database::VAR_FLOAT . ', ' . Database::VAR_BOOLEAN . ', ' . Database::VAR_DATETIME . ', ' . Database::VAR_RELATIONSHIP . ', ' . Database::VAR_POINT . ', ' . Database::VAR_LINESTRING . ', ' . Database::VAR_POLYGON);
throw new DatabaseException('Unknown type: ' . $type . '. Must be one of ' . Database::VAR_STRING . ', ' . Database::VAR_VARCHAR . ', ' . Database::VAR_TEXT . ', ' . Database::VAR_MEDIUMTEXT . ', ' . Database::VAR_LONGTEXT . ', ' . Database::VAR_INTEGER . ', ' . Database::VAR_BIGINT . ', ' . Database::VAR_FLOAT . ', ' . Database::VAR_BOOLEAN . ', ' . Database::VAR_DATETIME . ', ' . Database::VAR_RELATIONSHIP . ', ' . Database::VAR_POINT . ', ' . Database::VAR_LINESTRING . ', ' . Database::VAR_POLYGON);
}
}

Expand Down
12 changes: 12 additions & 0 deletions src/Database/Adapter/Mongo.php
Original file line number Diff line number Diff line change
Expand Up @@ -1310,6 +1310,7 @@ public function castingAfter(Document $collection, Document $document): Document
foreach ($value as &$node) {
switch ($type) {
case Database::VAR_INTEGER:
case Database::VAR_BIGINT:
$node = (int)$node;
break;
Comment thread
abnegate marked this conversation as resolved.
case Database::VAR_DATETIME:
Expand Down Expand Up @@ -2211,6 +2212,7 @@ private function getMongoTypeCode(string $appwriteType): string
Database::VAR_MEDIUMTEXT => 'string',
Database::VAR_LONGTEXT => 'string',
Database::VAR_INTEGER => 'int',
Database::VAR_BIGINT => 'long',
Database::VAR_FLOAT => 'double',
Database::VAR_BOOLEAN => 'bool',
Database::VAR_DATETIME => 'date',
Expand Down Expand Up @@ -3004,6 +3006,16 @@ public function getLimitForInt(): int
return 4294967295;
}

/**
* Get max BIGINT limit
*
* @return int
*/
public function getLimitForBigInt(): int
{
return Database::MAX_BIG_INT;
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

/**
* Get maximum column limit.
* Returns 0 to indicate no limit
Expand Down
5 changes: 5 additions & 0 deletions src/Database/Adapter/Pool.php
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,11 @@ public function getLimitForInt(): int
return $this->delegate(__FUNCTION__, \func_get_args());
}

public function getLimitForBigInt(): int
{
return $this->delegate(__FUNCTION__, \func_get_args());
}
Comment on lines +336 to +339
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Missing getSupportForUnsignedBigInt() delegation in Pool

Pool inherits getSupportForUnsignedBigInt() from Adapter (which returns false) instead of delegating to the wrapped adapter. In production, Pool is a common way to use MariaDB — but with this bug, Database::getSupportForUnsignedBigInt() always returns false on a Pool-wrapped MariaDB, so Structure, Filter, and attribute validators all clamp the unsigned bigint range to SIGNED_MAX (9,223,372,036,854,775,807). Any value in (PHP_INT_MAX, 18,446,744,073,709,551,615] is rejected at the PHP layer even though MariaDB can store it.

Add the delegation alongside the existing getLimitForBigInt() entry:

Suggested change
public function getLimitForBigInt(): int
{
return $this->delegate(__FUNCTION__, \func_get_args());
}
public function getLimitForBigInt(): int
{
return $this->delegate(__FUNCTION__, \func_get_args());
}
public function getSupportForUnsignedBigInt(): bool
{
return $this->delegate(__FUNCTION__, \func_get_args());
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

fixed


public function getLimitForAttributes(): int
{
return $this->delegate(__FUNCTION__, \func_get_args());
Expand Down
5 changes: 4 additions & 1 deletion src/Database/Adapter/Postgres.php
Original file line number Diff line number Diff line change
Expand Up @@ -1972,6 +1972,9 @@ protected function getSQLType(string $type, int $size, bool $signed = true, bool

return 'INTEGER';

case Database::VAR_BIGINT:
return 'BIGINT';

case Database::VAR_FLOAT:
return 'DOUBLE PRECISION';

Expand Down Expand Up @@ -2000,7 +2003,7 @@ protected function getSQLType(string $type, int $size, bool $signed = true, bool
return "VECTOR({$size})";

default:
throw new DatabaseException('Unknown Type: ' . $type . '. Must be one of ' . Database::VAR_STRING . ', ' . Database::VAR_VARCHAR . ', ' . Database::VAR_TEXT . ', ' . Database::VAR_MEDIUMTEXT . ', ' . Database::VAR_LONGTEXT . ', ' . Database::VAR_INTEGER . ', ' . Database::VAR_FLOAT . ', ' . Database::VAR_BOOLEAN . ', ' . Database::VAR_DATETIME . ', ' . Database::VAR_RELATIONSHIP . ', ' . Database::VAR_OBJECT . ', ' . Database::VAR_POINT . ', ' . Database::VAR_LINESTRING . ', ' . Database::VAR_POLYGON);
throw new DatabaseException('Unknown Type: ' . $type . '. Must be one of ' . Database::VAR_STRING . ', ' . Database::VAR_VARCHAR . ', ' . Database::VAR_TEXT . ', ' . Database::VAR_MEDIUMTEXT . ', ' . Database::VAR_LONGTEXT . ', ' . Database::VAR_INTEGER . ', ' . Database::VAR_BIGINT . ', ' . Database::VAR_FLOAT . ', ' . Database::VAR_BOOLEAN . ', ' . Database::VAR_DATETIME . ', ' . Database::VAR_RELATIONSHIP . ', ' . Database::VAR_OBJECT . ', ' . Database::VAR_POINT . ', ' . Database::VAR_LINESTRING . ', ' . Database::VAR_POLYGON);
}
}

Expand Down
14 changes: 14 additions & 0 deletions src/Database/Adapter/SQL.php
Original file line number Diff line number Diff line change
Expand Up @@ -896,6 +896,16 @@ public function getLimitForInt(): int
return 4294967295;
}

/**
* Get max BIGINT limit
*
* @return int
*/
public function getLimitForBigInt(): int
{
return Database::MAX_BIG_INT;
Copy link
Copy Markdown
Contributor Author

@ArnabChatterjee20k ArnabChatterjee20k Apr 8, 2026

Choose a reason for hiding this comment

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

Here going other way around
It is the signed big int limit(supported by all adapter)
For adapters supporting unsigned int, in the attribute validator, we are validating via string comparison

}
Comment thread
ArnabChatterjee20k marked this conversation as resolved.
Comment thread
coderabbitai[bot] marked this conversation as resolved.

/**
* Get maximum column limit.
* https://mariadb.com/kb/en/innodb-limitations/#limitations-on-schema
Expand Down Expand Up @@ -1164,6 +1174,10 @@ public function getAttributeWidth(Document $collection): int
}
break;

case Database::VAR_BIGINT:
$total += 8; // BIGINT 8 bytes
break;

case Database::VAR_FLOAT:
$total += 8; // DOUBLE 8 bytes
break;
Expand Down
7 changes: 7 additions & 0 deletions src/Database/Database.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ class Database
// Simple Types
public const VAR_STRING = 'string';
public const VAR_INTEGER = 'integer';
public const VAR_BIGINT = 'bigint';
Comment thread
coderabbitai[bot] marked this conversation as resolved.
public const VAR_FLOAT = 'double';
public const VAR_BOOLEAN = 'boolean';
public const VAR_DATETIME = 'datetime';
Expand Down Expand Up @@ -2512,6 +2513,7 @@ private function validateAttribute(
maxStringLength: $this->adapter->getLimitForString(),
maxVarcharLength: $this->adapter->getMaxVarcharLength(),
maxIntLength: $this->adapter->getLimitForInt(),
maxBigIntLength: $this->adapter->getLimitForBigInt(),
supportForSchemaAttributes: $this->adapter->getSupportForSchemaAttributes(),
supportForVectors: $this->adapter->getSupportForVectors(),
supportForSpatialAttributes: $this->adapter->getSupportForSpatialAttributes(),
Expand Down Expand Up @@ -2582,6 +2584,7 @@ protected function validateDefaultTypes(string $type, mixed $default): void
}
break;
case self::VAR_INTEGER:
case self::VAR_BIGINT:
case self::VAR_FLOAT:
case self::VAR_BOOLEAN:
if ($type !== $defaultType) {
Expand All @@ -2607,6 +2610,7 @@ protected function validateDefaultTypes(string $type, mixed $default): void
self::VAR_MEDIUMTEXT,
self::VAR_LONGTEXT,
self::VAR_INTEGER,
self::VAR_BIGINT,
self::VAR_FLOAT,
self::VAR_BOOLEAN,
self::VAR_DATETIME,
Expand Down Expand Up @@ -2909,6 +2913,8 @@ public function updateAttribute(string $collection, string $id, ?string $type =
throw new DatabaseException('Max size allowed for int is: ' . number_format($limit));
}
break;
case self::VAR_BIGINT:
break;
case self::VAR_FLOAT:
case self::VAR_BOOLEAN:
case self::VAR_DATETIME:
Expand Down Expand Up @@ -2975,6 +2981,7 @@ public function updateAttribute(string $collection, string $id, ?string $type =
self::VAR_MEDIUMTEXT,
self::VAR_LONGTEXT,
self::VAR_INTEGER,
self::VAR_BIGINT,
self::VAR_FLOAT,
self::VAR_BOOLEAN,
self::VAR_DATETIME,
Expand Down
10 changes: 10 additions & 0 deletions src/Database/Validator/Attribute.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class Attribute extends Validator
* @param int $maxStringLength
* @param int $maxVarcharLength
* @param int $maxIntLength
* @param int $maxBigIntLength
* @param bool $supportForSchemaAttributes
* @param bool $supportForVectors
* @param bool $supportForSpatialAttributes
Expand All @@ -49,6 +50,7 @@ public function __construct(
protected int $maxStringLength = 0,
protected int $maxVarcharLength = 0,
protected int $maxIntLength = 0,
protected int $maxBigIntLength = 0,
protected bool $supportForSchemaAttributes = false,
protected bool $supportForVectors = false,
protected bool $supportForSpatialAttributes = false,
Expand All @@ -59,6 +61,11 @@ public function __construct(
protected bool $isMigrating = false,
protected bool $sharedTables = false,
) {
// Keep backwards compatibility for existing validator construction sites.
if ($this->maxBigIntLength === 0) {
$this->maxBigIntLength = $this->maxIntLength;
}

foreach ($attributes as $attribute) {
$key = \strtolower($attribute->getAttribute('key', $attribute->getAttribute('$id')));
$this->attributes[$key] = $attribute;
Expand Down Expand Up @@ -337,6 +344,9 @@ public function checkType(Document $attribute): bool
}
break;

case Database::VAR_BIGINT:
break;

case Database::VAR_FLOAT:
case Database::VAR_BOOLEAN:
case Database::VAR_DATETIME:
Expand Down
3 changes: 2 additions & 1 deletion src/Database/Validator/Query/Filter.php
Original file line number Diff line number Diff line change
Expand Up @@ -153,9 +153,10 @@ protected function isValidAttributeAndValues(string $attribute, array $values, s
break;

case Database::VAR_INTEGER:
case Database::VAR_BIGINT:
$size = $attributeSchema['size'] ?? 4;
$signed = $attributeSchema['signed'] ?? true;
$bits = $size >= 8 ? 64 : 32;
$bits = ($attributeType === Database::VAR_BIGINT || $size >= 8) ? 64 : 32;
// For 64-bit unsigned, use signed since PHP doesn't support true 64-bit unsigned
$unsigned = !$signed && $bits < 64;
$validator = new Integer(false, $bits, $unsigned);
Expand Down
6 changes: 4 additions & 2 deletions src/Database/Validator/Structure.php
Original file line number Diff line number Diff line change
Expand Up @@ -352,13 +352,15 @@ protected function checkForInvalidAttributeValues(array $structure, array $keys)
break;

case Database::VAR_INTEGER:
case Database::VAR_BIGINT:
// Determine bit size based on attribute size in bytes
$bits = $size >= 8 ? 64 : 32;
// BIGINT is always 64-bit in SQL adapters; VAR_INTEGER uses size to decide.
$bits = ($type === Database::VAR_BIGINT || $size >= 8) ? 64 : 32;
// For 64-bit unsigned, use signed since PHP doesn't support true 64-bit unsigned
Comment thread
abnegate marked this conversation as resolved.
// The Range validator will restrict to positive values only
$unsigned = !$signed && $bits < 64;
$validators[] = new Integer(false, $bits, $unsigned);
$max = $size >= 8 ? Database::MAX_BIG_INT : Database::MAX_INT;
$max = $bits === 64 ? Database::MAX_BIG_INT : Database::MAX_INT;
$min = $signed ? -$max : 0;
$validators[] = new Range($min, $max, Database::VAR_INTEGER);
break;
Expand Down
33 changes: 33 additions & 0 deletions tests/e2e/Adapter/Scopes/AttributeTests.php
Original file line number Diff line number Diff line change
Expand Up @@ -2221,6 +2221,39 @@ public function testCreateAttributesIntegerSizeLimit(): void
}
}


public function testCreateAttributesBigIntIgnoresSizeLimit(): void
{
/** @var Database $database */
$database = $this->getDatabase();

if (!$database->getAdapter()->getSupportForBatchCreateAttributes()) {
$this->expectNotToPerformAssertions();
return;
}

$database->createCollection(__FUNCTION__);

$limit = $database->getAdapter()->getLimitForBigInt() / 2;
$size = (int)$limit + 1;

$attributes = [[
'$id' => 'foo',
'type' => Database::VAR_BIGINT,
'size' => $size,
'required' => false
]];

$result = $database->createAttributes(__FUNCTION__, $attributes);
$this->assertTrue($result);

$collection = $database->getCollection(__FUNCTION__);
$attrs = $collection->getAttribute('attributes');
$this->assertCount(1, $attrs);
$this->assertEquals('foo', $attrs[0]['$id']);
$this->assertEquals($size, $attrs[0]['size']);
}

public function testCreateAttributesSuccessMultiple(): void
{
/** @var Database $database */
Expand Down
28 changes: 28 additions & 0 deletions tests/e2e/Adapter/Scopes/DocumentTests.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,34 @@ public function testBigintSequence(): void
}
}

public function testCreateDocumentWithBigIntType(): void
{
/** @var Database $database */
$database = $this->getDatabase();

$database->createCollection(__FUNCTION__);
$this->assertEquals(true, $database->createAttribute(__FUNCTION__, 'bigint_signed', Database::VAR_BIGINT, 0, true));
$this->assertEquals(true, $database->createAttribute(__FUNCTION__, 'bigint_unsigned', Database::VAR_BIGINT, 0, true, signed: false));

$document = $database->createDocument(__FUNCTION__, new Document([
'$id' => 'bigint-type-doc',
'$permissions' => [Permission::read(Role::any())],
'bigint_signed' => -Database::MAX_BIG_INT,
'bigint_unsigned' => Database::MAX_BIG_INT,
]));

$this->assertIsInt($document->getAttribute('bigint_signed'));
$this->assertEquals(-Database::MAX_BIG_INT, $document->getAttribute('bigint_signed'));
$this->assertIsInt($document->getAttribute('bigint_unsigned'));
$this->assertEquals(Database::MAX_BIG_INT, $document->getAttribute('bigint_unsigned'));

$results = $database->find(__FUNCTION__, [
Query::equal('bigint_unsigned', [Database::MAX_BIG_INT])
]);
$this->assertCount(1, $results);
$this->assertEquals('bigint-type-doc', $results[0]->getId());
}

public function testCreateDocument(): Document
{
/** @var Database $database */
Expand Down
50 changes: 50 additions & 0 deletions tests/unit/Validator/AttributeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1139,6 +1139,56 @@ public function testUnsignedIntegerSizeTooLarge(): void
$validator->isValid($attribute);
}

public function testBigIntSizeNotLimited(): void
{
$validator = new Attribute(
attributes: [],
maxStringLength: 16777216,
maxVarcharLength: 65535,
maxIntLength: PHP_INT_MAX,
maxBigIntLength: 200,
);

$attribute = new Document([
'$id' => ID::custom('counter'),
'key' => 'counter',
'type' => Database::VAR_BIGINT,
'size' => 101,
'required' => false,
'default' => null,
'signed' => true,
'array' => false,
'filters' => [],
]);

$this->assertTrue($validator->isValid($attribute));
}

public function testUnsignedBigIntSizeLimit(): void
{
$validator = new Attribute(
attributes: [],
maxStringLength: 16777216,
maxVarcharLength: 65535,
maxIntLength: PHP_INT_MAX,
maxBigIntLength: 200,
);

$attribute = new Document([
'$id' => ID::custom('counter'),
'key' => 'counter',
'type' => Database::VAR_BIGINT,
'size' => 200,
'required' => false,
'default' => null,
'signed' => false,
'array' => false,
'filters' => [],
]);

$this->assertTrue($validator->isValid($attribute));
}

public function testDuplicateAttributeIdCaseInsensitive(): void
{
$validator = new Attribute(
Expand Down
Loading