projects/guix·blob python-team · refs

104 lines · 2.0 KiB

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