14#include "tkdb_table.h"
33 glog.set_class(
"db_table");
39 fDataBase(_other.fDataBase),
40 fColumns(_other.fColumns),
41 fOrderedColumnNames(_other.fOrderedColumnNames),
42 fConstraint(_other.fConstraint)
48 if (
this == &_other)
return *
this;
49 finalize_statements();
51 fDataBase = _other.fDataBase;
52 fColumns = _other.fColumns;
53 fOrderedColumnNames = _other.fOrderedColumnNames;
54 fConstraint = _other.fConstraint;
59 fName(std::move(_other.fName)),
60 fDataBase(_other.fDataBase),
61 fColumns(std::move(_other.fColumns)),
62 fOrderedColumnNames(std::move(_other.fOrderedColumnNames)),
63 fSQL_stmt(_other.fSQL_stmt),
64 fInsertStatement(_other.fInsertStatement),
65 fReading(_other.fReading),
66 fConstraint(std::move(_other.fConstraint))
68 _other.fSQL_stmt =
nullptr;
69 _other.fInsertStatement =
nullptr;
70 _other.fReading =
false;
75 if (
this == &_other)
return *
this;
76 finalize_statements();
77 fName = std::move(_other.fName);
78 fDataBase = _other.fDataBase;
79 fColumns = std::move(_other.fColumns);
80 fOrderedColumnNames = std::move(_other.fOrderedColumnNames);
81 fSQL_stmt = _other.fSQL_stmt;
82 fInsertStatement = _other.fInsertStatement;
83 fReading = _other.fReading;
84 fConstraint = std::move(_other.fConstraint);
85 _other.fSQL_stmt =
nullptr;
86 _other.fInsertStatement =
nullptr;
87 _other.fReading =
false;
93 finalize_statements();
96void tkdb_table::finalize_statements()
98 if (fSQL_stmt) sqlite3_finalize(fSQL_stmt);
99 if (fInsertStatement) sqlite3_finalize(fInsertStatement);
101 fInsertStatement =
nullptr;
107 glog.set_method(
tkstring::Form(
"get_column_list(%s)",fName.data()));
110 int rc = sqlite3_prepare_v2(fDataBase,
tkstring::form(
"PRAGMA table_info('%s');",fName.data()), -1, &stmt,
nullptr);
112 glog <<
error_v <<
"SQL error: " << sqlite3_errmsg(fDataBase) <<
" while loading table '" << fName.data() <<
"'" <<
do_endl;
113 sqlite3_free(
nullptr);
116 while((sqlite3_step(stmt)) == SQLITE_ROW) {
117 tkstring name = sqlite3_column_text(stmt, 1);
118 tkstring type = sqlite3_column_text(stmt, 2);
122 sqlite3_finalize(stmt);
137 for(
auto &column : fColumns) {
138 if(_opt.
contains(
"notnull")&&column.second.is_empty())
continue;
139 if(column.first.contains(_opt)) glog <<
info <<
tkstring::form(
"[%3d] %20s %6s %s",ii++,column.second.get_name(),column.second.get_type(),column.second.get_value().data()) <<
do_endl;
148 std::vector<tkstring> colnames;
150 if(pro.
equal_to(
"*")) colnames = fOrderedColumnNames;
153 for(
auto col : colnames) glog <<
tkstring::form(
"%20s",fColumns[col.data()].get_name());
156 begin(sel,_properties);
159 for(
auto col : colnames) glog <<
tkstring::form(
"%20s",fColumns[col.data()].get_value().data());
168 glog <<
warning <<
"Previous sql statement not yet closed. Closing in to start new statement..." <<
do_endl;
172 tkstring cmd =
tkstring::form(
"select %s from %s where %s",_selection.data(),fName.data(),_condition.data());
174 int rc = sqlite3_prepare_v2(fDataBase, cmd.data(), -1, &fSQL_stmt,
nullptr);
176 glog <<
error <<
"SQL error: " << sqlite3_errmsg(fDataBase) <<
"while executing cmd : " << cmd.data() <<
do_endl;
178 sqlite3_free(
nullptr);
180 else fReading =
true;
186 glog <<
error <<
"No sql statement prepared, please call begin() to prepare it " <<
do_endl;
190 int ret_code = sqlite3_step(fSQL_stmt);
191 if(ret_code== SQLITE_ROW) {
192 int cols = sqlite3_column_count(fSQL_stmt);
193 for (
int i=0; i<cols; i++) {
194 const unsigned char* tmp = sqlite3_column_text(fSQL_stmt, i);
196 fColumns[sqlite3_column_name(fSQL_stmt, i)].set_value(
"");
198 fColumns[sqlite3_column_name(fSQL_stmt, i)].set_value(sqlite3_column_text(fSQL_stmt, i));
208 if(!fReading) {glog <<
error <<
"No sql statement prepared to close..." <<
do_endl;
return;}
209 sqlite3_finalize(fSQL_stmt);
243 fColumns.insert(std::make_pair(col_name,col));
244 fOrderedColumnNames.push_back(col_name);
249 fConstraint += _constraint;
255 return fColumns.count(_col_name)>0;
260 const auto column = fColumns.find(_col_name);
261 return column == fColumns.end() ? nullptr : &column->second;
266 for (
auto &column : fColumns)
272 if (!fInsertStatement && !prepare_insert_statement()) {
278 bool bindings_ok =
true;
279 for (
const auto &name : fOrderedColumnNames) {
280 auto &column = fColumns[name];
282 if (column.is_empty())
283 rc = sqlite3_bind_null(fInsertStatement, parameter);
285 const tkstring value = column.get_value();
286 rc = sqlite3_bind_text(fInsertStatement, parameter, value.data(), -1, SQLITE_TRANSIENT);
288 if (rc != SQLITE_OK) {
289 glog <<
error <<
"SQL bind error while inserting into " << fName <<
": "
290 << sqlite3_errmsg(fDataBase) <<
do_endl;
298 const int rc = sqlite3_step(fInsertStatement);
299 if (rc != SQLITE_DONE) {
300 glog <<
error <<
"SQL insert error in " << fName <<
": "
301 << sqlite3_errmsg(fDataBase) <<
do_endl;
304 sqlite3_reset(fInsertStatement);
305 sqlite3_clear_bindings(fInsertStatement);
309bool tkdb_table::prepare_insert_statement()
311 if (fOrderedColumnNames.empty())
return false;
315 for (
const auto &name : fOrderedColumnNames) {
320 sql.erase(sql.length() - 1);
321 parameters.erase(parameters.length() - 1);
326 const int rc = sqlite3_prepare_v2(fDataBase, sql.data(), -1, &fInsertStatement,
nullptr);
327 if (rc != SQLITE_OK) {
328 glog <<
error <<
"SQL prepare error for " << fName <<
": "
329 << sqlite3_errmsg(fDataBase) <<
do_endl;
330 fInsertStatement =
nullptr;
342 for(
auto &column : fColumns) {
343 if(column.second.is_empty())
continue;
344 sql += column.second.get_name();
346 if(column.second.is_text()) sql +=
"'";
347 sql += column.second.get_value();
348 if(column.second.is_text()) sql +=
"'";
351 sql.erase(sql.length()-1);
353 sql += _where.data();
355 exec_sql(sql.data());
363 for (
auto it: fOrderedColumnNames) {
364 sql += fColumns[it.data()].get_name();
366 sql += fColumns[it.data()].get_type();
369 sql = sql.
substr(0,sql.size()-1);
370 if(!fConstraint.empty()) {
372 sql += fConstraint.data();
375 exec_sql(sql.data());
380 for (
auto &column : fColumns)
381 column.second.set_value_str(
"0");
385int tkdb_table::exec_sql(
const char *_cmd)
387 char *zErrMsg =
nullptr;
388 int rc = sqlite3_exec(fDataBase, _cmd,
nullptr,
nullptr, &zErrMsg);
390 if( rc != SQLITE_OK ) {
391 glog <<
error <<
"SQL error: " << zErrMsg <<
" while excuting command: " << _cmd <<
do_endl;
392 sqlite3_free(zErrMsg);
403 glog <<
warning <<
"no column named: " << _col_base_name <<
" in database: " << fName <<
do_endl;
411 static const std::array<const char *, 6> suffixes = {
412 "",
"_unit",
"_unc",
"_unc_low",
"_unc_high",
"_info"
415 for (std::size_t index = 0; index < suffixes.size(); ++index) {
417 name += suffixes[index];
430 if (!_columns[0] || _columns[0]->is_empty())
return;
432 _struct.
value = _columns[0]->get_value().atof();
434 if(_columns[1] && !_columns[1]->is_empty()) _struct.
unit = _columns[1]->get_value();
435 if(_columns[2] && !_columns[2]->is_empty()) _struct.
err = _columns[2]->get_value().atof();
436 if(_columns[3] && !_columns[3]->is_empty()) _struct.
err_low = _columns[3]->get_value().atof();
437 if(_columns[4] && !_columns[4]->is_empty()) _struct.
err_high = _columns[4]->get_value().atof();
438 if(_columns[5] && !_columns[5]->is_empty()) _struct.
info = _columns[5]->get_value();
Simple structure to store a table column.
void set_value_str(const char *val)
Representaiton of a sqlite data table.
std::array< tkdb_column *, 6 > measure_columns
void read_measure(measure_data_struct &_struct, const tkstring &_col_base_name)
tkdb_column * get_column(const tkstring &_col_name)
measure_columns get_measure_columns(const tkstring &_col_base_name)
void begin(tkstring _condition, tkstring _selection="*")
bool has_column(const tkstring &_col_name)
void update_row(const tkstring &_where)
tkdb_table & operator=(const tkdb_table &_other)
void load()
resets column values and ends the select statement
bool next()
executes the select statement
void print_columns(const tkstring &_opt="")
void add_constraint(const char *_constraint)
void print_rows(const char *_selection, const char *_properties="*")
void end()
reads the next entry coresponding to the select statement and fills columns
void print(const tkstring &_opt="")
void add_column(const char *_colname, const char *_coltype)
void reset_column_values()
tkdb_table(const char *_name, sqlite3 *_db)
std::string with usefull tricks from TString (ROOT) and KVString (KaliVeda) and more....
static const char * form(const char *_format,...)
std::vector< tkstring > tokenize(const tkstring &_delim=" ") const
Create a vector of string separated by at least one delimiter.
static tkstring Form(const char *_format,...)
tkstring substr(size_type __pos=0, size_type __n=npos) const
Inlines.
bool equal_to(const char *_s, ECaseCompare _cmp=kExact) const
Returns true if the string and _s are identical.
bool contains(const char *_pat, ECaseCompare _cmp=kExact) const
tklog & yellow(tklog &log)
tklog & error_v(tklog &log)
tklog & error(tklog &log)
tklog & do_endl(tklog &log)
tklog & warning(tklog &log)
data structure used to fill a tkmeasure object from the sqlite database