46 }
catch (std::exception& e) {
47 throw ReadError(
e.what());
55class SQLiteReadError : Error {
57 explicit SQLiteReadError(
const std::string& msg) : Error(msg) {}
58 explicit SQLiteReadError(
const char* msg) : Error(msg) {}
59 virtual ~SQLiteReadError() =
default;
69sqlite3* open(
const std::string& file_name)
71 sqlite3* db =
nullptr;
73 const int rc = sqlite3_open(file_name.c_str(), &db);
76 throw SQLiteReadError(
"Cannot open sqlite3 database file "
77 + file_name +
": " + sqlite3_errmsg(db));
94int extract_callback(
void*
data,
int argc,
char** argv,
char** col_name)
96 auto values =
static_cast<Eigen::ArrayXd*
>(
data);
97 values->conservativeResize(argc);
99 for (
int i = 0; i < argc; i++) {
108 : db(open(file_name))
125void Database::insert(
126 const std::string& table_name,
const std::vector<std::string>& names,
127 const Eigen::ArrayXd&
data)
129 const std::size_t number_of_elements =
data.rows();
131 if (names.size() != number_of_elements) {
132 ERROR(
"number of column names (" << names.size() <<
133 ") does not match vector size (" << number_of_elements <<
")!");
137 create_table<double>(table_name, names);
139 std::string sql(
"INSERT INTO " + table_name +
" (");
141 for (std::size_t i = 0; i < number_of_elements; i++) {
142 sql +=
'"' + names[i] +
'"';
143 if (i + 1 != number_of_elements)
149 for (std::size_t i = 0; i < number_of_elements; i++) {
151 if (i + 1 != number_of_elements)
157 execute(
"PRAGMA synchronous = OFF;");
168Eigen::ArrayXd Database::extract(
const std::string& table_name,
long long row)
170 Eigen::ArrayXd values;
171 const std::string sql =
173 "SELECT * FROM " + table_name +
" LIMIT 1 OFFSET "
175 "SELECT * FROM " + table_name +
" WHERE ROWID = (SELECT MAX(ROWID) - "
178 execute(sql, extract_callback,
static_cast<void*
>(&values));
191void Database::create_table(
192 const std::string& table_name,
const std::vector<std::string>& names)
194 const std::size_t number_of_elements = names.size();
195 std::string sql(
"CREATE TABLE IF NOT EXISTS " + table_name +
" (");
197 for (std::size_t i = 0; i < number_of_elements; i++) {
198 sql +=
'"' + names[i] + R
"(" REAL)";
199 if (i + 1 != number_of_elements)
213void Database::execute(
const std::string& cmd)
215 char* zErrMsg =
nullptr;
216 const int rc = sqlite3_exec(db, cmd.c_str(),
nullptr,
nullptr, &zErrMsg);
218 if (rc != SQLITE_OK) {
219 ERROR(
"SQL error while executing command \"" << cmd <<
"\": " << zErrMsg);
220 sqlite3_free(zErrMsg);
222 VERBOSE_MSG(
"SQL command \"" << cmd <<
"\" executed successfully");
233void Database::execute(
const std::string& cmd, TCallback callback,
void*
data)
235 char* zErrMsg =
nullptr;
236 const int rc = sqlite3_exec(db, cmd.c_str(), callback,
data, &zErrMsg);
238 if (rc != SQLITE_OK) {
239 ERROR(
"SQL error while executing command \"" << cmd <<
"\": " << zErrMsg);
240 sqlite3_free(zErrMsg);
242 VERBOSE_MSG(
"SQL command \"" << cmd <<
"\" executed successfully");
270 const std::string&,
const std::vector<std::string>&,
const Eigen::ArrayXd&)
void execute(const std::string &)
void create_table(const std::string &, const std::vector< std::string > &)
Database(const std::string &file_name)
int(*)(void *, int, char **, char **) TCallback
Eigen::ArrayXd extract(const std::string &, long long)
extract a row of doubles from a table
void insert(const std::string &, const std::vector< std::string > &, const Eigen::ArrayXd &)
insert a row of doubles into a table
DisabledSQLiteError(const std::string &msg)
DisabledSQLiteError(const char *msg)
virtual ~DisabledSQLiteError()=default
std::string to_string(char a)
double to_double(const char *s)