about summary refs log tree commit diff
path: root/third_party/nix/src/libstore/sqlite.hh
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/nix/src/libstore/sqlite.hh')
-rw-r--r--third_party/nix/src/libstore/sqlite.hh109
1 files changed, 109 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 0000000000..cad78aed45
--- /dev/null
+++ b/third_party/nix/src/libstore/sqlite.hh
@@ -0,0 +1,109 @@
+#pragma once
+
+#include <functional>
+#include <string>
+
+#include "libutil/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;
+    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);
+    }
+  }
+}
+
+}  // namespace nix