aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorThéophane Hufschmitt <7226587+thufschmitt@users.noreply.github.com>2022-04-21 10:30:22 +0200
committerGitHub <noreply@github.com>2022-04-21 10:30:22 +0200
commitd6efc07f85514d854dcd2adb7e21020019cad6c6 (patch)
tree4898577fd5b1e2ad3fd9beb800936ea7ed3a7ebe /src
parent3db663a3e4749382e30308b25a3809314a882d7d (diff)
parent0155a3b3da32a26becb259c546b98c93f7e414f2 (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.sql15
-rw-r--r--src/libstore/local-store.cc17
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);
}