Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TSQLiteStatement.cxx
Go to the documentation of this file.
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
12//////////////////////////////////////////////////////////////////////////
13// //
14// SQL statement class for SQLite. //
15// //
16// See TSQLStatement class documentation for more details. //
17// //
18//////////////////////////////////////////////////////////////////////////
19
20#include "TSQLiteStatement.h"
21#include "TSQLiteResult.h"
22#include "TDataType.h"
23#include "TDatime.h"
24#include "TTimeStamp.h"
25
26#include <sqlite3.h>
27
28#include <stdlib.h>
29
31
32////////////////////////////////////////////////////////////////////////////////
33/// Normal constructor.
34/// Checks if statement contains parameters tags.
35
37 TSQLStatement(errout),
38 fStmt(stmt),
39 fWorkingMode(0),
40 fNumPars(0),
41 fIterationCount(0)
42{
43 unsigned long bindParamcount = sqlite3_bind_parameter_count(fStmt->fRes);
44
45 if (bindParamcount > 0) {
46 fWorkingMode = 1;
47 fNumPars = bindParamcount;
48 } else {
49 fWorkingMode = 2;
50 fNumPars = sqlite3_column_count(fStmt->fRes);
51 }
52}
53
54////////////////////////////////////////////////////////////////////////////////
55/// Destructor.
56
58{
59 Close();
60}
61
62////////////////////////////////////////////////////////////////////////////////
63/// Close statement.
64
66{
67 if (fStmt->fRes) {
68 sqlite3_finalize(fStmt->fRes);
69 }
70
71 fStmt->fRes = nullptr;
72 fStmt->fConn = nullptr;
73 delete fStmt;
74}
75
76
77// Reset error and check that statement exists
78#define CheckStmt(method, res) \
79 { \
80 ClearError(); \
81 if (fStmt==0) { \
82 SetError(-1,"Statement handle is 0",method); \
83 return res; \
84 } \
85 }
86
87#define CheckErrNo(method, force, res) \
88 { \
89 int stmterrno = sqlite3_errcode(fStmt->fConn); \
90 if ((stmterrno!=0) || force) { \
91 const char* stmterrmsg = sqlite3_errmsg(fStmt->fConn); \
92 if (stmterrno==0) { stmterrno = -1; stmterrmsg = "SQLite statement error"; } \
93 SetError(stmterrno, stmterrmsg, method); \
94 return res; \
95 } \
96 }
97
98#define CheckGetField(method, res) \
99 { \
100 ClearError(); \
101 if (!IsResultSetMode()) { \
102 SetError(-1,"Cannot get statement parameters",method); \
103 return res; \
104 } \
105 if ((npar<0) || (npar>=fNumPars)) { \
106 SetError(-1,Form("Invalid parameter number %d", npar),method); \
107 return res; \
108 } \
109 }
110
111
112Bool_t TSQLiteStatement::CheckBindError(const char *method, int res)
113{
114 if (res == SQLITE_RANGE) {
115 SetError(-1, Form("SQLite parameter out of bounds, error: %d %s", res, sqlite3_errmsg(fStmt->fConn)), method);
116 return kFALSE;
117 }
118 if (res != SQLITE_OK) {
119 SetError(-1, Form("SQLite error code during parameter binding, error: %d %s", res, sqlite3_errmsg(fStmt->fConn)), method);
120 return kFALSE;
121 }
122 return kTRUE;
123}
124
125////////////////////////////////////////////////////////////////////////////////
126/// Process statement.
127
129{
130 CheckStmt("Process", kFALSE);
131
132 int res = sqlite3_step(fStmt->fRes);
133 if ((res != SQLITE_DONE) && (res != SQLITE_ROW)) {
134 SetError(-1, Form("SQLite error code during statement-stepping: %d %s", res, sqlite3_errmsg(fStmt->fConn)), "Process");
135 return kFALSE;
136 }
137
138 // After a DONE-step, we have to reset, note this still KEEPS the parameters bound in SQLite,
139 // real reset happens in finalize, but user can still reuse the query!
140 if (res == SQLITE_DONE) {
141 sqlite3_reset(fStmt->fRes);
142
143 // If IsResultSetMode then this means we are done and should return kFALSE:
144 if (IsResultSetMode()) {
145 return kFALSE;
146 }
147
148 // If IsSetParsMode then this means we just stepped and should return kTRUE:
149 if (IsSetParsMode()) {
150 return kTRUE;
151 }
152 }
153
154 if (res == SQLITE_ROW) {
155 // Next row data retrieved, return kTRUE.
156 return kTRUE;
157 }
158
159 return kFALSE;
160}
161
162////////////////////////////////////////////////////////////////////////////////
163/// Return number of affected rows after statement is processed.
164/// Indirect changes e.g. by triggers are not counted, only direct changes
165/// from last completed statement are taken into account.
166
168{
169 CheckStmt("GetNumAffectedRows", kFALSE);
170
171 return (Int_t) sqlite3_changes(fStmt->fConn);
172}
173
174////////////////////////////////////////////////////////////////////////////////
175/// Return number of statement parameters.
176
178{
179 CheckStmt("GetNumParameters", -1);
180
181 Int_t res = sqlite3_bind_parameter_count(fStmt->fRes);
182
183 CheckErrNo("GetNumParameters", kFALSE, -1);
184
185 return res;
186}
187
188////////////////////////////////////////////////////////////////////////////////
189/// Store result of statement processing to access them
190/// via GetInt(), GetDouble() and so on methods.
191/// For SQLite, this is a NO-OP.
192
194{
195 fWorkingMode = 2;
196
197 CheckStmt("StoreResult", kFALSE);
198
199 return kTRUE;
200}
201
202////////////////////////////////////////////////////////////////////////////////
203/// Return number of fields in result set.
204
206{
207 return fNumPars;
208}
209
210////////////////////////////////////////////////////////////////////////////////
211/// Returns field name in result set.
212
214{
215 if (!IsResultSetMode() || (nfield < 0) || (nfield >= sqlite3_column_count(fStmt->fRes))) {
216 return 0;
217 }
218
219 return sqlite3_column_name(fStmt->fRes, nfield);
220}
221
222////////////////////////////////////////////////////////////////////////////////
223/// Shift cursor to next row in result set.
224
226{
227 ClearError();
228
229 if (!fStmt || !IsResultSetMode()) return kFALSE;
230
231 if (fIterationCount == 0) {
232 // The interface says user should call NextResultRow() before getting any data,
233 // this makes no sense at least for SQLite.
234 // We just return kTRUE here and only do something on second request.
236 return kTRUE;
237 }
238
239 return Process();
240}
241
242////////////////////////////////////////////////////////////////////////////////
243/// Increment iteration counter for statement, where parameter can be set.
244/// Statement with parameters of previous iteration
245/// automatically will be applied to database.
246/// Actually a NO-OP for SQLite, as parameters stay bound when step-ping.
247
249{
250 ClearError();
251
252 if (!IsSetParsMode()) {
253 SetError(-1, "Cannot call for that statement", "NextIteration");
254 return kFALSE;
255 }
256
257 if (fIterationCount == 0) {
258 // The interface says user should call NextIteration() before binding any parameters,
259 // this makes no sense at least for SQLite.
260 // We just return kTRUE here and wait for data to really do something.
262 return kTRUE;
263 }
264
266
267 return Process();
268}
269
270////////////////////////////////////////////////////////////////////////////////
271/// Convert field value to string.
272
274{
275 CheckGetField("ConvertToString", "");
276
277 return reinterpret_cast<const char *>(sqlite3_column_text(fStmt->fRes, npar));
278}
279
280////////////////////////////////////////////////////////////////////////////////
281/// Convert field to numeric.
282
284{
285 CheckGetField("ConvertToNumeric", -1);
286
287 return (long double) sqlite3_column_double(fStmt->fRes, npar);
288}
289
290////////////////////////////////////////////////////////////////////////////////
291/// Checks if field value is null.
292
294{
295 CheckGetField("IsNull", kFALSE);
296
297 return (sqlite3_column_type(fStmt->fRes, npar) == SQLITE_NULL);
298}
299
300////////////////////////////////////////////////////////////////////////////////
301/// Get integer.
302
304{
305 CheckGetField("GetInt", -1);
306
307 return (Int_t) sqlite3_column_int(fStmt->fRes, npar);
308}
309
310////////////////////////////////////////////////////////////////////////////////
311/// Get unsigned integer.
312
314{
315 CheckGetField("GetUInt", 0);
316
317 return (UInt_t) sqlite3_column_int(fStmt->fRes, npar);
318}
319
320////////////////////////////////////////////////////////////////////////////////
321/// Get long.
322
324{
325 CheckGetField("GetLong", -1);
326
327 return (Long_t) sqlite3_column_int64(fStmt->fRes, npar);
328}
329
330////////////////////////////////////////////////////////////////////////////////
331/// Get long64.
332
334{
335 CheckGetField("GetLong64", -1);
336
337 return (Long64_t) sqlite3_column_int64(fStmt->fRes, npar);
338}
339
340////////////////////////////////////////////////////////////////////////////////
341/// Return field value as unsigned 64-bit integer
342
344{
345 CheckGetField("GetULong64", 0);
346
347 return (ULong64_t) sqlite3_column_int64(fStmt->fRes, npar);
348}
349
350////////////////////////////////////////////////////////////////////////////////
351/// Return field value as double.
352
354{
355 CheckGetField("GetDouble", -1);
356
357 return (Double_t) sqlite3_column_double(fStmt->fRes, npar);
358}
359
360////////////////////////////////////////////////////////////////////////////////
361/// Return field value as string.
362
364{
365 CheckGetField("GetString", "");
366
367 return reinterpret_cast<const char *>(sqlite3_column_text(fStmt->fRes, npar));
368}
369
370////////////////////////////////////////////////////////////////////////////////
371/// Return field value as binary array.
372/// Memory at 'mem' will be reallocated and size updated
373/// to fit the data if not large enough.
374
376{
377 CheckGetField("GetBinary", kFALSE);
378
379 // As we retrieve "as blob", we do NOT call sqlite3_column_text() before
380 // sqlite3_column_bytes(), which might leave us with a non-zero terminated
381 // data struture, but this should be okay for BLOB.
382 size_t sz = sqlite3_column_bytes(fStmt->fRes, npar);
383 if ((Long_t)sz > size) {
384 delete [](unsigned char*) mem;
385 mem = (void*) new unsigned char[sz];
386 }
387 size = sz;
388
389 memcpy(mem, sqlite3_column_blob(fStmt->fRes, npar), sz);
390
391 return kTRUE;
392}
393
394////////////////////////////////////////////////////////////////////////////////
395/// Return field value as date.
396
398{
399 CheckGetField("GetDate", kFALSE);
400
401 TString val = reinterpret_cast<const char*>(sqlite3_column_text(fStmt->fRes, npar));
402 TDatime d = TDatime(val.Data());
403 year = d.GetYear();
404 month = d.GetMonth();
405 day = d.GetDay();
406
407 return kTRUE;
408}
409
410////////////////////////////////////////////////////////////////////////////////
411/// Return field as time.
412
414{
415 CheckGetField("GetTime", kFALSE);
416
417 TString val = reinterpret_cast<const char*>(sqlite3_column_text(fStmt->fRes, npar));
418 TDatime d = TDatime(val.Data());
419 hour = d.GetHour();
420 min = d.GetMinute();
421 sec = d.GetSecond();
422
423 return kTRUE;
424}
425
426////////////////////////////////////////////////////////////////////////////////
427/// Return field value as date & time.
428
429Bool_t TSQLiteStatement::GetDatime(Int_t npar, Int_t& year, Int_t& month, Int_t& day, Int_t& hour, Int_t& min, Int_t& sec)
430{
431 CheckGetField("GetDatime", kFALSE);
432
433 TString val = reinterpret_cast<const char*>(sqlite3_column_text(fStmt->fRes, npar));
434 TDatime d = TDatime(val.Data());
435 year = d.GetYear();
436 month = d.GetMonth();
437 day = d.GetDay();
438 hour = d.GetHour();
439 min = d.GetMinute();
440 sec = d.GetSecond();
441
442 return kTRUE;
443}
444
445////////////////////////////////////////////////////////////////////////////////
446/// Return field as timestamp.
447/// Second fraction is in milliseconds, which is also the precision all date and time functions of sqlite use.
448
449Bool_t TSQLiteStatement::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)
450{
451 CheckGetField("GetTimestamp", kFALSE);
452
453 TString val = reinterpret_cast<const char*>(sqlite3_column_text(fStmt->fRes, npar));
454
455 Ssiz_t p = val.Last('.');
456 TSubString ts_part = val(0, p);
457
458 TDatime d(ts_part.Data());
459 year = d.GetYear();
460 month = d.GetMonth();
461 day = d.GetDay();
462 hour = d.GetHour();
463 min = d.GetMinute();
464 sec = d.GetSecond();
465
466 TSubString s_frac = val(p, val.Length() - p+1);
467 frac=(Int_t) (atof(s_frac.Data())*1.E3);
468
469 return kTRUE;
470}
471
472////////////////////////////////////////////////////////////////////////////////
473/// Set NULL as parameter value.
474
476{
477 int res = sqlite3_bind_null(fStmt->fRes, npar + 1);
478
479 return CheckBindError("SetNull", res);
480}
481
482////////////////////////////////////////////////////////////////////////////////
483/// Set parameter value as integer.
484
486{
487 int res = sqlite3_bind_int(fStmt->fRes, npar + 1, value);
488
489 return CheckBindError("SetInt", res);
490}
491
492////////////////////////////////////////////////////////////////////////////////
493/// Set parameter value as unsigned integer.
494/// Actually casted to signed integer, has to be re-casted upon read!
495
497{
498 int res = sqlite3_bind_int(fStmt->fRes, npar + 1, (Int_t)value);
499
500 return CheckBindError("SetUInt", res);
501}
502
503////////////////////////////////////////////////////////////////////////////////
504/// Set parameter value as long.
505
507{
508 int res = sqlite3_bind_int64(fStmt->fRes, npar + 1, value);
509
510 return CheckBindError("SetLong", res);
511}
512
513////////////////////////////////////////////////////////////////////////////////
514/// Set parameter value as 64-bit integer.
515
517{
518 int res = sqlite3_bind_int64(fStmt->fRes, npar + 1, value);
519
520 return CheckBindError("SetLong64", res);
521}
522
523////////////////////////////////////////////////////////////////////////////////
524/// Set parameter value as unsigned 64-bit integer.
525/// Actually casted to signed integer, has to be re-casted upon read!
526
528{
529 int res = sqlite3_bind_int64(fStmt->fRes, npar + 1, (Long64_t)value);
530
531 return CheckBindError("SetULong64", res);
532}
533
534////////////////////////////////////////////////////////////////////////////////
535/// Set parameter value as double value.
536
538{
539 int res = sqlite3_bind_double(fStmt->fRes, npar + 1, value);
540
541 return CheckBindError("SetDouble", res);
542}
543
544////////////////////////////////////////////////////////////////////////////////
545/// Set parameter value as string.
546
547Bool_t TSQLiteStatement::SetString(Int_t npar, const char* value, Int_t maxsize)
548{
549 int res = sqlite3_bind_text(fStmt->fRes, npar + 1, value, maxsize, SQLITE_TRANSIENT);
550
551 return CheckBindError("SetString", res);
552}
553
554////////////////////////////////////////////////////////////////////////////////
555/// Set parameter value as binary data.
556/// Maxsize is ignored for SQLite, we directly insert BLOB of size 'size'.
557/// Negative size would cause undefined behaviour, so we refuse that.
558
560{
561 if (size < 0) {
562 SetError(-1, "Passing negative value to size for BLOB to SQLite would cause undefined behaviour, refusing it!", "SetBinary");
563 return kFALSE;
564 }
565
566 int res = sqlite3_bind_blob(fStmt->fRes, npar + 1, mem, (size_t)size, SQLITE_TRANSIENT);
567
568 return CheckBindError("SetBinary", res);
569}
570
571////////////////////////////////////////////////////////////////////////////////
572/// Set parameter value as date.
573
575{
576 TDatime d = TDatime(year, month, day, 0, 0, 0);
577 int res = sqlite3_bind_text(fStmt->fRes, npar + 1, (char*)d.AsSQLString(), -1, SQLITE_TRANSIENT);
578
579 return CheckBindError("SetDate", res);
580}
581
582////////////////////////////////////////////////////////////////////////////////
583/// Set parameter value as time.
584
586{
587 TDatime d = TDatime(2000, 1, 1, hour, min, sec);
588
589 int res = sqlite3_bind_text(fStmt->fRes, npar + 1, (char*)d.AsSQLString(), -1, SQLITE_TRANSIENT);
590
591 return CheckBindError("SetTime", res);
592}
593
594////////////////////////////////////////////////////////////////////////////////
595/// Set parameter value as date & time.
596
597Bool_t TSQLiteStatement::SetDatime(Int_t npar, Int_t year, Int_t month, Int_t day, Int_t hour, Int_t min, Int_t sec)
598{
599 TDatime d = TDatime(year, month, day, hour, min, sec);
600
601 int res = sqlite3_bind_text(fStmt->fRes, npar + 1, (char*)d.AsSQLString(), -1, SQLITE_TRANSIENT);
602
603 return CheckBindError("SetDatime", res);
604}
605
606////////////////////////////////////////////////////////////////////////////////
607/// Set parameter value as timestamp.
608/// The second fraction has to be in milliseconds,
609/// as all SQLite functions for date and time assume 3 significant digits.
610
611Bool_t TSQLiteStatement::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)
612{
613 TDatime d(year,month,day,hour,min,sec);
614 TString value;
615 value.Form("%s.%03d", (char*)d.AsSQLString(), frac);
616
617 int res = sqlite3_bind_text(fStmt->fRes, npar + 1, value.Data(), -1, SQLITE_TRANSIENT);
618
619 return CheckBindError("SetTimestamp", res);
620}
#define d(i)
Definition RSha256.hxx:102
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
int Int_t
Definition RtypesCore.h:45
const Bool_t kFALSE
Definition RtypesCore.h:101
long Long_t
Definition RtypesCore.h:54
double Double_t
Definition RtypesCore.h:59
long long Long64_t
Definition RtypesCore.h:80
unsigned long long ULong64_t
Definition RtypesCore.h:81
const Bool_t kTRUE
Definition RtypesCore.h:100
const char Option_t
Definition RtypesCore.h:66
#define ClassImp(name)
Definition Rtypes.h:364
#define CheckErrNo(method, force, res)
#define CheckGetField(method, defres)
#define CheckStmt(method, res)
char * Form(const char *fmt,...)
This class stores the date and time with a precision of one second in an unsigned 32 bit word (950130...
Definition TDatime.h:37
void SetError(Int_t code, const char *msg, const char *method=nullptr)
set new values for error fields if method specified, displays error message
void ClearError()
reset error fields
Bool_t SetString(Int_t npar, const char *value, Int_t maxsize=256) final
Set parameter value as string.
Bool_t 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=0) final
Set parameter value as timestamp.
Bool_t GetTime(Int_t npar, Int_t &hour, Int_t &min, Int_t &sec) final
Return field as time.
void Close(Option_t *="") final
Close statement.
Bool_t SetTime(Int_t npar, Int_t hour, Int_t min, Int_t sec) final
Set parameter value as time.
Bool_t SetBinary(Int_t npar, void *mem, Long_t size, Long_t maxsize=0x1000) final
Set parameter value as binary data.
Bool_t SetLong64(Int_t npar, Long64_t value) final
Set parameter value as 64-bit integer.
UInt_t GetUInt(Int_t npar) final
Get unsigned integer.
Bool_t GetTimestamp(Int_t npar, Int_t &year, Int_t &month, Int_t &day, Int_t &hour, Int_t &min, Int_t &sec, Int_t &) final
Return field as timestamp.
Bool_t IsNull(Int_t npar) final
Checks if field value is null.
Bool_t GetDatime(Int_t npar, Int_t &year, Int_t &month, Int_t &day, Int_t &hour, Int_t &min, Int_t &sec) final
Return field value as date & time.
virtual ~TSQLiteStatement()
Destructor.
SQLite3_Stmt_t * fStmt
Bool_t SetDate(Int_t npar, Int_t year, Int_t month, Int_t day) final
Set parameter value as date.
Int_t fIterationCount
Number of bindable / gettable parameters.
Long_t GetLong(Int_t npar) final
Get long.
Int_t GetInt(Int_t npar) final
Get integer.
Bool_t GetBinary(Int_t npar, void *&mem, Long_t &size) final
Return field value as binary array.
Bool_t CheckBindError(const char *method, int res)
ULong64_t GetULong64(Int_t npar) final
Return field value as unsigned 64-bit integer.
Bool_t SetLong(Int_t npar, Long_t value) final
Set parameter value as long.
const char * GetString(Int_t npar) final
Return field value as string.
Bool_t SetNull(Int_t npar) final
Set NULL as parameter value.
const char * ConvertToString(Int_t npar)
Convert field value to string.
Int_t fWorkingMode
executed statement
Bool_t SetInt(Int_t npar, Int_t value) final
Set parameter value as integer.
Bool_t IsSetParsMode() const
Iteration count.
Bool_t GetDate(Int_t npar, Int_t &year, Int_t &month, Int_t &day) final
Return field value as date.
Int_t fNumPars
1 - setting parameters, 2 - retrieving results
Long64_t GetLong64(Int_t npar) final
Get long64.
Bool_t NextIteration() final
Increment iteration counter for statement, where parameter can be set.
Bool_t IsResultSetMode() const
Bool_t StoreResult() final
Store result of statement processing to access them via GetInt(), GetDouble() and so on methods.
Bool_t SetDouble(Int_t npar, Double_t value) final
Set parameter value as double value.
Int_t GetNumAffectedRows() final
Return number of affected rows after statement is processed.
Bool_t Process() final
Process statement.
Bool_t SetULong64(Int_t npar, ULong64_t value) final
Set parameter value as unsigned 64-bit integer.
Bool_t SetUInt(Int_t npar, UInt_t value) final
Set parameter value as unsigned integer.
Bool_t SetDatime(Int_t npar, Int_t year, Int_t month, Int_t day, Int_t hour, Int_t min, Int_t sec) final
Set parameter value as date & time.
Bool_t NextResultRow() final
Shift cursor to next row in result set.
const char * GetFieldName(Int_t nfield) final
Returns field name in result set.
Int_t GetNumFields() final
Return number of fields in result set.
Double_t GetDouble(Int_t npar) final
Return field value as double.
Int_t GetNumParameters() final
Return number of statement parameters.
TSQLiteStatement(SQLite3_Stmt_t *stmt, Bool_t errout=kTRUE)
Normal constructor.
long double ConvertToNumeric(Int_t npar)
Convert field to numeric.
Basic string class.
Definition TString.h:136
Ssiz_t Length() const
Definition TString.h:410
const char * Data() const
Definition TString.h:369
Ssiz_t Last(char c) const
Find last occurrence of a character c.
Definition TString.cxx:916
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition TString.cxx:2314
A zero length substring is legal.
Definition TString.h:82
const char * Data() const
Definition TString.h:726
sqlite3_stmt * fRes