diff options
author | Théophane Hufschmitt <7226587+thufschmitt@users.noreply.github.com> | 2022-04-21 10:30:22 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-04-21 10:30:22 +0200 |
commit | d6efc07f85514d854dcd2adb7e21020019cad6c6 (patch) | |
tree | 4898577fd5b1e2ad3fd9beb800936ea7ed3a7ebe /src | |
parent | 3db663a3e4749382e30308b25a3809314a882d7d (diff) | |
parent | 0155a3b3da32a26becb259c546b98c93f7e414f2 (diff) |
Merge pull request #5479 from NixOS/selfref-ca
Fix the removal of ca-induced self-references
Diffstat (limited to 'src')
-rw-r--r-- | src/libstore/ca-specific-schema.sql | 15 | ||||
-rw-r--r-- | src/libstore/local-store.cc | 17 |
2 files changed, 31 insertions, 1 deletions
diff --git a/src/libstore/ca-specific-schema.sql b/src/libstore/ca-specific-schema.sql index 64cc97fde..4ca91f585 100644 --- a/src/libstore/ca-specific-schema.sql +++ b/src/libstore/ca-specific-schema.sql @@ -13,12 +13,27 @@ create table if not exists Realisations ( create index if not exists IndexRealisations on Realisations(drvPath, outputName); +-- We can end-up in a weird edge-case where a path depends on itself because +-- it’s an output of a CA derivation, that happens to be the same as one of its +-- dependencies. +-- In that case we have a dependency loop (path -> realisation1 -> realisation2 +-- -> path) that we need to break by removing the dependencies between the +-- realisations +create trigger if not exists DeleteSelfRefsViaRealisations before delete on ValidPaths + begin + delete from RealisationsRefs where realisationReference in ( + select id from Realisations where outputPath = old.id + ); + end; + create table if not exists RealisationsRefs ( referrer integer not null, realisationReference integer, foreign key (referrer) references Realisations(id) on delete cascade, foreign key (realisationReference) references Realisations(id) on delete restrict ); +-- used by deletion trigger +create index if not exists IndexRealisationsRefsRealisationReference on RealisationsRefs(realisationReference); -- used by QueryRealisationReferences create index if not exists IndexRealisationsRefs on RealisationsRefs(referrer); diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index ece5bb5ef..5cc5c91cc 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -81,7 +81,7 @@ int getSchema(Path schemaPath) void migrateCASchema(SQLite& db, Path schemaPath, AutoCloseFD& lockFd) { - const int nixCASchemaVersion = 3; + const int nixCASchemaVersion = 4; int curCASchema = getSchema(schemaPath); if (curCASchema != nixCASchemaVersion) { if (curCASchema > nixCASchemaVersion) { @@ -143,6 +143,21 @@ void migrateCASchema(SQLite& db, Path schemaPath, AutoCloseFD& lockFd) )"); txn.commit(); } + if (curCASchema < 4) { + SQLiteTxn txn(db); + db.exec(R"( + create trigger if not exists DeleteSelfRefsViaRealisations before delete on ValidPaths + begin + delete from RealisationsRefs where realisationReference in ( + select id from Realisations where outputPath = old.id + ); + end; + -- used by deletion trigger + create index if not exists IndexRealisationsRefsRealisationReference on RealisationsRefs(realisationReference); + )"); + txn.commit(); + } + writeFile(schemaPath, fmt("%d", nixCASchemaVersion)); lockFile(lockFd.get(), ltRead, true); } |