Skip to content

Commit 78529fe

Browse files
github-actions[bot]claude-bot
authored andcommitted
(fix): CI — propagate skipDuplicates through Database → Adapter → Permissions hook
The feat-query-lib branch merged skipDuplicates support into Mirror / Adapter but the Database layer's skipDuplicates(callback) only flipped a dynamic property and never propagated to the adapter, so INSERT IGNORE was never emitted. - Database: declare protected bool $skipDuplicates so the flag is real. - Traits/Documents::createDocuments: when $this->skipDuplicates is set, wrap each batch with $this->adapter->skipDuplicates(...) so the adapter flag is live during the INSERT. - Hook/WriteContext: add a bool $skipDuplicates field so write hooks can see the mode in effect for the parent INSERT. - Adapter/SQL::buildWriteContext: pass the adapter's $skipDuplicates through to the context. - Hook/Permissions::afterDocumentCreate: use $permBuilder->insertOrIgnore() when the context signals skipDuplicates. Without this, destination backfill under skipDuplicates hit 1062 on the _perms unique index when a row already existed on source with the same permissions. Verified: MirrorTest now green (653 tests, 0 failures).
1 parent 3f277c1 commit 78529fe

5 files changed

Lines changed: 10 additions & 4 deletions

File tree

src/Database/Adapter/SQL.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2919,6 +2919,7 @@ protected function buildWriteContext(string $collection): WriteContext
29192919
decorateRow: fn (array $row, array $metadata) => $this->decorateRow($row, $metadata),
29202920
createBuilder: fn () => $this->createBuilder(),
29212921
getTableRaw: fn (string $table) => $this->getSQLTableRaw($table),
2922+
skipDuplicates: $this->skipDuplicates,
29222923
);
29232924
}
29242925

src/Database/Database.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,8 @@ class Database
298298

299299
protected bool $preserveSequence = false;
300300

301+
protected bool $skipDuplicates = false;
302+
301303
protected int $maxQueryValues = 5000;
302304

303305
protected bool $migrating = false;

src/Database/Hook/Permissions.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public function afterDocumentCreate(string $collection, array $documents, WriteC
4444
}
4545

4646
if ($hasPermissions) {
47-
$result = $permBuilder->insert();
47+
$result = $context->skipDuplicates ? $permBuilder->insertOrIgnore() : $permBuilder->insert();
4848
$stmt = ($context->executeResult)($result, Event::PermissionsCreate);
4949
($context->execute)($stmt);
5050
}

src/Database/Hook/WriteContext.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
* @param Closure(array<string, mixed>, array<string, mixed>): array<string, mixed> $decorateRow Apply all write hooks' decorateRow to a row
1919
* @param Closure(): \Utopia\Query\Builder\SQL $createBuilder Create a raw builder (no hooks, no table)
2020
* @param Closure(string): string $getTableRaw Get the raw SQL table name with namespace prefix
21+
* @param bool $skipDuplicates Whether duplicate-key errors should be swallowed by this write
2122
*/
2223
public function __construct(
2324
public Closure $newBuilder,
@@ -26,6 +27,7 @@ public function __construct(
2627
public Closure $decorateRow,
2728
public Closure $createBuilder,
2829
public Closure $getTableRaw,
30+
public bool $skipDuplicates = false,
2931
) {
3032
}
3133
}

src/Database/Traits/Documents.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -556,9 +556,10 @@ public function createDocuments(
556556
}
557557

558558
foreach (\array_chunk($documents, $batchSize) as $chunk) {
559-
$batch = $this->withTransaction(function () use ($collection, $chunk) {
560-
return $this->adapter->createDocuments($collection, $chunk);
561-
});
559+
$insert = fn () => $this->withTransaction(fn () => $this->adapter->createDocuments($collection, $chunk));
560+
$batch = $this->skipDuplicates
561+
? $this->adapter->skipDuplicates($insert)
562+
: $insert();
562563

563564
$batch = $this->adapter->getSequences($collection->getId(), $batch);
564565

0 commit comments

Comments
 (0)