* Foreign key support in SQLite is not a persistent setting, so enable

it at startup.
* Implement negative caching.  Now `make check' passes.
This commit is contained in:
Eelco Dolstra 2010-02-19 17:15:22 +00:00
parent 9c9a88e9e2
commit 1930570ad9
4 changed files with 25 additions and 29 deletions

View file

@ -209,6 +209,9 @@ LocalStore::LocalStore()
if (sqlite3_busy_timeout(db, 60000) != SQLITE_OK) if (sqlite3_busy_timeout(db, 60000) != SQLITE_OK)
throw SQLiteError(db, "setting timeout"); throw SQLiteError(db, "setting timeout");
if (sqlite3_exec(db, "pragma foreign_keys = 1;", 0, 0, 0) != SQLITE_OK)
throw SQLiteError(db, "enabling foreign keys");
/* !!! check whether sqlite has been built with foreign key /* !!! check whether sqlite has been built with foreign key
support */ support */
@ -288,6 +291,10 @@ void LocalStore::prepareStatements()
"select path from Refs join ValidPaths on referrer = id where reference = (select id from ValidPaths where path = ?);"); "select path from Refs join ValidPaths on referrer = id where reference = (select id from ValidPaths where path = ?);");
stmtInvalidatePath.create(db, stmtInvalidatePath.create(db,
"delete from ValidPaths where path = ?;"); "delete from ValidPaths where path = ?;");
stmtRegisterFailedPath.create(db,
"insert into FailedPaths (path, time) values (?, ?);");
stmtHasPathFailed.create(db,
"select time from FailedPaths where path = ?;");
} }
@ -425,13 +432,23 @@ void LocalStore::registerValidPath(const ValidPathInfo & info)
void LocalStore::registerFailedPath(const Path & path) void LocalStore::registerFailedPath(const Path & path)
{ {
throw Error("not implemented"); if (hasPathFailed(path)) return;
SQLiteStmtUse use(stmtRegisterFailedPath);
stmtRegisterFailedPath.bind(path);
stmtRegisterFailedPath.bind(time(0));
if (sqlite3_step(stmtRegisterFailedPath) != SQLITE_DONE)
throw SQLiteError(db, format("registering failed path `%1%'") % path);
} }
bool LocalStore::hasPathFailed(const Path & path) bool LocalStore::hasPathFailed(const Path & path)
{ {
throw Error("not implemented"); SQLiteStmtUse use(stmtHasPathFailed);
stmtHasPathFailed.bind(path);
int res = sqlite3_step(stmtHasPathFailed);
if (res != SQLITE_DONE && res != SQLITE_ROW)
throw SQLiteError(db, "querying whether path failed");
return res == SQLITE_ROW;
} }

View file

@ -196,6 +196,8 @@ private:
SQLiteStmt stmtQueryReferences; SQLiteStmt stmtQueryReferences;
SQLiteStmt stmtQueryReferrers; SQLiteStmt stmtQueryReferrers;
SQLiteStmt stmtInvalidatePath; SQLiteStmt stmtInvalidatePath;
SQLiteStmt stmtRegisterFailedPath;
SQLiteStmt stmtHasPathFailed;
int getSchema(); int getSchema();

View file

@ -1,5 +1,3 @@
pragma foreign_keys = on;
create table if not exists ValidPaths ( create table if not exists ValidPaths (
id integer primary key autoincrement not null, id integer primary key autoincrement not null,
path text unique not null, path text unique not null,
@ -19,7 +17,7 @@ create table if not exists Refs (
create index if not exists IndexReferrer on Refs(referrer); create index if not exists IndexReferrer on Refs(referrer);
create index if not exists IndexReference on Refs(reference); create index if not exists IndexReference on Refs(reference);
create table if not exists FailedDerivations ( create table if not exists FailedPaths (
path text primary key not null, path text primary key not null,
time integer not null time integer not null
); );

View file

@ -3,6 +3,8 @@ source common.sh
# This takes way to long on Cygwin (because process creation is so slow...). # This takes way to long on Cygwin (because process creation is so slow...).
if test "$system" = i686-cygwin; then exit 0; fi if test "$system" = i686-cygwin; then exit 0; fi
clearStore
max=2500 max=2500
reference=$NIX_STORE_DIR/abcdef reference=$NIX_STORE_DIR/abcdef
@ -25,34 +27,11 @@ echo "registering..."
time $nixstore --register-validity < $TEST_ROOT/reg_info time $nixstore --register-validity < $TEST_ROOT/reg_info
oldTime=$(cat test-tmp/db/info/1 | grep Registered-At)
echo "sleeping..."
sleep 2
echo "reregistering..."
time $nixstore --register-validity --reregister < $TEST_ROOT/reg_info
newTime=$(cat test-tmp/db/info/1 | grep Registered-At)
if test "$newTime" != "$oldTime"; then
echo "reregistration changed original registration time"
exit 1
fi
if test "$(cat test-tmp/db/referrer/1 | wc -w)" -ne 1; then
echo "reregistration duplicated referrers"
exit 1
fi
echo "collecting garbage..." echo "collecting garbage..."
ln -sfn $reference "$NIX_STATE_DIR"/gcroots/ref ln -sfn $reference "$NIX_STATE_DIR"/gcroots/ref
time $nixstore --gc time $nixstore --gc
if test "$(cat test-tmp/db/referrer/abcdef | wc -w)" -ne 0; then if test "$(sqlite3 ./test-tmp/db/db.sqlite 'select count(*) from Refs')" -ne 0; then
echo "referrers not cleaned up" echo "referrers not cleaned up"
exit 1 exit 1
fi fi