Commit | Line | Data |
---|---|---|
7bed5d91 ED |
1 | #pragma once |
2 | ||
3 | #include <functional> | |
4 | #include <string> | |
5 | ||
6 | #include "types.hh" | |
7 | ||
8 | class sqlite3; | |
9 | class sqlite3_stmt; | |
10 | ||
11 | namespace nix { | |
12 | ||
13 | /* RAII wrapper to close a SQLite database automatically. */ | |
14 | struct SQLite | |
15 | { | |
16 | sqlite3 * db; | |
17 | SQLite() { db = 0; } | |
18 | ~SQLite(); | |
19 | operator sqlite3 * () { return db; } | |
20 | }; | |
21 | ||
22 | /* RAII wrapper to create and destroy SQLite prepared statements. */ | |
23 | struct SQLiteStmt | |
24 | { | |
b1fd0ab7 ED |
25 | sqlite3 * db = 0; |
26 | sqlite3_stmt * stmt = 0; | |
27 | SQLiteStmt() { } | |
7bed5d91 | 28 | void create(sqlite3 * db, const std::string & s); |
7bed5d91 ED |
29 | ~SQLiteStmt(); |
30 | operator sqlite3_stmt * () { return stmt; } | |
7bed5d91 | 31 | |
b1fd0ab7 ED |
32 | /* Helper for binding / executing statements. */ |
33 | class Use | |
34 | { | |
35 | friend struct SQLiteStmt; | |
36 | private: | |
37 | SQLiteStmt & stmt; | |
38 | unsigned int curArg = 1; | |
39 | Use(SQLiteStmt & stmt); | |
40 | ||
41 | public: | |
42 | ||
43 | ~Use(); | |
44 | ||
45 | /* Bind the next parameter. */ | |
46 | Use & operator () (const std::string & value, bool notNull = true); | |
47 | Use & operator () (int64_t value, bool notNull = true); | |
48 | Use & bind(); // null | |
49 | ||
50 | int step(); | |
51 | ||
52 | /* Execute a statement that does not return rows. */ | |
53 | void exec(); | |
54 | ||
55 | /* For statements that return 0 or more rows. Returns true iff | |
56 | a row is available. */ | |
57 | bool next(); | |
58 | ||
59 | std::string getStr(int col); | |
60 | int64_t getInt(int col); | |
61 | }; | |
62 | ||
63 | Use use() | |
64 | { | |
65 | return Use(*this); | |
66 | } | |
7bed5d91 ED |
67 | }; |
68 | ||
69 | /* RAII helper that ensures transactions are aborted unless explicitly | |
70 | committed. */ | |
71 | struct SQLiteTxn | |
72 | { | |
73 | bool active = false; | |
74 | sqlite3 * db; | |
75 | ||
76 | SQLiteTxn(sqlite3 * db); | |
77 | ||
78 | void commit(); | |
79 | ||
80 | ~SQLiteTxn(); | |
81 | }; | |
82 | ||
83 | ||
84 | MakeError(SQLiteError, Error); | |
85 | MakeError(SQLiteBusy, SQLiteError); | |
86 | ||
87 | [[noreturn]] void throwSQLiteError(sqlite3 * db, const format & f); | |
88 | ||
89 | /* Convenience function for retrying a SQLite transaction when the | |
90 | database is busy. */ | |
91 | template<typename T> | |
92 | T retrySQLite(std::function<T()> fun) | |
93 | { | |
94 | while (true) { | |
95 | try { | |
96 | return fun(); | |
97 | } catch (SQLiteBusy & e) { | |
98 | } | |
99 | } | |
100 | } | |
101 | ||
102 | } |