KaliVeda
Toolkit for HIC analysis
KVSQLiteStatement.cxx
1 // @(#)root/sqlite:$Id$
2 // Author: o.freyermuth <o.f@cern.ch>, 01/06/2013
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2013, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
13 // //
14 // SQL statement class for SQLite. //
15 // //
16 // See TSQLStatement class documentation for more details. //
17 // //
19 
20 #include "KVSQLiteStatement.h"
21 #include "KVSQLiteResult.h"
22 #include "TDataType.h"
23 #include "TDatime.h"
24 #include "TTimeStamp.h"
25 
26 #include <sqlite3.h>
27 
28 #include <stdlib.h>
29 #include <thread>
30 #include <chrono>
31 using namespace std::chrono_literals;
32 
33 ClassImp(KVSQLiteStatement)
34 
35 
39 
40 
42 KVSQLiteStatement::KVSQLiteStatement(SQLite3_Stmt_t* stmt, Bool_t errout):
43  TSQLStatement(errout),
44  fStmt(stmt),
45  fWorkingMode(0),
46  fNumPars(0),
47  fIterationCount(0)
48 {
49  unsigned long bindParamcount = sqlite3_bind_parameter_count(fStmt->fRes);
50 
51  if (bindParamcount > 0) {
52  fWorkingMode = 1;
53  fNumPars = bindParamcount;
54  }
55  else {
56  fWorkingMode = 2;
57  fNumPars = sqlite3_column_count(fStmt->fRes);
58  }
59 }
60 
61 
64 
65 
67 
68 KVSQLiteStatement::~KVSQLiteStatement()
69 {
70  Close();
71 }
72 
73 
76 
77 
79 
80 void KVSQLiteStatement::Close(Option_t*)
81 {
82  if (fStmt->fRes) {
83  sqlite3_finalize(fStmt->fRes);
84  }
85 
86  fStmt->fRes = nullptr;
87  fStmt->fConn = nullptr;
88  delete fStmt;
89 }
90 
91 
92 
93 // Reset error and check that statement exists
94 
96 
97 #define CheckStmt(method, res) \
98  { \
99  ClearError(); \
100  if (!fStmt) { \
101  SetError(-1,"Statement handle is 0",method); \
102  return res; \
103  } \
104  }
105 
106 
107 
109 
110 #define CheckErrNo(method, force, res) \
111  { \
112  int stmterrno = sqlite3_errcode(fStmt->fConn); \
113  if ((stmterrno!=0) || force) { \
114  const char* stmterrmsg = sqlite3_errmsg(fStmt->fConn); \
115  if (stmterrno==0) { stmterrno = -1; stmterrmsg = "SQLite statement error"; } \
116  SetError(stmterrno, stmterrmsg, method); \
117  return res; \
118  } \
119  }
120 
121 
122 
124 
125 #define CheckGetField(method, res) \
126  { \
127  ClearError(); \
128  if (!IsResultSetMode()) { \
129  SetError(-1,"Cannot get statement parameters",method); \
130  return res; \
131  } \
132  if ((npar<0) || (npar>=fNumPars)) { \
133  SetError(-1,Form("Invalid parameter number %d", npar),method); \
134  return res; \
135  } \
136  }
137 
138 
139 
140 
142 
143 Bool_t KVSQLiteStatement::CheckBindError(const char* method, int res)
144 {
145  if (res == SQLITE_RANGE) {
146  SetError(-1, Form("SQLite parameter out of bounds, error: %d %s", res, sqlite3_errmsg(fStmt->fConn)), method);
147  return kFALSE;
148  }
149  if (res != SQLITE_OK) {
150  SetError(-1, Form("SQLite error code during parameter binding, error: %d %s", res, sqlite3_errmsg(fStmt->fConn)), method);
151  return kFALSE;
152  }
153  return kTRUE;
154 }
155 
156 
159 
160 
162 
163 Bool_t KVSQLiteStatement::Process()
164 {
165  CheckStmt("Process", kFALSE);
166 
167  int res = sqlite3_step(fStmt->fRes);
168  if ((res != SQLITE_DONE) && (res != SQLITE_ROW)) {
169  if(res == SQLITE_BUSY)
170  {
171  // retry the statement 4 times after sleeping
172  int i=0;
173  do
174  {
175  ++i;
176  Info("Process","DB locked: retry same statement processing in 50ms...(%d)",i);
177  std::this_thread::sleep_for(50ms);
178  res = sqlite3_step(fStmt->fRes);
179  }
180  while((i<4) && ((res != SQLITE_DONE) && (res != SQLITE_ROW)));
181  if ((res != SQLITE_DONE) && (res != SQLITE_ROW))
182  {
183  SetError(-1, Form("SQLite error code during statement-stepping: %d %s", res, sqlite3_errmsg(fStmt->fConn)), "Process");
184  return kFALSE;
185  }
186  }
187  else
188  {
189  SetError(-1, Form("SQLite error code during statement-stepping: %d %s", res, sqlite3_errmsg(fStmt->fConn)), "Process");
190  return kFALSE;
191  }
192  }
193 
194  // After a DONE-step, we have to reset, note this still KEEPS the parameters bound in SQLite,
195  // real reset happens in finalize, but user can still reuse the query!
196  if (res == SQLITE_DONE) {
197  sqlite3_reset(fStmt->fRes);
198 
199  // If IsResultSetMode then this means we are done and should return kFALSE:
200  if (IsResultSetMode()) {
201  return kFALSE;
202  }
203 
204  // If IsSetParsMode then this means we just stepped and should return kTRUE:
205  if (IsSetParsMode()) {
206  return kTRUE;
207  }
208  }
209 
210  if (res == SQLITE_ROW) {
211  // Next row data retrieved, return kTRUE.
212  return kTRUE;
213  }
214 
215  return kFALSE;
216 }
217 
218 
223 
224 
226 
227 Int_t KVSQLiteStatement::GetNumAffectedRows()
228 {
229  CheckStmt("GetNumAffectedRows", kFALSE);
230 
231  return (Int_t) sqlite3_changes(fStmt->fConn);
232 }
233 
234 
237 
238 
240 
241 Int_t KVSQLiteStatement::GetNumParameters()
242 {
243  CheckStmt("GetNumParameters", -1);
244 
245  Int_t res = sqlite3_bind_parameter_count(fStmt->fRes);
246 
247  CheckErrNo("GetNumParameters", kFALSE, -1);
248 
249  return res;
250 }
251 
252 
257 
258 
260 
261 Bool_t KVSQLiteStatement::StoreResult()
262 {
263  fWorkingMode = 2;
264 
265  CheckStmt("StoreResult", kFALSE);
266 
267  return kTRUE;
268 }
269 
270 
273 
274 
276 
277 Int_t KVSQLiteStatement::GetNumFields()
278 {
279  return fNumPars;
280 }
281 
282 
285 
286 
288 
289 const char* KVSQLiteStatement::GetFieldName(Int_t nfield)
290 {
291  if (!IsResultSetMode() || (nfield < 0) || (nfield >= sqlite3_column_count(fStmt->fRes)))
292  return nullptr;
293 
294  return sqlite3_column_name(fStmt->fRes, nfield);
295 }
296 
297 
300 
301 
303 
304 Bool_t KVSQLiteStatement::NextResultRow()
305 {
306  ClearError();
307 
308  if (!fStmt || !IsResultSetMode()) return kFALSE;
309 
310  if (fIterationCount == 0) {
311  // The interface says user should call NextResultRow() before getting any data,
312  // this makes no sense at least for SQLite.
313  // We just return kTRUE here and only do something on second request.
314  fIterationCount++;
315  return kTRUE;
316  }
317 
318  return Process();
319 }
320 
321 
327 
328 
330 
331 Bool_t KVSQLiteStatement::NextIteration()
332 {
333  ClearError();
334 
335  if (!IsSetParsMode()) {
336  SetError(-1, "Cannot call for that statement", "NextIteration");
337  return kFALSE;
338  }
339 
340  if (fIterationCount == 0) {
341  // The interface says user should call NextIteration() before binding any parameters,
342  // this makes no sense at least for SQLite.
343  // We just return kTRUE here and wait for data to really do something.
344  fIterationCount++;
345  return kTRUE;
346  }
347 
348  fIterationCount++;
349 
350  return Process();
351 }
352 
353 
356 
357 
359 
360 const char* KVSQLiteStatement::ConvertToString(Int_t npar)
361 {
362  CheckGetField("ConvertToString", "");
363 
364  return reinterpret_cast<const char*>(sqlite3_column_text(fStmt->fRes, npar));
365 }
366 
367 
370 
371 
373 
374 long double KVSQLiteStatement::ConvertToNumeric(Int_t npar)
375 {
376  CheckGetField("ConvertToNumeric", -1);
377 
378  return (long double) sqlite3_column_double(fStmt->fRes, npar);
379 }
380 
381 
384 
385 
387 
388 Bool_t KVSQLiteStatement::IsNull(Int_t npar)
389 {
390  CheckGetField("IsNull", kFALSE);
391 
392  return (sqlite3_column_type(fStmt->fRes, npar) == SQLITE_NULL);
393 }
394 
395 
398 
399 
401 
402 Int_t KVSQLiteStatement::GetInt(Int_t npar)
403 {
404  CheckGetField("GetInt", -1);
405 
406  return (Int_t) sqlite3_column_int(fStmt->fRes, npar);
407 }
408 
409 
412 
413 
415 
416 UInt_t KVSQLiteStatement::GetUInt(Int_t npar)
417 {
418  CheckGetField("GetUInt", 0);
419 
420  return (UInt_t) sqlite3_column_int(fStmt->fRes, npar);
421 }
422 
423 
426 
427 
429 
430 Long_t KVSQLiteStatement::GetLong(Int_t npar)
431 {
432  CheckGetField("GetLong", -1);
433 
434  return (Long_t) sqlite3_column_int64(fStmt->fRes, npar);
435 }
436 
437 
440 
441 
443 
444 Long64_t KVSQLiteStatement::GetLong64(Int_t npar)
445 {
446  CheckGetField("GetLong64", -1);
447 
448  return (Long64_t) sqlite3_column_int64(fStmt->fRes, npar);
449 }
450 
451 
454 
455 
457 
458 ULong64_t KVSQLiteStatement::GetULong64(Int_t npar)
459 {
460  CheckGetField("GetULong64", 0);
461 
462  return (ULong64_t) sqlite3_column_int64(fStmt->fRes, npar);
463 }
464 
465 
468 
469 
471 
472 Double_t KVSQLiteStatement::GetDouble(Int_t npar)
473 {
474  CheckGetField("GetDouble", -1);
475 
476  return (Double_t) sqlite3_column_double(fStmt->fRes, npar);
477 }
478 
479 
482 
483 
485 
486 const char* KVSQLiteStatement::GetString(Int_t npar)
487 {
488  CheckGetField("GetString", "");
489 
490  return reinterpret_cast<const char*>(sqlite3_column_text(fStmt->fRes, npar));
491 }
492 
493 
498 
499 
501 
502 Bool_t KVSQLiteStatement::GetBinary(Int_t npar, void*& mem, Long_t& size)
503 {
504  CheckGetField("GetBinary", kFALSE);
505 
506  // As we retrieve "as blob", we do NOT call sqlite3_column_text() before
507  // sqlite3_column_bytes(), which might leave us with a non-zero terminated
508  // data struture, but this should be okay for BLOB.
509  size_t sz = sqlite3_column_bytes(fStmt->fRes, npar);
510  if ((Long_t)sz > size) {
511  delete [](unsigned char*) mem;
512  mem = (void*) new unsigned char[sz];
513  }
514  size = sz;
515 
516  memcpy(mem, sqlite3_column_blob(fStmt->fRes, npar), sz);
517 
518  return kTRUE;
519 }
520 
521 
524 
525 
527 
528 Bool_t KVSQLiteStatement::GetDate(Int_t npar, Int_t& year, Int_t& month, Int_t& day)
529 {
530  CheckGetField("GetDate", kFALSE);
531 
532  TString val = reinterpret_cast<const char*>(sqlite3_column_text(fStmt->fRes, npar));
533  TDatime d = TDatime(val.Data());
534  year = d.GetYear();
535  month = d.GetMonth();
536  day = d.GetDay();
537 
538  return kTRUE;
539 }
540 
541 
544 
545 
547 
548 Bool_t KVSQLiteStatement::GetTime(Int_t npar, Int_t& hour, Int_t& min, Int_t& sec)
549 {
550  CheckGetField("GetTime", kFALSE);
551 
552  TString val = reinterpret_cast<const char*>(sqlite3_column_text(fStmt->fRes, npar));
553  TDatime d = TDatime(val.Data());
554  hour = d.GetHour();
555  min = d.GetMinute();
556  sec = d.GetSecond();
557 
558  return kTRUE;
559 }
560 
561 
564 
565 
567 
568 Bool_t KVSQLiteStatement::GetDatime(Int_t npar, Int_t& year, Int_t& month, Int_t& day, Int_t& hour, Int_t& min, Int_t& sec)
569 {
570  CheckGetField("GetDatime", kFALSE);
571 
572  TString val = reinterpret_cast<const char*>(sqlite3_column_text(fStmt->fRes, npar));
573  TDatime d = TDatime(val.Data());
574  year = d.GetYear();
575  month = d.GetMonth();
576  day = d.GetDay();
577  hour = d.GetHour();
578  min = d.GetMinute();
579  sec = d.GetSecond();
580 
581  return kTRUE;
582 }
583 
584 
588 
589 
591 
592 Bool_t KVSQLiteStatement::GetTimestamp(Int_t npar, Int_t& year, Int_t& month, Int_t& day, Int_t& hour, Int_t& min, Int_t& sec, Int_t& frac)
593 {
594  CheckGetField("GetTimestamp", kFALSE);
595 
596  TString val = reinterpret_cast<const char*>(sqlite3_column_text(fStmt->fRes, npar));
597 
598  Ssiz_t p = val.Last('.');
599  TSubString ts_part = val(0, p);
600 
601  TDatime d(ts_part.Data());
602  year = d.GetYear();
603  month = d.GetMonth();
604  day = d.GetDay();
605  hour = d.GetHour();
606  min = d.GetMinute();
607  sec = d.GetSecond();
608 
609  TSubString s_frac = val(p, val.Length() - p + 1);
610  frac = (Int_t)(atof(s_frac.Data()) * 1.E3);
611 
612  return kTRUE;
613 }
614 
615 
618 
619 
621 
622 Bool_t KVSQLiteStatement::SetNull(Int_t npar)
623 {
624  int res = sqlite3_bind_null(fStmt->fRes, npar + 1);
625 
626  return CheckBindError("SetNull", res);
627 }
628 
629 
632 
633 
635 
636 Bool_t KVSQLiteStatement::SetInt(Int_t npar, Int_t value)
637 {
638  int res = sqlite3_bind_int(fStmt->fRes, npar + 1, value);
639 
640  return CheckBindError("SetInt", res);
641 }
642 
643 
647 
648 
650 
651 Bool_t KVSQLiteStatement::SetUInt(Int_t npar, UInt_t value)
652 {
653  int res = sqlite3_bind_int(fStmt->fRes, npar + 1, (Int_t)value);
654 
655  return CheckBindError("SetUInt", res);
656 }
657 
658 
661 
662 
664 
665 Bool_t KVSQLiteStatement::SetLong(Int_t npar, Long_t value)
666 {
667  int res = sqlite3_bind_int64(fStmt->fRes, npar + 1, value);
668 
669  return CheckBindError("SetLong", res);
670 }
671 
672 
675 
676 
678 
679 Bool_t KVSQLiteStatement::SetLong64(Int_t npar, Long64_t value)
680 {
681  int res = sqlite3_bind_int64(fStmt->fRes, npar + 1, value);
682 
683  return CheckBindError("SetLong64", res);
684 }
685 
686 
690 
691 
693 
694 Bool_t KVSQLiteStatement::SetULong64(Int_t npar, ULong64_t value)
695 {
696  int res = sqlite3_bind_int64(fStmt->fRes, npar + 1, (Long64_t)value);
697 
698  return CheckBindError("SetULong64", res);
699 }
700 
701 
704 
705 
707 
708 Bool_t KVSQLiteStatement::SetDouble(Int_t npar, Double_t value)
709 {
710  int res = sqlite3_bind_double(fStmt->fRes, npar + 1, value);
711 
712  return CheckBindError("SetDouble", res);
713 }
714 
715 
718 
719 
721 
722 Bool_t KVSQLiteStatement::SetString(Int_t npar, const char* value, Int_t maxsize)
723 {
724  int res = sqlite3_bind_text(fStmt->fRes, npar + 1, value, maxsize, SQLITE_TRANSIENT);
725 
726  return CheckBindError("SetString", res);
727 }
728 
729 
734 
735 
737 
738 Bool_t KVSQLiteStatement::SetBinary(Int_t npar, void* mem, Long_t size, Long_t /*maxsize*/)
739 {
740  if (size < 0) {
741  SetError(-1, "Passing negative value to size for BLOB to SQLite would cause undefined behaviour, refusing it!", "SetBinary");
742  return kFALSE;
743  }
744 
745  int res = sqlite3_bind_blob(fStmt->fRes, npar + 1, mem, (size_t)size, SQLITE_TRANSIENT);
746 
747  return CheckBindError("SetBinary", res);
748 }
749 
750 
753 
754 
756 
757 Bool_t KVSQLiteStatement::SetDate(Int_t npar, Int_t year, Int_t month, Int_t day)
758 {
759  TDatime d = TDatime(year, month, day, 0, 0, 0);
760  int res = sqlite3_bind_text(fStmt->fRes, npar + 1, (char*)d.AsSQLString(), -1, SQLITE_TRANSIENT);
761 
762  return CheckBindError("SetDate", res);
763 }
764 
765 
768 
769 
771 
772 Bool_t KVSQLiteStatement::SetTime(Int_t npar, Int_t hour, Int_t min, Int_t sec)
773 {
774  TDatime d = TDatime(2000, 1, 1, hour, min, sec);
775 
776  int res = sqlite3_bind_text(fStmt->fRes, npar + 1, (char*)d.AsSQLString(), -1, SQLITE_TRANSIENT);
777 
778  return CheckBindError("SetTime", res);
779 }
780 
781 
784 
785 
787 
788 Bool_t KVSQLiteStatement::SetDatime(Int_t npar, Int_t year, Int_t month, Int_t day, Int_t hour, Int_t min, Int_t sec)
789 {
790  TDatime d = TDatime(year, month, day, hour, min, sec);
791 
792  int res = sqlite3_bind_text(fStmt->fRes, npar + 1, (char*)d.AsSQLString(), -1, SQLITE_TRANSIENT);
793 
794  return CheckBindError("SetDatime", res);
795 }
796 
797 
802 
803 
805 
806 Bool_t KVSQLiteStatement::SetTimestamp(Int_t npar, Int_t year, Int_t month, Int_t day, Int_t hour, Int_t min, Int_t sec, Int_t frac)
807 {
808  TDatime d(year, month, day, hour, min, sec);
809  TString value;
810  value.Form("%s.%03d", (char*)d.AsSQLString(), frac);
811 
812  int res = sqlite3_bind_text(fStmt->fRes, npar + 1, value.Data(), -1, SQLITE_TRANSIENT);
813 
814  return CheckBindError("SetTimestamp", res);
815 }
816 
817 
int Int_t
unsigned int UInt_t
long Long_t
#define d(i)
size_t size(const MatrixT &matrix)
bool Bool_t
int Ssiz_t
constexpr Bool_t kFALSE
double Double_t
constexpr Bool_t kTRUE
const char Option_t
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
char * Form(const char *fmt,...)
Ssiz_t Length() const
const char * Data() const
Ssiz_t Last(char c) const
const char * Data() const
long long Long64_t
unsigned long long ULong64_t
void Info(const char *location, const char *fmt,...)
double min(double x, double y)
ClassImp(TPyArg)