12 #include "KVSQLiteServer.h"
13 #include "KVSQLiteResult.h"
14 #include "KVSQLiteStatement.h"
24 using namespace std::chrono_literals;
40 KVSQLiteServer::KVSQLiteServer(
const char* db,
const char* ,
const char* )
44 fSrvInfo += sqlite3_libversion();
46 if (strncmp(db,
"sqlite://", 9)) {
48 Error(
"KVSQLiteServer",
"protocol in db argument should be sqlite it is %s",
49 givenProtocol.Data());
54 const char* dbase = db + 9;
56 #ifndef SQLITE_OPEN_URI
57 #define SQLITE_OPEN_URI 0x00000000
59 #if SQLITE_VERSION_NUMBER >= 3005000
60 Int_t error = sqlite3_open_v2(dbase, &fSQLite, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_URI, NULL);
62 Int_t error = sqlite3_open(dbase, &fSQLite);
74 Error(
"KVSQLiteServer",
"opening of %s failed with error: %d %s", dbase, sqlite3_errcode(fSQLite), sqlite3_errmsg(fSQLite));
75 sqlite3_close(fSQLite);
88 KVSQLiteServer::~KVSQLiteServer()
91 sqlite3_close(fSQLite);
102 void KVSQLiteServer::Close(
Option_t*)
109 sqlite3_close(fSQLite);
124 Bool_t KVSQLiteServer::StartTransaction()
126 return Exec(
"BEGIN TRANSACTION");
136 Bool_t KVSQLiteServer::HasTransactionInFlight()
141 return sqlite3_get_autocommit(fSQLite) == 0;
153 Bool_t KVSQLiteServer::Commit()
155 return Exec(
"COMMIT TRANSACTION");
166 Bool_t KVSQLiteServer::Rollback()
168 return Exec(
"ROLLBACK TRANSACTION");
180 TSQLResult* KVSQLiteServer::Query(
const char* sql)
182 if (!IsConnected()) {
183 Error(
"Query",
"not connected");
187 sqlite3_stmt* preparedStmt =
nullptr;
188 const char* tail =
nullptr;
191 #if SQLITE_VERSION_NUMBER >= 3005000
192 int retVal = sqlite3_prepare_v2(fSQLite, sql, -1, &preparedStmt, &tail);
194 int retVal = sqlite3_prepare(fSQLite, sql, -1, &preparedStmt, &tail);
196 if (retVal != SQLITE_OK) {
197 SetError(retVal,sqlite3_errmsg(fSQLite),
"Query");
198 Info(
"Query",
"Query was:%s",sql);
201 if (tail && tail[0] !=
'\0')
202 Warning(
"Query",
"Don't use multiple queries, '%s' query was ignored", tail);
204 return new KVSQLiteResult(preparedStmt);
215 Bool_t KVSQLiteServer::Exec(
const char* sql)
217 if (!IsConnected()) {
218 Error(
"Exec",
"not connected");
223 int ret = sqlite3_exec(fSQLite, sql, NULL, NULL, NULL);
224 if (ret != SQLITE_OK) {
225 SetError(ret,sqlite3_errmsg(fSQLite),
"Exec");
240 Int_t KVSQLiteServer::SelectDataBase(
const char* )
242 Error(
"SelectDataBase",
"SelectDataBase command makes no sense for SQLite!");
254 TSQLResult* KVSQLiteServer::GetDataBases(
const char* )
256 Error(
"GetDataBases",
"GetDataBases command makes no sense for SQLite!");
270 TSQLResult* KVSQLiteServer::GetTables(
const char* ,
const char* wild)
272 if (!IsConnected()) {
273 Error(
"GetTables",
"not connected");
277 TString sql =
"SELECT name FROM sqlite_master where type='table'";
279 sql +=
Form(
" AND name LIKE '%s'", wild);
288 TList* KVSQLiteServer::GetTablesList(
const char* wild)
299 Info(
"GetTablesList",
"Database is locked. Try again in 50ms...");
300 std::this_thread::sleep_for(50ms);
301 Info(
"GetTablesList",
"Try number %d...",i);
304 while(!l && IsLocked() && (i<6));
306 Info(
"GetTablesList",
"...database access successful!");
325 TSQLResult* KVSQLiteServer::GetColumns(
const char* ,
const char* table,
328 if (!IsConnected()) {
329 Error(
"GetColumns",
"not connected");
334 Error(
"GetColumns",
"Not implementable for SQLite as a query with wildcard, use GetFieldNames() after SELECT instead!");
338 TString sql =
Form(
"PRAGMA table_info('%s')", table);
351 TSQLTableInfo* KVSQLiteServer::GetTableInfo(
const char* tablename)
353 if (!IsConnected()) {
354 Error(
"GetTableInfo",
"not connected");
358 if (!tablename || (*tablename == 0))
return nullptr;
360 TSQLResult* columnRes = GetColumns(
"", tablename);
362 if (columnRes ==
nullptr) {
363 Error(
"GetTableInfo",
"could not query columns");
367 TList* lst =
nullptr;
371 while ((columnRow = columnRes->
Next()) !=
nullptr) {
406 Int_t KVSQLiteServer::CreateDataBase(
const char* )
408 Error(
"CreateDataBase",
"CreateDataBase command makes no sense for SQLite!");
420 Int_t KVSQLiteServer::DropDataBase(
const char* )
422 Error(
"DropDataBase",
"DropDataBase command makes no sense for SQLite!");
434 Int_t KVSQLiteServer::Reload()
436 if (!IsConnected()) {
437 Error(
"Reload",
"not connected");
441 Error(
"Reload",
"not implemented");
453 Int_t KVSQLiteServer::Shutdown()
455 if (!IsConnected()) {
456 Error(
"Shutdown",
"not connected");
460 Error(
"Shutdown",
"not implemented");
474 Bool_t KVSQLiteServer::HasStatement()
const
489 SetError(-1,
"no query string specified",
"Statement");
493 if (!IsConnected()) {
494 Error(
"Statement",
"not connected");
498 sqlite3_stmt* preparedStmt =
nullptr;
499 const char* tail =
nullptr;
504 #if SQLITE_VERSION_NUMBER >= 3005000
505 int retVal = sqlite3_prepare_v2(fSQLite, sql, -1, &preparedStmt, &tail);
507 int retVal = sqlite3_prepare(fSQLite, sql, -1, &preparedStmt, &tail);
509 if (retVal != SQLITE_OK) {
510 SetError(retVal,sqlite3_errmsg(fSQLite),
"Statement");
513 if (tail && tail[0] !=
'\0')
514 Warning(
"Statement",
"Don't use multiple statements, '%s' statement was ignored", tail);
517 stmt->
fConn = fSQLite;
518 stmt->
fRes = preparedStmt;
520 return new KVSQLiteStatement(stmt);
530 const char* KVSQLiteServer::ServerInfo()
532 if (!IsConnected()) {
533 Error(
"ServerInfo",
"not connected");
537 return fSrvInfo.Data();
544 bool KVSQLiteServer::IsLocked()
const
546 return GetErrorCode()==SQLITE_BUSY;
553 bool KVSQLiteServer::IsOK()
const
555 return GetErrorCode()==SQLITE_OK;
char * Form(const char *fmt,...)
void Add(TObject *obj) override
virtual TSQLRow * Next()=0
virtual const char * GetField(Int_t field)=0
virtual TList * GetTablesList(const char *wild=nullptr)
CPYCPPYY_EXTERN bool Exec(const std::string &cmd)