Use better C++ SQL APIs

This commit is contained in:
topjohnwu
2024-12-31 22:52:34 -08:00
committed by John Wu
parent 3ca6d06f69
commit 2722875190
9 changed files with 283 additions and 224 deletions
+30 -55
View File
@@ -6,29 +6,8 @@
#include <string_view>
#include <functional>
template <class T, size_t N>
class db_dict {
public:
T& operator [](std::string_view key) {
return data[get_idx(key)];
}
const T& operator [](std::string_view key) const {
return data[get_idx(key)];
}
T& operator [](int key) {
return data[key];
}
const T& operator [](int key) const {
return data[key];
}
protected:
T data[N + 1];
virtual int get_idx(std::string_view key) const = 0;
};
#include <base.hpp>
#include <sqlite.hpp>
/***************
* DB Settings *
@@ -75,11 +54,16 @@ enum {
NAMESPACE_MODE_ISOLATE
};
class db_settings : public db_dict<int, std::size(DB_SETTING_KEYS)> {
public:
struct db_settings {
int root_access;
int multiuser_mode;
int mnt_ns;
int bootloop;
bool denylist;
bool zygisk;
db_settings();
protected:
int get_idx(std::string_view key) const override;
void operator()(StringSlice columns, DbValues &data);
};
/**************
@@ -93,43 +77,34 @@ enum {
SU_MANAGER = 0
};
class db_strings : public db_dict<std::string, std::size(DB_STRING_KEYS)> {
protected:
int get_idx(std::string_view key) const override;
struct db_strings {
std::string su_manager;
void operator()(StringSlice columns, DbValues &data);
};
/*************
* SU Access *
*************/
typedef enum {
QUERY = 0,
DENY = 1,
ALLOW = 2,
} policy_t;
struct su_access {
policy_t policy;
int log;
int notify;
};
#define DEFAULT_SU_ACCESS { QUERY, 1, 1 }
#define SILENT_SU_ACCESS { ALLOW, 0, 0 }
#define NO_SU_ACCESS { DENY, 0, 0 }
/********************
* Public Functions *
********************/
using db_row = std::map<std::string_view, std::string_view>;
using db_row_cb = std::function<bool(db_row&)>;
struct owned_fd;
using db_exec_callback = std::function<void(StringSlice, DbValues&)>;
using db_bind_callback = std::function<void(int, DbStatement&)>;
int get_db_settings(db_settings &cfg, int key = -1);
int set_db_settings(int key, int value);
int get_db_strings(db_strings &str, int key = -1);
void rm_db_strings(int key);
void exec_sql(owned_fd client);
bool db_exec(const char *sql);
bool db_exec(const char *sql, const db_row_cb &fn);
bool db_exec(const char *sql, db_bind_callback bind_fn = {}, db_exec_callback exec_fn = {});
static inline bool db_exec(const char *sql, db_exec_callback exec_fn) {
return db_exec(sql, {}, std::move(exec_fn));
}
template<typename T>
concept DbData = requires(T t, StringSlice s, DbValues &v) { t(s, v); };
template<DbData T>
bool db_exec(const char *sql, T &data) {
return db_exec(sql, (db_exec_callback) std::ref(data));
}
+19 -13
View File
@@ -15,23 +15,29 @@ struct sqlite3_stmt;
extern int (*sqlite3_open_v2)(const char *filename, sqlite3 **ppDb, int flags, const char *zVfs);
extern int (*sqlite3_close)(sqlite3 *db);
extern int (*sqlite3_prepare_v2)(sqlite3 *db, const char *zSql, int nByte, sqlite3_stmt **ppStmt, const char **pzTail);
extern int (*sqlite3_bind_parameter_count)(sqlite3_stmt*);
extern int (*sqlite3_bind_int)(sqlite3_stmt*, int, int);
extern int (*sqlite3_bind_text)(sqlite3_stmt*,int,const char*,int,void(*)(void*));
extern int (*sqlite3_column_count)(sqlite3_stmt *pStmt);
extern const char *(*sqlite3_column_name)(sqlite3_stmt*, int N);
extern const char *(*sqlite3_column_text)(sqlite3_stmt*, int iCol);
extern int (*sqlite3_step)(sqlite3_stmt*);
extern int (*sqlite3_finalize)(sqlite3_stmt *pStmt);
extern const char *(*sqlite3_errstr)(int);
using StringVec = rust::Vec<rust::String>;
// Transparent wrapper of sqlite3_stmt
struct DbValues {
const char *get_text(int index);
int get_int(int index);
~DbValues() = delete;
};
struct DbStatement {
int bind_text(int index, const char *val);
int bind_text(int index, rust::Str val);
int bind_int64(int index, int64_t val);
};
using StringSlice = rust::Slice<rust::String>;
using StrSlice = rust::Slice<rust::Str>;
using sqlite_row_callback = void(*)(void*, StringSlice, StringSlice);
using sql_bind_callback = void(*)(void*, int, DbStatement&);
using sql_exec_callback = void(*)(void*, StringSlice, DbValues&);
#define fn_run_ret(fn, ...) if (int rc = fn(__VA_ARGS__); rc != SQLITE_OK) return rc
bool load_sqlite();
int sql_exec(sqlite3 *db, rust::Str zSql, StrSlice args, sqlite_row_callback callback, void *v);
sqlite3 *open_and_init_db();
int sql_exec(sqlite3 *db, rust::Str zSql,
sql_bind_callback bind_cb, void *bind_cookie,
sql_exec_callback exec_cb, void *exec_cookie);