diff options
author | Vincent Ambo <tazjin@google.com> | 2020-05-17T14·52+0100 |
---|---|---|
committer | Vincent Ambo <tazjin@google.com> | 2020-05-17T14·52+0100 |
commit | 7994fd1d545cc5c876d6f21db7ddf9185d23dad6 (patch) | |
tree | 32dd695785378c5b9c8be97fc583e9dfc62cb105 /third_party/nix/src/libstore/sqlite.hh | |
parent | cf8cd640c1adf74a3706efbcb0ea4625da106fb2 (diff) | |
parent | 90b3b31dc27f31e9b11653a636025d29ddb087a3 (diff) |
Add 'third_party/nix/' from commit 'be66c7a6b24e3c3c6157fd37b86c7203d14acf10' r/724
git-subtree-dir: third_party/nix git-subtree-mainline: cf8cd640c1adf74a3706efbcb0ea4625da106fb2 git-subtree-split: be66c7a6b24e3c3c6157fd37b86c7203d14acf10
Diffstat (limited to 'third_party/nix/src/libstore/sqlite.hh')
-rw-r--r-- | third_party/nix/src/libstore/sqlite.hh | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/third_party/nix/src/libstore/sqlite.hh b/third_party/nix/src/libstore/sqlite.hh new file mode 100644 index 000000000000..115679b84159 --- /dev/null +++ b/third_party/nix/src/libstore/sqlite.hh @@ -0,0 +1,114 @@ +#pragma once + +#include <functional> +#include <string> + +#include "types.hh" + +class sqlite3; +class sqlite3_stmt; + +namespace nix { + +/* RAII wrapper to close a SQLite database automatically. */ +struct SQLite +{ + sqlite3 * db = 0; + SQLite() { } + SQLite(const Path & path); + SQLite(const SQLite & from) = delete; + SQLite& operator = (const SQLite & from) = delete; + SQLite& operator = (SQLite && from) { db = from.db; from.db = 0; return *this; } + ~SQLite(); + operator sqlite3 * () { return db; } + + void exec(const std::string & stmt); +}; + +/* RAII wrapper to create and destroy SQLite prepared statements. */ +struct SQLiteStmt +{ + sqlite3 * db = 0; + sqlite3_stmt * stmt = 0; + std::string sql; + SQLiteStmt() { } + SQLiteStmt(sqlite3 * db, const std::string & sql) { create(db, sql); } + void create(sqlite3 * db, const std::string & s); + ~SQLiteStmt(); + operator sqlite3_stmt * () { return stmt; } + + /* Helper for binding / executing statements. */ + class Use + { + friend struct SQLiteStmt; + private: + SQLiteStmt & stmt; + unsigned int curArg = 1; + Use(SQLiteStmt & stmt); + + public: + + ~Use(); + + /* Bind the next parameter. */ + Use & operator () (const std::string & value, bool notNull = true); + Use & operator () (int64_t value, bool notNull = true); + Use & bind(); // null + + int step(); + + /* Execute a statement that does not return rows. */ + void exec(); + + /* For statements that return 0 or more rows. Returns true iff + a row is available. */ + bool next(); + + std::string getStr(int col); + int64_t getInt(int col); + bool isNull(int col); + }; + + Use use() + { + return Use(*this); + } +}; + +/* RAII helper that ensures transactions are aborted unless explicitly + committed. */ +struct SQLiteTxn +{ + bool active = false; + sqlite3 * db; + + SQLiteTxn(sqlite3 * db); + + void commit(); + + ~SQLiteTxn(); +}; + + +MakeError(SQLiteError, Error); +MakeError(SQLiteBusy, SQLiteError); + +[[noreturn]] void throwSQLiteError(sqlite3 * db, const FormatOrString & fs); + +void handleSQLiteBusy(const SQLiteBusy & e); + +/* Convenience function for retrying a SQLite transaction when the + database is busy. */ +template<typename T> +T retrySQLite(std::function<T()> fun) +{ + while (true) { + try { + return fun(); + } catch (SQLiteBusy & e) { + handleSQLiteBusy(e); + } + } +} + +} |