forked from ish-app/ish
-
Notifications
You must be signed in to change notification settings - Fork 0
/
fake-migrate.c
61 lines (56 loc) · 2.14 KB
/
fake-migrate.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include "kernel/fs.h"
#include "debug.h"
#include "kernel/errno.h"
#include "fs/sqlutil.h"
// The value of the user_version pragma is used to decide what needs migrating.
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
static struct migration {
const char *sql;
void (*migrate)(struct mount *mount);
} migrations[] = {
// version 1: add another index
{
"create index inode_to_path on paths (inode, path);"
},
// version 2: add foreign key constraint on paths, create trigger to automatically cleanup stats
{
"create table paths_new (path blob primary key, inode integer references stats(inode));"
"insert into paths_new select * from paths where exists (select 1 from stats where inode = paths.inode);"
"drop table paths; alter table paths_new rename to paths;"
"create index inode_to_path on paths (inode, path);"
"delete from stats where not exists (select 1 from paths where inode = stats.inode);"
"create trigger delete_path after delete on paths "
"when not exists (select 1 from paths where inode = old.inode) "
"begin "
"delete from stats where not exists (select 1 from paths where inode = old.inode) and inode = old.inode; "
"end;"
},
// version 3: the trigger was a mistake
{
"drop trigger delete_path"
},
};
int fakefs_migrate(struct mount *mount) {
sqlite3 *db = mount->db;
int err;
sqlite3_stmt *user_version = PREPARE("pragma user_version");
STEP(user_version);
int version = sqlite3_column_int(user_version, 0);
FINALIZE(user_version);
EXEC("begin");
int versions = sizeof(migrations)/sizeof(migrations[0]);
while (version < versions) {
struct migration m = migrations[version];
if (m.sql != NULL)
EXEC(m.sql);
if (m.migrate != NULL)
m.migrate(mount);
version++;
}
// for some reason placeholders aren't allowed in pragmas
char *pragma_user_version = sqlite3_mprintf("pragma user_version = %d", version);
EXEC(pragma_user_version);
sqlite3_free(pragma_user_version);
EXEC("commit");
return 0;
}