Store the realisation deps on the local store

This commit is contained in:
regnat 2021-05-07 13:57:01 +02:00
parent 7ce0441d80
commit eca6ff06d6
2 changed files with 59 additions and 13 deletions

View file

@ -3,10 +3,19 @@
-- is enabled -- is enabled
create table if not exists Realisations ( create table if not exists Realisations (
id integer primary key autoincrement not null,
drvPath text not null, drvPath text not null,
outputName text not null, -- symbolic output id, usually "out" outputName text not null, -- symbolic output id, usually "out"
outputPath integer not null, outputPath integer not null,
signatures text, -- space-separated list signatures text, -- space-separated list
primary key (drvPath, outputName),
foreign key (outputPath) references ValidPaths(id) on delete cascade foreign key (outputPath) references ValidPaths(id) on delete cascade
); );
create index if not exists IndexRealisations on Realisations(drvPath, outputName);
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
);

View file

@ -59,6 +59,8 @@ struct LocalStore::State::Stmts {
SQLiteStmt QueryAllRealisedOutputs; SQLiteStmt QueryAllRealisedOutputs;
SQLiteStmt QueryPathFromHashPart; SQLiteStmt QueryPathFromHashPart;
SQLiteStmt QueryValidPaths; SQLiteStmt QueryValidPaths;
SQLiteStmt QueryRealisationRealisationReferences;
SQLiteStmt AddRealisationRealisationReference;
}; };
int getSchema(Path schemaPath) int getSchema(Path schemaPath)
@ -316,7 +318,7 @@ LocalStore::LocalStore(const Params & params)
)"); )");
state->stmts->QueryRealisedOutput.create(state->db, state->stmts->QueryRealisedOutput.create(state->db,
R"( R"(
select Output.path, Realisations.signatures from Realisations select Realisations.id, Output.path, Realisations.signatures from Realisations
inner join ValidPaths as Output on Output.id = Realisations.outputPath inner join ValidPaths as Output on Output.id = Realisations.outputPath
where drvPath = ? and outputName = ? where drvPath = ? and outputName = ?
; ;
@ -328,6 +330,19 @@ LocalStore::LocalStore(const Params & params)
where drvPath = ? where drvPath = ?
; ;
)"); )");
state->stmts->QueryRealisationRealisationReferences.create(state->db,
R"(
select drvPath, outputName from Realisations
join RealisationsRefs on realisationReference = Realisations.id
where referrer = ?;
)");
state->stmts->AddRealisationRealisationReference.create(state->db,
R"(
insert or replace into RealisationsRefs (referrer, realisationReference)
values (
?,
(select id from Realisations where drvPath = ? and outputName = ?));
)");
} }
} }
@ -666,13 +681,17 @@ void LocalStore::registerDrvOutput(const Realisation & info)
settings.requireExperimentalFeature("ca-derivations"); settings.requireExperimentalFeature("ca-derivations");
auto state(_state.lock()); auto state(_state.lock());
retrySQLite<void>([&]() { retrySQLite<void>([&]() {
state->stmts->RegisterRealisedOutput.use() state->stmts->RegisterRealisedOutput
(info.id.strHash()) .use()(info.id.strHash())(info.id.outputName)(printStorePath(
(info.id.outputName) info.outPath))(concatStringsSep(" ", info.signatures))
(printStorePath(info.outPath))
(concatStringsSep(" ", info.signatures))
.exec(); .exec();
}); });
uint64_t myId = state->db.getLastInsertedRowId();
for (auto& outputId : info.drvOutputDeps) {
state->stmts->AddRealisationRealisationReference
.use()(myId)(outputId.strHash())(outputId.outputName)
.exec();
}
} }
void LocalStore::cacheDrvOutputMapping(State & state, const uint64_t deriver, const string & outputName, const StorePath & output) void LocalStore::cacheDrvOutputMapping(State & state, const uint64_t deriver, const string & outputName, const StorePath & output)
@ -1670,14 +1689,32 @@ std::optional<const Realisation> LocalStore::queryRealisation(
typedef std::optional<const Realisation> Ret; typedef std::optional<const Realisation> Ret;
return retrySQLite<Ret>([&]() -> Ret { return retrySQLite<Ret>([&]() -> Ret {
auto state(_state.lock()); auto state(_state.lock());
auto use(state->stmts->QueryRealisedOutput.use()(id.strHash())( auto useQueryRealisedOutput(state->stmts->QueryRealisedOutput.use()(
id.outputName)); id.strHash())(id.outputName));
if (!use.next()) if (!useQueryRealisedOutput.next())
return std::nullopt; return std::nullopt;
auto outputPath = parseStorePath(use.getStr(0)); auto realisationDbId = useQueryRealisedOutput.getInt(0);
auto signatures = tokenizeString<StringSet>(use.getStr(1)); auto outputPath = parseStorePath(useQueryRealisedOutput.getStr(1));
auto signatures =
tokenizeString<StringSet>(useQueryRealisedOutput.getStr(2));
std::set<DrvOutput> drvOutputDeps;
auto useRealisationRefs(
state->stmts->QueryRealisationRealisationReferences.use()(
realisationDbId));
while (useRealisationRefs.next())
drvOutputDeps.insert(DrvOutput{
Hash::parseAnyPrefixed(useRealisationRefs.getStr(0)),
useRealisationRefs.getStr(1),
}
);
return Ret{Realisation{ return Ret{Realisation{
.id = id, .outPath = outputPath, .signatures = signatures}}; .id = id,
.outPath = outputPath,
.signatures = signatures,
.drvOutputDeps = drvOutputDeps,
}};
}); });
} }
} // namespace nix } // namespace nix