23 std::map<TString, KVSQLite::column_type::types> table::type_map;
24 std::map<KVSQLite::column_type::types, TString> column::inv_type_map;
41 query.
Form(
"SELECT %s FROM '%s'", columns.
Data(),
table.Data());
42 if (condition !=
"") query +=
Form(
" WHERE %s", condition.
Data());
43 return unique_ptr<TSQLResult>(fDBserv->Query(query));
51 void database::read_table_infos()
54 unique_ptr<TList> tl(fDBserv->GetTablesList());
56 TIter it_tab(tl.get());
57 while ((o = it_tab())) {
61 unique_ptr<TSQLTableInfo> ti(fDBserv->GetTableInfo(o->
GetName()));
63 TIter it_col(ti->GetColumns());
67 fTables.insert(std::pair<std::string, KVSQLite::table>(o->
GetName(), t));
77 void database::show_tables()
const
80 std::cout <<
"Tables in database:" << std::endl;
82 for (
auto it = fTables.begin();
84 for (std::map<std::string, KVSQLite::table>::const_iterator it = fTables.begin();
86 it != fTables.end(); ++it) {
87 std::cout <<
"\t" << it->first << std::endl;
97 void database::open(
const TString& dbfile)
101 TString uri =
"sqlite://" + dbfile;
104 if (!fDBserv->Exec(
"pragma schema_version")) {
117 void database::PrintResults(
TSQLResult* tabent,
int column_width)
const
120 unique_ptr<TSQLRow> row(
nullptr);
121 for (
int r = -1;
true; ++
r) {
123 row.reset(tabent->
Next());
124 if (row.get() ==
nullptr)
break;
125 std::cout << std::setw(6) <<
r;
127 for (
int f = 0;
f < nfields; ++
f) {
129 if (
f == 0) std::cout << std::setw(6) <<
"#";
130 std::cout <<
"|" << std::setw(column_width) << tabent->
GetFieldName(
f) ;
133 std::cout <<
"|" << std::setw(column_width) << row->GetField(
f) ;
145 void database::Dump()
const
149 std::cout <<
"Database : " << fDBserv->GetDB() <<
" [" << fDBserv->GetDBMS() <<
"]\n";
150 unique_ptr<TList> tl(fDBserv->GetTablesList());
152 TIter it_tab(tl.get());
153 while ((o = it_tab())) {
155 std::cout <<
"Table : " << o->
GetName() <<
"\n";
156 unique_ptr<TSQLResult> tabent = SelectRowsFromTable(o->
GetName());
157 PrintResults(tabent.get());
159 std::cout << std::endl;
170 unique_ptr<TSQLResult> tabent = SelectRowsFromTable(
table, columns, condition);
171 PrintResults(tabent.get(), column_width);
172 std::cout << std::endl;
212 command +=
"TABLE IF NOT EXISTS \"";
217 if (i) command +=
", ";
218 command += t[i].get_declaration();
222 if (fDBserv->Exec(command))
223 fTables.insert(std::pair<std::string, KVSQLite::table>(t.
name(), t));
261 Error(
"database::prepare_data_insertion",
262 "bulk insertion in progress for table %s; call database::commit() to terminate transaction",
267 Error(
"database::prepare_data_insertion",
268 "bulk insertion in progress; call database::commit() to terminate transaction");
273 Error(
"database::prepare_data_insertion",
274 "data retrieval in progress; call get_next_result() until it returns false");
278 fDBserv->StartTransaction();
280 fBulkTable = &fTables[
table.Data()];
281 TString com(fBulkTable->get_insert_command());
282 int ncol = fBulkTable->number_of_columns();
284 for (
int i = 0; i < ncol; ++i) {
286 if (!(*fBulkTable)[i].primary_key()) {
287 com +=
Form(
"\"%s\"", (*fBulkTable)[i].name());;
293 for (
int i = 0; i < ncol; ++i) {
295 if (!(*fBulkTable)[i].primary_key()) {
302 fSQLstmt.reset(fDBserv->Statement(com));
310 const char* table::get_insert_command()
const
314 return Form(
"INSERT OR FAIL INTO \"%s\"(", name());
317 return Form(
"INSERT OR IGNORE INTO \"%s\"(", name());
320 return Form(
"INSERT OR REPLACE INTO \"%s\"(", name());
326 return Form(
"INSERT INTO \"%s\"(", name());
334 const char* column::get_declaration()
const
339 decl.
Form(
"\"%s\" %s", name(), type_name());
341 decl +=
" REFERENCES ";
342 decl +=
Form(
"\"%s\"(\"%s\")", fFKtable.Data(), fFKcolumn.Data());
365 void database::insert_data_row()
378 if (!fInserting || !fBulkTable) {
379 Error(
"database::insert_data_row",
380 "no transaction initialized; call prepare_data_insertion(name_table) before this method");
384 Error(
"database::insert_data_row",
385 "data retrieval in progress; call get_next_result() until it returns false, then call prepare_data_insertion(name_table) before this method");
388 int ncol = fBulkTable->number_of_columns();
389 fSQLstmt->NextIteration();
391 for (
int i = 0; i < ncol; ++i) {
392 if (!(*fBulkTable)[i].primary_key()) {
393 (*fBulkTable)[i].set_data_in_statement(fSQLstmt.get(), idx);
405 void database::end_data_insertion()
411 Error(
"database::end_data_insertion",
412 "no transaction initialized; call prepare_data_insertion(name_table) first");
416 Error(
"database::insert_data_row",
417 "data retrieval in progress; call get_next_result() until it returns false, then call prepare_data_insertion(name_table) before this method");
420 fBulkTable =
nullptr;
455 Error(
"database::select_data",
456 "data insertion in progress; call end_data_insertion() before retrieving data");
460 Error(
"database::select_data",
461 "data retrieval already in progress; call get_next_result() until it returns false before making new selection");
465 fBulkTable = &fTables[
table.Data()];
467 KVString column_selection(
""), _columns(columns);
468 if (columns ==
"*") {
469 column_selection =
"*";
471 fSelectedColumns =
"*";
474 if (distinct) column_selection =
"DISTINCT ";
475 fSelectedColumns =
"";
479 while (!_columns.
End()) {
482 column_selection +=
", ";
483 fSelectedColumns +=
", ";
485 column_selection +=
Form(
"\"%s\"", colnam.
Data());
486 fSelectedColumns += colnam.
Data();
491 TString cond =
Form(
"SELECT %s FROM \"%s\"", column_selection.Data(),
table.Data());
492 if (selection !=
"") cond +=
Form(
" WHERE %s", selection.
Data());
493 if (anything_else !=
"") cond +=
Form(
" %s", anything_else.
Data());
494 fSQLstmt.reset(fDBserv->Statement(cond));
495 if (fSQLstmt.get() ==
nullptr) {
496 Error(
"database::select_data",
"problem processing : %s", cond.
Data());
498 fBulkTable =
nullptr;
501 fSQLstmt->EnableErrorOutput();
502 if (fSQLstmt->Process()) {
503 fSQLstmt->StoreResult();
505 fEmptyResultSet =
false;
508 else if (!fSQLstmt->IsError()) {
510 fSQLstmt->StoreResult();
512 fEmptyResultSet =
true;
516 fBulkTable =
nullptr;
526 bool database::get_next_result()
const
532 Error(
"database::get_next_result",
533 "data insertion in progress; call end_data_insertion() then select_data() before this method");
537 Error(
"database::get_next_result",
538 "no data retrieval in progress; select_data() must be called and return true before calling this method");
541 if (!fEmptyResultSet && fSQLstmt->NextResultRow()) {
543 if (fSelectedColumns ==
"*") {
544 for (
int i = 0; i < fBulkTable->number_of_columns(); ++i) {
545 (*fBulkTable)[i].set_data_from_statement(fSQLstmt.get());
551 for (
int i = 0; i < fBulkTable->number_of_columns(); ++i) {
552 if (fSelectedColumns.Contains((*fBulkTable)[i].name())) {
553 (*fBulkTable)[i].set_data_from_statement(fSQLstmt.get(), idx);
560 fBulkTable =
nullptr;
577 if (select_data(
table,
column, selection,
true, anything_else)) {
578 while (get_next_result()) {
599 if (select_data(
table,
column, selection,
false, anything_else)) {
600 while (get_next_result()) {
602 if (result !=
"") result +=
",";
623 if (select_data(tablename,
Form(
"%s,%s", name_column.
Data(), value_column.
Data()), selection,
false, anything_else)) {
624 table& tb = (*this)[tablename];
625 column& nom = tb[name_column];
626 column& val = tb[value_column];
627 while (get_next_result()) {
645 if (select_data(tablename,
Form(
"%s,%s", Xcolumn.
Data(), Ycolumn.
Data()), selection)) {
648 table& tb = (*this)[tablename];
649 column& Xcol = tb[Xcolumn];
650 column& Ycol = tb[Ycolumn];
651 while (get_next_result()) {
664 void database::clear_table(
const TString& name)
690 if (distinct) qry +=
"DISTINCT ";
695 if (selection !=
"") {
700 unique_ptr<TSQLResult> result(fDBserv->Query(qry));
701 unique_ptr<TSQLRow> row(result->Next());
702 TString number = row->GetField(0);
703 return number.
Atoi();
728 Error(
"database::update",
729 "data insertion in progress; call end_data_insertion() before doing anything else");
733 Error(
"database::update",
734 "data retrieval in progress; call get_next_result() until it returns false before doing anything else");
738 fBulkTable = &fTables[
table.Data()];
740 int ncol = fBulkTable->number_of_columns();
742 for (
int i = 0; i < ncol; ++i) {
743 if (columns.
Contains((*fBulkTable)[i].name())) {
744 if (idx) query +=
",";
745 query +=
Form(
"\"%s\"", (*fBulkTable)[i].name());
750 if (selection !=
"") query +=
Form(
" WHERE %s", selection.
Data());
752 fSQLstmt.reset(fDBserv->Statement(query));
753 fSQLstmt->NextIteration();
755 for (
int i = 0; i < ncol; ++i) {
756 if (columns.
Contains((*fBulkTable)[i].name())) {
757 (*fBulkTable)[i].set_data_in_statement(fSQLstmt.get(), idx);
761 return (fSQLstmt->Process());
786 if (selection !=
"") query +=
Form(
" WHERE %s", selection.
Data());
787 fDBserv->Exec(query);
801 fDBserv->Exec(query);
802 return (*
this)[
table].add_column(name,
type);
817 Error(
"database::add_missing_columns",
818 "data insertion in progress; call end_data_insertion() before doing anything else");
822 Error(
"database::add_missing_columns",
823 "data retrieval in progress; call get_next_result() until it returns false before doing anything else");
826 int ipar =
l.GetNpar();
827 table& tab = (*this)[_table_];
828 for (
int i = 0; i < ipar; ++i) {
854 if (COLUMNS !=
"*") {
859 while (!_columns.
End()) {
860 if (COLUMNS !=
"") COLUMNS +=
", ";
864 TString query =
Form(
"INSERT INTO \"%s\" SELECT %s FROM %s", destination.
Data(), COLUMNS.
Data(), source.
Data());
865 if (selection !=
"") query +=
Form(
" WHERE %s", selection.
Data());
866 fDBserv->Exec(query);
873 void column::init_type_map()
885 const char* column::_type()
887 return inv_type_map[fNameType.second];
896 fData.Set(
x.GetName(),
x);
915 if (idx < 0) idx = index();
923 s->SetDouble(idx, fData.GetDouble());
926 s->SetInt(idx, fData.GetInt());
929 s->SetString(idx, fData.GetString(), -1);
932 s->SetBinary(idx, fBlob, fBlobSize);
963 if (idx < 0) idx = index();
964 fIsNull =
s->IsNull(idx);
967 fData.Set(fIsNull ? 0.0 :
s->GetDouble(idx));
970 fData.Set(fIsNull ? 0 :
s->GetInt(idx));
973 fData.Set(fIsNull ?
"" :
s->GetString(idx));
980 if (!fBlob) fBlob = (
void*)
new unsigned char[256];
981 s->GetBinary(idx, fBlob, fBlobSize);
1001 fFKcolumn = _column;
1010 void column::set_foreign_key(
const table& _table,
const column& _column)
1015 fFKtable = _table.
name();
1016 fFKcolumn = _column.
name();
1023 void table::init_type_map()
1036 void table::show_columns()
const
1039 std::cout <<
"Columns in table:" << std::endl;
1041 for (
auto it = fColumns.begin(); it != fColumns.end(); ++it) {
1043 for (std::vector<KVSQLite::column>::const_iterator it = fColumns.begin(); it != fColumns.end(); ++it) {
1045 std::cout <<
"\t" << it->name() <<
" [" << it->type_name() <<
"]" << std::endl;
1061 fColumns.push_back(
c);
1062 fColMap[
c.name()] =
c.index();
1063 return fColumns.back();
1078 return add_column(name, type_map[
type]);
1103 c.set_constraint(
"PRIMARY KEY");
1121 c.set_foreign_key(other_table, other_column);
1139 c.set_foreign_key(other_table, other_column);
1155 int ipar =
l.GetNpar();
1156 for (
int i = 0; i < ipar; ++i) {
1158 if (!has_column(par->
GetName())) ncols++;
1180 for (
int i = 0; i < number_of_columns(); ++i) {
1183 (*
this)[i].set_data(*p);
1185 (*
this)[i].set_null();
1194 void table::set_all_columns_null()
1197 for (
int i = 0; i < number_of_columns(); ++i) {
1198 (*this)[i].set_null();
Defines macros for standard error messages.
ClassImp(KVPartitionList) void KVPartitionList
Initialisation.
char * Form(const char *fmt,...)
Handles lists of named parameters with different types, a list of KVNamedParameter objects.
void SetValue(const Char_t *name, value_type value)
A generic named parameter storing values of different types.
Bool_t HasSameValueAs(const KVNamedParameter &) const
const Char_t * GetSQLType() const
Strings used to represent a set of ranges of values.
void Add(Int_t)
Add value 'n' to the list.
const char * name() const
const KVNamedParameter & data() const
Interface to ROOT SQLite database backend ,.
const char * name() const
bool is_temporary() const
column & add_column(const KVSQLite::column &c)
int number_of_columns() const
bool has_column(const TString &name) const
Extension of ROOT TString class which allows backwards compatibility with ROOT v3....
void Begin(TString delim) const
KVString Next(Bool_t strip_whitespace=kFALSE) const
virtual const char * GetName() const
virtual const char * GetName() const
const char * GetTypeName() const
virtual Int_t GetFieldCount()=0
virtual const char * GetFieldName(Int_t field)=0
virtual TSQLRow * Next()=0
static TSQLServer * Connect(const char *db, const char *uid, const char *pw)
const char * Data() const
void Form(const char *fmt,...)
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
const long double g
masses