diff --git a/src/Database/Adapter/MariaDB.php b/src/Database/Adapter/MariaDB.php index ddb72d5a8..1ab7e7583 100644 --- a/src/Database/Adapter/MariaDB.php +++ b/src/Database/Adapter/MariaDB.php @@ -496,12 +496,23 @@ public function createDocument(string $collection, Document $document): Document $bindIndex++; } + // Insert manual id if set + if (!empty($document->getInternalId())) { + $bindKey = '_id'; + $columns .= " _id" . ' = :' . $bindKey . ','; + } + $stmt = $this->getPDO() ->prepare("INSERT INTO {$this->getSQLTable($name)} SET {$columns} _uid = :_uid"); $stmt->bindValue(':_uid', $document->getId(), PDO::PARAM_STR); + // Bind manual internal id if set + if (!empty($document->getInternalId())) { + $stmt->bindValue(':_id', $document->getInternalId(), PDO::PARAM_STR); + } + $attributeIndex = 0; foreach ($attributes as $attribute => $value) { if (is_array($value)) { // arrays & objects should be saved as strings @@ -531,11 +542,7 @@ public function createDocument(string $collection, Document $document): Document try { $stmt->execute(); - $statment = $this->getPDO()->prepare("select last_insert_id() as id"); - $statment->execute(); - $last = $statment->fetch(); - $document['$internalId'] = $last['id']; - + $document['$internalId'] = $this->getDocument($collection, $document->getId())->getInternalId(); if (isset($stmtPermissions)) { $stmtPermissions->execute(); } diff --git a/src/Database/Adapter/Mongo/MongoDBAdapter.php b/src/Database/Adapter/Mongo/MongoDBAdapter.php index 690be6bd8..34eac710c 100644 --- a/src/Database/Adapter/Mongo/MongoDBAdapter.php +++ b/src/Database/Adapter/Mongo/MongoDBAdapter.php @@ -386,6 +386,11 @@ public function createDocument(string $collection, Document $document): Document $record = $this->replaceChars('$', '_', $document->getArrayCopy()); + // Insert manual id if set + if (!empty($internalId)) { + $record['_id'] = $internalId; + } + $this->client->insert($name, $record); return $document; diff --git a/src/Database/Adapter/SQLite.php b/src/Database/Adapter/SQLite.php index 41ac61ec4..8307966e2 100644 --- a/src/Database/Adapter/SQLite.php +++ b/src/Database/Adapter/SQLite.php @@ -319,12 +319,23 @@ public function createDocument(string $collection, Document $document): Document $bindIndex++; } + // Insert manual id if set + if (!empty($document->getInternalId())) { + $values[] = '_id'; + $columns[] = "_id"; + } + $stmt = $this->getPDO() ->prepare("INSERT INTO `{$this->getNamespace()}_{$name}` (".implode(', ', $columns).") VALUES (:".implode(', :', $values).");"); $stmt->bindValue(':_uid', $document->getId(), PDO::PARAM_STR); + // Bind manual internal id if set + if (!empty($document->getInternalId())) { + $stmt->bindValue(':_id', $document->getInternalId(), PDO::PARAM_STR); + } + $attributeIndex = 0; foreach ($attributes as $attribute => $value) { if (is_array($value)) { // arrays & objects should be saved as strings diff --git a/src/Database/Validator/Structure.php b/src/Database/Validator/Structure.php index cddcd1a42..f2ae54ada 100644 --- a/src/Database/Validator/Structure.php +++ b/src/Database/Validator/Structure.php @@ -34,7 +34,7 @@ class Structure extends Validator [ '$id' => '$internalId', 'type' => Database::VAR_STRING, - 'size' => 64, + 'size' => 0, 'required' => false, 'signed' => true, 'array' => false, diff --git a/tests/Database/Base.php b/tests/Database/Base.php index 693289c84..45d130bd1 100644 --- a/tests/Database/Base.php +++ b/tests/Database/Base.php @@ -605,6 +605,50 @@ public function testCreateDocument() $this->assertEquals([], $document->getAttribute('empty')); $this->assertEquals('Works', $document->getAttribute('with-dash')); + // Test create document with manual internal id + $manualIdDocument = static::getDatabase()->createDocument('documents', new Document([ + '$internalId' => '56000', + '$permissions' => [ + Permission::read(Role::any()), + Permission::read(Role::user(ID::custom('1'))), + Permission::read(Role::user(ID::custom('2'))), + Permission::create(Role::any()), + Permission::create(Role::user(ID::custom('1x'))), + Permission::create(Role::user(ID::custom('2x'))), + Permission::update(Role::any()), + Permission::update(Role::user(ID::custom('1x'))), + Permission::update(Role::user(ID::custom('2x'))), + Permission::delete(Role::any()), + Permission::delete(Role::user(ID::custom('1x'))), + Permission::delete(Role::user(ID::custom('2x'))), + ], + 'string' => 'textđź“ť', + 'integer' => 5, + 'bigint' => 8589934592, // 2^33 + 'float' => 5.55, + 'boolean' => true, + 'colors' => ['pink', 'green', 'blue'], + 'empty' => [], + 'with-dash' => 'Works', + ])); + + $this->assertEquals('56000', $manualIdDocument->getInternalId()); + $this->assertNotEmpty(true, $manualIdDocument->getId()); + $this->assertIsString($manualIdDocument->getAttribute('string')); + $this->assertEquals('textđź“ť', $manualIdDocument->getAttribute('string')); // Also makes sure an emoji is working + $this->assertIsInt($manualIdDocument->getAttribute('integer')); + $this->assertEquals(5, $manualIdDocument->getAttribute('integer')); + $this->assertIsInt($manualIdDocument->getAttribute('bigint')); + $this->assertEquals(8589934592, $manualIdDocument->getAttribute('bigint')); + $this->assertIsFloat($manualIdDocument->getAttribute('float')); + $this->assertEquals(5.55, $manualIdDocument->getAttribute('float')); + $this->assertIsBool($manualIdDocument->getAttribute('boolean')); + $this->assertEquals(true, $manualIdDocument->getAttribute('boolean')); + $this->assertIsArray($manualIdDocument->getAttribute('colors')); + $this->assertEquals(['pink', 'green', 'blue'], $manualIdDocument->getAttribute('colors')); + $this->assertEquals([], $manualIdDocument->getAttribute('empty')); + $this->assertEquals('Works', $manualIdDocument->getAttribute('with-dash')); + return $document; } @@ -2636,6 +2680,7 @@ public function testExceptionDuplicate(Document $document) public function testExceptionCaseInsensitiveDuplicate(Document $document) { $document->setAttribute('$id', 'caseSensitive'); + $document->setAttribute('$internalId', '200'); static::getDatabase()->createDocument($document->getCollection(), $document); $document->setAttribute('$id', 'CaseSensitive');