fix: change $sequence to string type to support MongoDB UUID7 values

The Document and Row response models were casting $sequence to (int),
which destroyed UUID7 values on MongoDB. On MongoDB, $sequence is the
internal _id field which is a UUID7 string, not an auto-increment integer.
The (int) cast converted UUID7 values like "019c56a9-df6d-73fa-8d48-..."
to 19, making $sequence queries fail validation with 400.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Jake Barnby
2026-02-14 00:29:38 +13:00
co-authored by Claude Opus 4.6
parent 7708f13ebd
commit ecf0b4a1dd
4 changed files with 17 additions and 19 deletions
@@ -37,10 +37,10 @@ class Document extends Any
'example' => '5e5ea5c16897e',
])
->addRule('$sequence', [
'type' => self::TYPE_INTEGER,
'description' => 'Document automatically incrementing ID.',
'default' => 0,
'example' => 1,
'type' => self::TYPE_STRING,
'description' => 'Document sequence ID.',
'default' => '',
'example' => '1',
'readOnly' => true,
])
->addRule('$collectionId', [
@@ -84,7 +84,7 @@ class Document extends Any
$document->removeAttribute('$tenant');
if (!$document->isEmpty()) {
$document->setAttribute('$sequence', (int)$document->getAttribute('$sequence', 0));
$document->setAttribute('$sequence', (string)$document->getAttribute('$sequence', ''));
}
foreach ($document->getAttributes() as $attribute) {
+5 -5
View File
@@ -37,10 +37,10 @@ class Row extends Any
'example' => '5e5ea5c16897e',
])
->addRule('$sequence', [
'type' => self::TYPE_INTEGER,
'description' => 'Row automatically incrementing ID.',
'default' => 0,
'example' => 1,
'type' => self::TYPE_STRING,
'description' => 'Row sequence ID.',
'default' => '',
'example' => '1',
'readOnly' => true,
])
->addRule('$tableId', [
@@ -82,7 +82,7 @@ class Row extends Any
{
$document->removeAttribute('$collection');
$document->removeAttribute('$tenant');
$document->setAttribute('$sequence', (int)$document->getAttribute('$sequence', 0));
$document->setAttribute('$sequence', (string)$document->getAttribute('$sequence', ''));
foreach ($document->getAttributes() as $column) {
if (\is_array($column)) {
@@ -1755,7 +1755,7 @@ trait DatabasesBase
$this->assertEquals($document1['body']['actors'][1], 'Samuel Jackson');
$this->assertEquals($document1['body']['birthDay'], '1975-06-12T12:12:55.000+00:00');
$this->assertTrue(array_key_exists('$sequence', $document1['body']));
$this->assertIsInt($document1['body']['$sequence']);
$this->assertIsString($document1['body']['$sequence']);
$this->assertEquals(201, $document2['headers']['status-code']);
$this->assertEquals($data['moviesId'], $document2['body']['$collectionId']);
@@ -2526,17 +2526,16 @@ trait DatabasesBase
$this->assertEquals('Invalid query method: equal', $response['body']['message']);
// Query by sequence
$queryStr = Query::equal('$sequence', [$sequence])->toString();
$response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $document['$collectionId'] . '/documents', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'queries' => [
$queryStr
Query::equal('$sequence', [$sequence])->toString()
],
]);
$this->assertEquals(200, $response['headers']['status-code'], 'Query by $sequence failed. Sequence value: "' . $sequence . '", query: "' . $queryStr . '", response: ' . json_encode($response['body']));
$this->assertEquals(200, $response['headers']['status-code']);
$this->assertEquals($document['title'], $response['body']['documents'][0]['title']);
$this->assertEquals($document['releaseYear'], $response['body']['documents'][0]['releaseYear']);
$this->assertTrue(array_key_exists('$sequence', $response['body']['documents'][0]));
@@ -3192,7 +3191,7 @@ trait DatabasesBase
$this->assertEquals($id, $response['body']['$id']);
$this->assertEquals($data['moviesId'], $response['body']['$collectionId']);
$this->assertEquals($databaseId, $response['body']['$databaseId']);
$this->assertNotEquals(9999, $response['body']['$sequence']);
$this->assertNotEquals('9999', $response['body']['$sequence']);
if ($this->getSide() === 'client') {
$this->assertNotEquals('2024-01-01T00:00:00.000+00:00', $response['body']['$createdAt']);
@@ -1707,7 +1707,7 @@ trait DatabasesBase
$this->assertEquals($row1['body']['actors'][1], 'Samuel Jackson');
$this->assertEquals($row1['body']['birthDay'], '1975-06-12T12:12:55.000+00:00');
$this->assertTrue(array_key_exists('$sequence', $row1['body']));
$this->assertIsInt($row1['body']['$sequence']);
$this->assertIsString($row1['body']['$sequence']);
$this->assertEquals(201, $row2['headers']['status-code']);
$this->assertEquals($data['moviesId'], $row2['body']['$tableId']);
@@ -2448,17 +2448,16 @@ trait DatabasesBase
$this->assertEquals('Invalid query method: equal', $response['body']['message']);
// Query by sequence
$queryStr = Query::equal('$sequence', [$sequence])->toString();
$response = $this->client->call(Client::METHOD_GET, '/tablesdb/' . $databaseId . '/tables/' . $row['$tableId'] . '/rows', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'queries' => [
$queryStr
Query::equal('$sequence', [$sequence])->toString()
],
]);
$this->assertEquals(200, $response['headers']['status-code'], 'Query by $sequence failed. Sequence value: "' . $sequence . '", query: "' . $queryStr . '", response: ' . json_encode($response['body']));
$this->assertEquals(200, $response['headers']['status-code']);
$this->assertEquals($row['title'], $response['body']['rows'][0]['title']);
$this->assertEquals($row['releaseYear'], $response['body']['rows'][0]['releaseYear']);
$this->assertTrue(array_key_exists('$sequence', $response['body']['rows'][0]));