/usr/include/dballe/sql/sqlite.h is in libdballe-dev 7.21-1build1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 | /** @file
* SQLite DB connector
*/
#ifndef DBALLE_SQL_SQLITE_H
#define DBALLE_SQL_SQLITE_H
#include <dballe/core/error.h>
#include <dballe/sql/sql.h>
#include <sqlite3.h>
#include <vector>
namespace dballe {
namespace sql {
struct SQLiteStatement;
/**
* Report an SQLite error
*/
struct error_sqlite : public dballe::error_db
{
std::string msg;
error_sqlite(sqlite3* db, const std::string& msg);
error_sqlite(const std::string& dbmsg, const std::string& msg);
~error_sqlite() noexcept {}
const char* what() const noexcept override { return msg.c_str(); }
static void throwf(sqlite3* db, const char* fmt, ...) WREPORT_THROWF_ATTRS(2, 3);
};
/// Database connection
class SQLiteConnection : public Connection
{
protected:
/// Database connection
sqlite3* db = nullptr;
void init_after_connect();
static void on_sqlite3_profile(void* arg, const char* query, sqlite3_uint64 usecs);
public:
SQLiteConnection();
SQLiteConnection(const SQLiteConnection&) = delete;
SQLiteConnection(const SQLiteConnection&&) = delete;
~SQLiteConnection();
SQLiteConnection& operator=(const SQLiteConnection&) = delete;
operator sqlite3*() { return db; }
void open_file(const std::string& pathname, int flags=SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
void open_memory(int flags=SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
void open_private_file(int flags=SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
std::unique_ptr<Transaction> transaction() override;
std::unique_ptr<SQLiteStatement> sqlitestatement(const std::string& query);
bool has_table(const std::string& name) override;
std::string get_setting(const std::string& key) override;
void set_setting(const std::string& key, const std::string& value) override;
void drop_settings() override;
void execute(const std::string& query) override;
void explain(const std::string& query, FILE* out) override;
/**
* Delete a table in the database if it exists, otherwise do nothing.
*/
void drop_table_if_exists(const char* name);
/**
* Return LAST_INSERT_ID or LAST_INSER_ROWID or whatever is appropriate for
* the current database, if supported.
*
* If not supported, an exception is thrown.
*/
int get_last_insert_id();
/// Count the number of rows modified by the last query that was run
int changes();
/// Wrap sqlite3_exec, without a callback
void exec(const std::string& query);
void exec_nothrow(const std::string& query) noexcept;
};
/// SQLite statement
struct SQLiteStatement
{
SQLiteConnection& conn;
sqlite3_stmt *stm = nullptr;
SQLiteStatement(SQLiteConnection& conn, const std::string& query);
SQLiteStatement(const SQLiteStatement&) = delete;
SQLiteStatement(const SQLiteStatement&&) = delete;
~SQLiteStatement();
SQLiteStatement& operator=(const SQLiteStatement&) = delete;
/**
* Bind all the arguments in a single invocation.
*
* Note that the parameter positions are used as bind column numbers, so
* calling this function twice will re-bind columns instead of adding new
* ones.
*/
template<typename... Args> void bind(const Args& ...args)
{
bindn<sizeof...(args)>(args...);
}
void bind_null_val(int idx);
void bind_val(int idx, int val);
void bind_val(int idx, unsigned val);
void bind_val(int idx, unsigned short val);
void bind_val(int idx, const Datetime& val);
void bind_val(int idx, const char* val); // Warning: SQLITE_STATIC is used
void bind_val(int idx, const std::string& val); // Warning: SQLITE_STATIC is used
void bind_val(int idx, const std::vector<uint8_t>& val); // Warning: SQLITE_STATIC is used
/// Run the query, ignoring all results
void execute();
/**
* Run the query, calling on_row for every row in the result.
*
* At the end of the function, the statement is reset, even in case an
* exception is thrown.
*/
void execute(std::function<void()> on_row);
/**
* Run the query, raising an error if there is more than one row in the
* result
*/
void execute_one(std::function<void()> on_row);
/// Read the int value of a column in the result set (0-based)
int column_int(int col) { return sqlite3_column_int(stm, col); }
/// Read the int value of a column in the result set (0-based)
sqlite3_int64 column_int64(int col) { return sqlite3_column_int64(stm, col); }
/// Read the double value of a column in the result set (0-based)
double column_double(int col) { return sqlite3_column_double(stm, col); }
/// Read the string value of a column in the result set (0-based)
const char* column_string(int col) { return (const char*)sqlite3_column_text(stm, col); }
/// Read the string value of a column in the result set (0-based)
std::vector<uint8_t> column_blob(int col) {
int size = sqlite3_column_bytes(stm, col);
const uint8_t* val = (const uint8_t*)sqlite3_column_blob(stm, col);
return std::vector<uint8_t>(val, val + size);
}
/// Read the string value of a column and parse it as a Datetime
Datetime column_datetime(int col);
/// Check if a column has a NULL value (0-based)
bool column_isnull(int col) { return sqlite3_column_type(stm, col) == SQLITE_NULL; }
void wrap_sqlite3_reset();
void wrap_sqlite3_reset_nothrow() noexcept;
/**
* Get the current error message, reset the statement and throw
* error_sqlite
*/
[[noreturn]] void reset_and_throw(const std::string& errmsg);
operator sqlite3_stmt*() { return stm; }
#if 0
/// @return SQLExecute's result
int execute();
/// @return SQLExecute's result
int exec_direct(const char* query);
/// @return SQLExecute's result
int exec_direct(const char* query, int qlen);
/// @return SQLExecute's result
int execute_and_close();
/// @return SQLExecute's result
int exec_direct_and_close(const char* query);
/// @return SQLExecute's result
int exec_direct_and_close(const char* query, int qlen);
/**
* @return the number of columns in the result set (or 0 if the statement
* did not return columns)
*/
int columns_count();
bool fetch();
bool fetch_expecting_one();
void close_cursor();
void close_cursor_if_needed();
/// Row count for select operations
size_t select_rowcount();
/// Row count for insert, delete and other non-select operations
size_t rowcount();
#endif
private:
// Implementation of variadic bind: terminating condition
template<size_t total> void bindn() {}
// Implementation of variadic bind: recursive iteration over the parameter pack
template<size_t total, typename ...Args, typename T> void bindn(const T& first, const Args& ...args)
{
bind_val(total - sizeof...(args), first);
bindn<total>(args...);
}
};
}
}
#endif
|