Skip to content

Commit 20846d3

Browse files
committed
Defer relationship creation in ignore mode to prevent orphaned relationships
1 parent b9c7f4d commit 20846d3

1 file changed

Lines changed: 44 additions & 5 deletions

File tree

src/Database/Database.php

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5725,6 +5725,12 @@ public function createDocuments(
57255725
}
57265726
}
57275727

5728+
// For ignore mode: defer relationship creation until after INSERT
5729+
$deferredRelationships = [];
5730+
$relationships = $ignore && $this->resolveRelationships
5731+
? \array_filter($collection->getAttribute('attributes', []), fn ($attr) => $attr['type'] === self::VAR_RELATIONSHIP)
5732+
: [];
5733+
57285734
foreach ($documents as $document) {
57295735
$createdAt = $document->getCreatedAt();
57305736
$updatedAt = $document->getUpdatedAt();
@@ -5765,12 +5771,30 @@ public function createDocuments(
57655771
}
57665772

57675773
if ($this->resolveRelationships) {
5768-
$preExistKey = $tenantPerDocument
5769-
? $document->getTenant() . ':' . $document->getId()
5770-
: $document->getId();
5774+
if ($ignore) {
5775+
// In ignore mode, defer relationship creation until after INSERT
5776+
// to avoid orphaned relationships from race-condition duplicates.
5777+
// Store original relationship data and strip attributes for INSERT.
5778+
$relationshipData = [];
5779+
foreach ($relationships as $rel) {
5780+
$key = $rel['key'];
5781+
$value = $document->getAttribute($key);
5782+
if ($value !== null) {
5783+
$relationshipData[$key] = $value;
5784+
}
5785+
$document->removeAttribute($key);
5786+
}
5787+
if (!empty($relationshipData)) {
5788+
$deferredRelationships[$document->getId()] = $relationshipData;
5789+
}
5790+
} else {
5791+
$preExistKey = $tenantPerDocument
5792+
? $document->getTenant() . ':' . $document->getId()
5793+
: $document->getId();
57715794

5772-
if (!isset($preExistingIds[$preExistKey])) {
5773-
$document = $this->silent(fn () => $this->createDocumentRelationships($collection, $document));
5795+
if (!isset($preExistingIds[$preExistKey])) {
5796+
$document = $this->silent(fn () => $this->createDocumentRelationships($collection, $document));
5797+
}
57745798
}
57755799
}
57765800

@@ -5794,6 +5818,21 @@ public function createDocuments(
57945818
return $this->adapter->createDocuments($collection, $chunk, $ignore);
57955819
});
57965820

5821+
// In ignore mode, create relationships only for docs actually inserted
5822+
if ($ignore && $this->resolveRelationships && !empty($deferredRelationships)) {
5823+
foreach ($batch as $insertedDoc) {
5824+
$docId = $insertedDoc->getId();
5825+
if (isset($deferredRelationships[$docId])) {
5826+
$relDoc = clone $insertedDoc;
5827+
foreach ($deferredRelationships[$docId] as $key => $value) {
5828+
$relDoc->setAttribute($key, $value);
5829+
}
5830+
$this->silent(fn () => $this->createDocumentRelationships($collection, $relDoc));
5831+
unset($deferredRelationships[$docId]);
5832+
}
5833+
}
5834+
}
5835+
57975836
$batch = $this->adapter->getSequences($collection->getId(), $batch);
57985837

57995838
if (!$this->inBatchRelationshipPopulation && $this->resolveRelationships) {

0 commit comments

Comments
 (0)