@@ -1726,6 +1726,12 @@ public function deleteDocument(Document $collection, string $id): bool
17261726 return true ;
17271727 }
17281728
1729+ /**
1730+ * Deletes only the rows that match every one of the deletionFilters().
1731+ *
1732+ * @param array<string> $sequences
1733+ * @param array<string> $permissionIds
1734+ */
17291735 #[\Override]
17301736 public function deleteDocuments (Document $ collection , array $ sequences , array $ permissionIds ): int
17311737 {
@@ -1734,52 +1740,59 @@ public function deleteDocuments(Document $collection, array $sequences, array $p
17341740 throw new NotFoundException ('Collection not found ' );
17351741 }
17361742
1737- $ seqSet = [];
1738- foreach ($ sequences as $ seq ) {
1739- $ seqSet [(string ) $ seq ] = true ;
1743+ $ sequenceSet = [];
1744+ foreach ($ sequences as $ sequence ) {
1745+ $ sequenceSet [(string ) $ sequence ] = true ;
17401746 }
17411747
1748+ $ filters = Query::groupByType ($ this ->deletionFilters ())->filters ;
17421749 $ count = 0 ;
17431750 $ deletedIds = [];
1744- foreach ($ this ->data [$ key ]['documents ' ] as $ docKey => $ row ) {
1751+ $ keptIds = [];
1752+ foreach ($ this ->data [$ key ]['documents ' ] as $ storageKey => $ row ) {
17451753 // With sharedTables the row map is keyed by "tenant|uid" so sequence
17461754 // collisions across tenants are possible. Skip rows that don't belong
17471755 // to the current tenant so we never delete another tenant's data.
17481756 if ($ this ->sharedTables && ($ row [Storage::TENANT ] ?? null ) !== $ this ->getTenant ()) {
17491757 continue ;
17501758 }
17511759 $ rowId = $ row [Storage::SEQUENCE ] ?? '' ;
1752- $ rowUid = $ row [Storage::UID ] ?? $ docKey ;
1753- if (isset ($ seqSet [\is_scalar ($ rowId ) ? (string ) $ rowId : '' ])) {
1754- $ deletedIds [\is_scalar ($ rowUid ) ? (string ) $ rowUid : $ docKey ] = true ;
1760+ $ rowUid = $ row [Storage::UID ] ?? $ storageKey ;
1761+ if (isset ($ sequenceSet [\is_scalar ($ rowId ) ? (string ) $ rowId : '' ])) {
1762+ if (! $ this ->matchesAll ($ row , $ filters )) {
1763+ $ keptIds [\is_scalar ($ rowUid ) ? (string ) $ rowUid : $ storageKey ] = true ;
1764+
1765+ continue ;
1766+ }
1767+ $ deletedIds [\is_scalar ($ rowUid ) ? (string ) $ rowUid : $ storageKey ] = true ;
17551768 $ oldSignatures = $ this ->rowUniqueSignatures ($ key , $ row );
1756- unset($ this ->data [$ key ]['documents ' ][$ docKey ]);
1757- $ this ->journal (function () use ($ key , $ docKey , $ row ): void {
1758- $ this ->data [$ key ]['documents ' ][$ docKey ] = $ row ;
1769+ unset($ this ->data [$ key ]['documents ' ][$ storageKey ]);
1770+ $ this ->journal (function () use ($ key , $ storageKey , $ row ): void {
1771+ $ this ->data [$ key ]['documents ' ][$ storageKey ] = $ row ;
17591772 });
17601773 foreach ($ oldSignatures as $ indexId => $ hash ) {
1761- if (($ this ->uniqueIndexHashes [$ key ][$ indexId ][$ hash ] ?? null ) === $ docKey ) {
1774+ if (($ this ->uniqueIndexHashes [$ key ][$ indexId ][$ hash ] ?? null ) === $ storageKey ) {
17621775 unset($ this ->uniqueIndexHashes [$ key ][$ indexId ][$ hash ]);
1763- $ this ->journal (function () use ($ key , $ indexId , $ hash , $ docKey ): void {
1764- $ this ->uniqueIndexHashes [$ key ][$ indexId ][$ hash ] = $ docKey ;
1776+ $ this ->journal (function () use ($ key , $ indexId , $ hash , $ storageKey ): void {
1777+ $ this ->uniqueIndexHashes [$ key ][$ indexId ][$ hash ] = $ storageKey ;
17651778 });
17661779 }
17671780 }
17681781 $ count ++;
17691782 }
17701783 }
17711784
1772- $ permSet = ! empty ($ permissionIds )
1785+ $ permissionSet = ! empty ($ permissionIds )
17731786 ? \array_flip (\array_map ('strval ' , $ permissionIds ))
17741787 : [];
17751788
1776- if (! empty ($ deletedIds ) || ! empty ($ permSet )) {
1789+ if (! empty ($ deletedIds ) || ! empty ($ permissionSet )) {
17771790 $ tenant = $ this ->getTenant ();
17781791 foreach (\array_keys ($ deletedIds ) as $ documentId ) {
17791792 $ this ->removePermissionsForDocument ($ key , (string ) $ documentId , $ tenant , $ this ->sharedTables );
17801793 }
1781- foreach (\array_keys ($ permSet ) as $ documentId ) {
1782- if (isset ($ deletedIds [$ documentId ])) {
1794+ foreach (\array_keys ($ permissionSet ) as $ documentId ) {
1795+ if (isset ($ deletedIds [$ documentId ]) || isset ( $ keptIds [ $ documentId ]) ) {
17831796 continue ;
17841797 }
17851798 $ this ->removePermissionsForDocument ($ key , (string ) $ documentId , $ tenant , $ this ->sharedTables );
@@ -2432,6 +2445,21 @@ protected function fusedFilter(string $key, string $collectionId, array $queries
24322445 return $ output ;
24332446 }
24342447
2448+ /**
2449+ * @param array<string, mixed> $row
2450+ * @param array<Query> $queries
2451+ */
2452+ private function matchesAll (array $ row , array $ queries ): bool
2453+ {
2454+ foreach ($ queries as $ query ) {
2455+ if (! $ this ->matches ($ row , $ query )) {
2456+ return false ;
2457+ }
2458+ }
2459+
2460+ return true ;
2461+ }
2462+
24352463 /**
24362464 * @param array<string, mixed> $row
24372465 */
0 commit comments