diff --git a/src/Database/Database.php b/src/Database/Database.php index 93a36b23a..d4e2dc151 100644 --- a/src/Database/Database.php +++ b/src/Database/Database.php @@ -3970,15 +3970,15 @@ public function updateDocument(string $collection, string $id, Document $documen * @param array $queries * @param int $batchSize * - * @return int + * @return array * * @throws AuthorizationException * @throws DatabaseException */ - public function updateDocuments(string $collection, Document $updates, array $queries = [], int $batchSize = self::INSERT_BATCH_SIZE): int + public function updateDocuments(string $collection, Document $updates, array $queries = [], int $batchSize = self::INSERT_BATCH_SIZE): array { if ($updates->isEmpty()) { - return 0; + return []; } $collection = $this->silent(fn () => $this->getCollection($collection)); @@ -4033,11 +4033,9 @@ public function updateDocuments(string $collection, Document $updates, array $qu throw new StructureException($validator->getDescription()); } - $affectedDocumentIds = []; - - $affected = $this->withTransaction(function () use ($collection, $queries, $batchSize, $updates, $limit, $cursor, $affectedDocumentIds) { + $documents = $this->withTransaction(function () use ($collection, $queries, $batchSize, $updates, $limit, $cursor) { $lastDocument = null; - $totalModified = 0; + $documents = []; $documentSecurity = $collection->getAttribute('documentSecurity', false); @@ -4075,12 +4073,10 @@ public function updateDocuments(string $collection, Document $updates, array $qu foreach ($affectedDocuments as $document) { if ($this->resolveRelationships) { - $newDocument = array_merge($document->getArrayCopy(), $updates->getArrayCopy()); - - $this->silent(fn () => $this->updateDocumentRelationships($collection, $document, new Document($newDocument))); + $newDocument = new Document(array_merge($document->getArrayCopy(), $updates->getArrayCopy())); + $this->silent(fn () => $this->updateDocumentRelationships($collection, $document, $newDocument)); + $documents[] = $newDocument; } - - $affectedDocumentIds[] = $document->getId(); } $getResults = fn () => $this->adapter->updateDocuments( @@ -4089,33 +4085,27 @@ public function updateDocuments(string $collection, Document $updates, array $qu $affectedDocuments ); - $result = $skipAuth ? $authorization->skip($getResults) : $getResults(); - - $totalModified += $result; + $skipAuth ? $authorization->skip($getResults) : $getResults(); if (count($affectedDocuments) < $batchSize) { break; - } elseif ($originalLimit && count($affectedDocumentIds) == $originalLimit) { + } elseif ($originalLimit && count($documents) == $originalLimit) { break; } $lastDocument = end($affectedDocuments); } - $this->trigger(self::EVENT_DOCUMENTS_UPDATE, new Document([ - '$collection' => $collection->getId(), - 'modified' => $affectedDocumentIds, - ])); - - foreach ($affectedDocumentIds as $id) { - $this->purgeRelatedDocuments($collection, $id); - $this->purgeCachedDocument($collection->getId(), $id); + foreach ($documents as $document) { + $this->purgeRelatedDocuments($collection, $document->getId()); + $this->purgeCachedDocument($collection->getId(), $document->getId()); + $this->trigger(self::EVENT_DOCUMENT_UPDATE, $document); } - return $totalModified; + return $documents; }); - return $affected; + return $documents; } /** @@ -5150,13 +5140,13 @@ private function deleteCascade(Document $collection, Document $relatedCollection * @param array $queries * @param int $batchSize * - * @return int + * @return array * * @throws AuthorizationException * @throws DatabaseException * @throws RestrictedException */ - public function deleteDocuments(string $collection, array $queries = [], int $batchSize = self::DELETE_BATCH_SIZE): int + public function deleteDocuments(string $collection, array $queries = [], int $batchSize = self::DELETE_BATCH_SIZE): array { if ($this->adapter->getSharedTables() && empty($this->adapter->getTenant())) { throw new DatabaseException('Missing tenant. Tenant must be set when table sharing is enabled.'); @@ -5193,12 +5183,11 @@ public function deleteDocuments(string $collection, array $queries = [], int $ba throw new DatabaseException("cursor Document must be from the same Collection."); } - $affectedDocumentIds = []; - - $deleted = $this->withTransaction(function () use ($collection, $queries, $batchSize, $affectedDocumentIds, $limit, $cursor) { + $documents = $this->withTransaction(function () use ($collection, $queries, $batchSize, $limit, $cursor) { $documentSecurity = $collection->getAttribute('documentSecurity', false); $authorization = new Authorization(self::PERMISSION_DELETE); $skipAuth = $authorization->isValid($collection->getDelete()); + $documents = []; if (!$skipAuth && !$documentSecurity && $collection->getId() !== self::METADATA) { throw new AuthorizationException($authorization->getDescription()); @@ -5228,7 +5217,7 @@ public function deleteDocuments(string $collection, array $queries = [], int $ba break; } - $affectedDocumentIds = array_merge($affectedDocumentIds, array_map(fn ($document) => $document->getId(), $affectedDocuments)); + $documents = array_merge($affectedDocuments, $documents); foreach ($affectedDocuments as $document) { // Delete Relationships @@ -5242,27 +5231,27 @@ public function deleteDocuments(string $collection, array $queries = [], int $ba if (count($affectedDocuments) < $batchSize) { break; - } elseif ($originalLimit && count($affectedDocumentIds) == $originalLimit) { + } elseif ($originalLimit && count($documents) == $originalLimit) { break; } $lastDocument = end($affectedDocuments); } - if (empty($affectedDocumentIds)) { - return 0; + if (empty($documents)) { + return []; } - $this->trigger(self::EVENT_DOCUMENTS_DELETE, new Document([ - '$collection' => $collection->getId(), - 'modified' => $affectedDocumentIds - ])); + foreach ($documents as $document) { + $this->trigger(self::EVENT_DOCUMENT_DELETE, $document); + } + + $this->adapter->deleteDocuments($collection->getId(), array_map(fn ($document) => $document->getId(), $documents)); - // Mass delete using adapter with query - return $this->adapter->deleteDocuments($collection->getId(), $affectedDocumentIds); + return $documents; }); - return $deleted; + return $documents; } /** diff --git a/src/Database/Mirror.php b/src/Database/Mirror.php index a01a72022..f21b97f43 100644 --- a/src/Database/Mirror.php +++ b/src/Database/Mirror.php @@ -662,19 +662,19 @@ public function updateDocuments( Document $updates, array $queries = [], int $batchSize = self::INSERT_BATCH_SIZE - ): int { - $count = $this->source->updateDocuments($collection, $updates, $queries, $batchSize); + ): array { + $documents = $this->source->updateDocuments($collection, $updates, $queries, $batchSize); if ( \in_array($collection, self::SOURCE_ONLY_COLLECTIONS) || $this->destination === null ) { - return $count; + return $documents; } $upgrade = $this->silent(fn () => $this->getUpgradeStatus($collection)); if ($upgrade === null || $upgrade->getAttribute('status', '') !== 'upgraded') { - return $count; + return $documents; } try { @@ -707,7 +707,7 @@ public function updateDocuments( $this->logError('updateDocuments', $err); } - return $count; + return $documents; } public function deleteDocument(string $collection, string $id): bool @@ -753,20 +753,20 @@ public function deleteDocument(string $collection, string $id): bool return $result; } - public function deleteDocuments(string $collection, array $queries = [], int $batchSize = self::DELETE_BATCH_SIZE): int + public function deleteDocuments(string $collection, array $queries = [], int $batchSize = self::DELETE_BATCH_SIZE): array { - $count = $this->source->deleteDocuments($collection, $queries, $batchSize); + $documents = $this->source->deleteDocuments($collection, $queries, $batchSize); if ( \in_array($collection, self::SOURCE_ONLY_COLLECTIONS) || $this->destination === null ) { - return $count; + return $documents; } $upgrade = $this->silent(fn () => $this->getUpgradeStatus($collection)); if ($upgrade === null || $upgrade->getAttribute('status', '') !== 'upgraded') { - return $count; + return $documents; } try { @@ -793,7 +793,7 @@ public function deleteDocuments(string $collection, array $queries = [], int $ba $this->logError('deleteDocuments', $err); } - return $count; + return $documents; } public function updateAttributeRequired(string $collection, string $id, bool $required): Document diff --git a/tests/e2e/Adapter/Base.php b/tests/e2e/Adapter/Base.php index 72622dd31..ea18ea2a7 100644 --- a/tests/e2e/Adapter/Base.php +++ b/tests/e2e/Adapter/Base.php @@ -15897,8 +15897,7 @@ public function testDeleteBulkDocuments(): void $this->assertCount(10, $docs); // TEST: Bulk Delete All Documents - $deleted = static::getDatabase()->deleteDocuments('bulk_delete'); - $this->assertEquals(10, $deleted); + $this->assertCount(10, static::getDatabase()->deleteDocuments('bulk_delete')); $docs = static::getDatabase()->find('bulk_delete'); $this->assertCount(0, $docs); @@ -15906,10 +15905,14 @@ public function testDeleteBulkDocuments(): void // TEST: Bulk delete documents with queries. $this->propegateBulkDocuments('bulk_delete'); - $deleted = static::getDatabase()->deleteDocuments('bulk_delete', [ + $modified = static::getDatabase()->deleteDocuments('bulk_delete', [ Query::greaterThanEqual('integer', 5) ]); - $this->assertEquals(5, $deleted); + $this->assertCount(5, $modified); + + foreach ($modified as $document) { + $this->assertGreaterThanOrEqual(5, $document->getAttribute('integer')); + } $docs = static::getDatabase()->find('bulk_delete'); $this->assertCount(5, $docs); @@ -15927,9 +15930,8 @@ public function testDeleteBulkDocuments(): void Permission::read(Role::any()), Permission::delete(Role::any()) ], false); - $deleted = static::getDatabase()->deleteDocuments('bulk_delete'); - $this->assertEquals(5, $deleted); + $this->assertCount(5, static::getDatabase()->deleteDocuments('bulk_delete')); $this->assertEquals(0, count($this->getDatabase()->find('bulk_delete'))); // TEST: Make sure we can't delete documents we don't have permissions for @@ -15938,8 +15940,7 @@ public function testDeleteBulkDocuments(): void ], true); $this->propegateBulkDocuments('bulk_delete', documentSecurity: true); - $deleted = static::getDatabase()->deleteDocuments('bulk_delete'); - $this->assertEquals(0, $deleted); + $this->assertCount(0, static::getDatabase()->deleteDocuments('bulk_delete')); $documents = Authorization::skip(function () { return static::getDatabase()->find('bulk_delete'); @@ -15967,7 +15968,7 @@ public function testDeleteBulkDocumentsQueries(): void } static::getDatabase()->createCollection( - 'bulk_delete', + 'bulk_delete_queries', attributes: [ new Document([ '$id' => 'text', @@ -15991,36 +15992,36 @@ public function testDeleteBulkDocumentsQueries(): void ); // Test limit - $this->propegateBulkDocuments('bulk_delete'); + $this->propegateBulkDocuments('bulk_delete_queries'); - $this->assertEquals(5, static::getDatabase()->deleteDocuments('bulk_delete', [Query::limit(5)])); - $this->assertCount(5, static::getDatabase()->find('bulk_delete')); + $this->assertCount(5, static::getDatabase()->deleteDocuments('bulk_delete_queries', [Query::limit(5)])); + $this->assertCount(5, static::getDatabase()->find('bulk_delete_queries')); - $this->assertEquals(5, static::getDatabase()->deleteDocuments('bulk_delete', [Query::limit(5)])); - $this->assertCount(0, static::getDatabase()->find('bulk_delete')); + $this->assertCount(5, static::getDatabase()->deleteDocuments('bulk_delete_queries', [Query::limit(5)])); + $this->assertCount(0, static::getDatabase()->find('bulk_delete_queries')); // Test Limit more than batchSize - $this->propegateBulkDocuments('bulk_delete', Database::DELETE_BATCH_SIZE * 2); - $this->assertCount(Database::DELETE_BATCH_SIZE * 2, static::getDatabase()->find('bulk_delete', [Query::limit(200)])); + $this->propegateBulkDocuments('bulk_delete_queries', Database::DELETE_BATCH_SIZE * 2); + $this->assertCount(Database::DELETE_BATCH_SIZE * 2, static::getDatabase()->find('bulk_delete_queries', [Query::limit(200)])); - $this->assertEquals(Database::DELETE_BATCH_SIZE + 2, static::getDatabase()->deleteDocuments('bulk_delete', [Query::limit(Database::DELETE_BATCH_SIZE + 2)])); + $this->assertCount(Database::DELETE_BATCH_SIZE + 2, static::getDatabase()->deleteDocuments('bulk_delete_queries', [Query::limit(Database::DELETE_BATCH_SIZE + 2)])); - $this->assertCount(Database::DELETE_BATCH_SIZE - 2, static::getDatabase()->find('bulk_delete', [Query::limit(200)])); - $this->assertEquals(Database::DELETE_BATCH_SIZE - 2, $this->getDatabase()->deleteDocuments('bulk_delete')); + $this->assertCount(Database::DELETE_BATCH_SIZE - 2, static::getDatabase()->find('bulk_delete_queries', [Query::limit(200)])); + $this->assertCount(Database::DELETE_BATCH_SIZE - 2, $this->getDatabase()->deleteDocuments('bulk_delete_queries')); // Test Offset - $this->propegateBulkDocuments('bulk_delete', 100); - $this->assertEquals(50, static::getDatabase()->deleteDocuments('bulk_delete', [Query::offset(50)])); + $this->propegateBulkDocuments('bulk_delete_queries', 100); + $this->assertCount(50, static::getDatabase()->deleteDocuments('bulk_delete_queries', [Query::offset(50)])); - $docs = static::getDatabase()->find('bulk_delete', [Query::limit(100)]); + $docs = static::getDatabase()->find('bulk_delete_queries', [Query::limit(100)]); $this->assertCount(50, $docs); $lastDoc = end($docs); $this->assertNotEmpty($lastDoc); $this->assertEquals('doc49', $lastDoc->getId()); - $this->assertEquals(50, static::getDatabase()->deleteDocuments('bulk_delete')); + $this->assertCount(50, static::getDatabase()->deleteDocuments('bulk_delete_queries')); - static::getDatabase()->deleteCollection('bulk_delete'); + static::getDatabase()->deleteCollection('bulk_delete_queries'); } public function testDeleteBulkDocumentsOneToOneRelationship(): void @@ -16604,22 +16605,26 @@ public function testUpdateDocuments(): void } // Test Update half of the documents - $affected = static::getDatabase()->updateDocuments($collection, new Document([ + $modified = static::getDatabase()->updateDocuments($collection, new Document([ 'string' => 'text📝 updated', ]), [ Query::greaterThanEqual('integer', 5), ]); + $this->assertCount(5, $modified); - $this->assertEquals($affected, 5); + foreach ($modified as $document) { + $this->assertEquals('text📝 updated', $document->getAttribute('string')); + } $updatedDocuments = static::getDatabase()->find($collection, [ Query::greaterThanEqual('integer', 5), ]); - $this->assertEquals(count($updatedDocuments), 5); + $this->assertCount(5, $updatedDocuments); foreach ($updatedDocuments as $document) { $this->assertEquals('text📝 updated', $document->getAttribute('string')); + $this->assertGreaterThanOrEqual(5, $document->getAttribute('integer')); } $controlDocuments = static::getDatabase()->find($collection, [ @@ -16633,11 +16638,9 @@ public function testUpdateDocuments(): void } // Test Update all documents - $affected = static::getDatabase()->updateDocuments($collection, new Document([ + $this->assertCount(10, static::getDatabase()->updateDocuments($collection, new Document([ 'string' => 'text📝 updated all', - ])); - - $this->assertEquals(10, $affected); + ]))); $updatedDocuments = static::getDatabase()->find($collection); @@ -16711,14 +16714,12 @@ public function testUpdateDocuments(): void }); // Test we can update more documents than batchSize - $affected = static::getDatabase()->updateDocuments($collection, new Document([ + $this->assertCount(10, static::getDatabase()->updateDocuments($collection, new Document([ 'string' => 'batchSize Test' - ]), batchSize: 2); + ]), batchSize: 2)); $documents = static::getDatabase()->find($collection); - $this->assertEquals(10, $affected); - foreach ($documents as $document) { $this->assertEquals('batchSize Test', $document->getAttribute('string')); } @@ -16759,23 +16760,19 @@ public function testUpdateDocumentsQueries(): void // Test limit $this->propegateBulkDocuments($collection, 100); - $affected = static::getDatabase()->updateDocuments($collection, new Document([ + $this->assertCount(10, static::getDatabase()->updateDocuments($collection, new Document([ 'text' => 'text📝 updated', - ]), [Query::limit(10)]); - - $this->assertEquals(10, $affected); + ]), [Query::limit(10)])); $this->assertCount(10, static::getDatabase()->find($collection, [Query::equal('text', ['text📝 updated'])])); - $this->assertEquals(100, static::getDatabase()->deleteDocuments($collection)); + $this->assertCount(100, static::getDatabase()->deleteDocuments($collection)); $this->assertCount(0, static::getDatabase()->find($collection)); // Test Offset $this->propegateBulkDocuments($collection, 100); - - $affected = static::getDatabase()->updateDocuments($collection, new Document([ + $this->assertCount(50, static::getDatabase()->updateDocuments($collection, new Document([ 'text' => 'text📝 updated', - ]), [Query::offset(50)]); + ]), [Query::offset(50)])); - $this->assertEquals(50, $affected); $docs = static::getDatabase()->find($collection, [Query::equal('text', ['text📝 updated']), Query::limit(100)]); $this->assertCount(50, $docs); @@ -16783,7 +16780,7 @@ public function testUpdateDocumentsQueries(): void $this->assertNotEmpty($lastDoc); $this->assertEquals('doc99', $lastDoc->getId()); - $this->assertEquals(100, static::getDatabase()->deleteDocuments($collection)); + $this->assertCount(100, static::getDatabase()->deleteDocuments($collection)); } public function testUpdateDocumentsPermissions(): void @@ -16844,7 +16841,7 @@ public function testUpdateDocumentsPermissions(): void return static::getDatabase()->find($collection); }); - $this->assertEquals(10, $affected); + $this->assertCount(10, $affected); $this->assertCount(11, $documents); $modifiedDocuments = array_filter($documents, function (Document $document) { @@ -16882,7 +16879,7 @@ public function testUpdateDocumentsPermissions(): void 'string' => 'text📝 updated', ])); - $this->assertEquals(10, $affected); + $this->assertCount(10, $affected); $documents = Authorization::skip(function () use ($collection) { return $this->getDatabase()->find($collection); @@ -17040,10 +17037,13 @@ public function testEvents(): void Database::EVENT_DOCUMENT_INCREASE, Database::EVENT_DOCUMENT_DECREASE, Database::EVENT_DOCUMENTS_CREATE, - Database::EVENT_DOCUMENTS_UPDATE, + Database::EVENT_DOCUMENT_UPDATE, + Database::EVENT_DOCUMENT_UPDATE, + Database::EVENT_DOCUMENT_UPDATE, Database::EVENT_INDEX_DELETE, Database::EVENT_DOCUMENT_DELETE, - Database::EVENT_DOCUMENTS_DELETE, + Database::EVENT_DOCUMENT_DELETE, + Database::EVENT_DOCUMENT_DELETE, Database::EVENT_ATTRIBUTE_DELETE, Database::EVENT_COLLECTION_DELETE, Database::EVENT_DATABASE_DELETE @@ -17051,7 +17051,6 @@ public function testEvents(): void $database->on(Database::EVENT_ALL, 'test', function ($event, $data) use (&$events) { $shifted = array_shift($events); - $this->assertEquals($shifted, $event); }); @@ -17118,6 +17117,7 @@ public function testEvents(): void $database->deleteIndex($collectionId, $indexId1); $database->deleteDocument($collectionId, 'doc1'); + $database->deleteDocuments($collectionId); $database->deleteAttribute($collectionId, 'attr1'); $database->deleteCollection($collectionId);