Logo ROOT  
Reference Guide
TPgSQLStatement.cxx
Go to the documentation of this file.
1 // @(#)root/pgsql:$Id$
2// Author: Dennis Box (dbox@fnal.gov) 3/12/2007
3
4/*************************************************************************
5 * Copyright (C) 1995-2007, 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 PgSQL //
15// //
16// See TSQLStatement class documentation for more details. //
17// //
18//////////////////////////////////////////////////////////////////////////
19
20#include "TPgSQLStatement.h"
21#include "TDataType.h"
22#include "TDatime.h"
23#include "TTimeStamp.h"
24#include "TMath.h"
25
26#include <stdlib.h>
27
28#define pgsql_success(x) (((x) == PGRES_EMPTY_QUERY) \
29 || ((x) == PGRES_COMMAND_OK) \
30 || ((x) == PGRES_TUPLES_OK))
31
32
34
35#ifdef PG_VERSION_NUM
36
37#include "libpq/libpq-fs.h"
38
39static const Int_t kBindStringSize = 30; // big enough to handle text rep. of 64 bit number and timestamp (e.g. "1970-01-01 01:01:01.111111+00")
40
41////////////////////////////////////////////////////////////////////////////////
42/// Normal constructor.
43/// Checks if statement contains parameters tags.
44
46 TSQLStatement(errout),
47 fStmt(stmt),
48 fNumBuffers(0),
49 fBind(nullptr),
50 fFieldName(nullptr),
51 fWorkingMode(0),
52 fIterationCount(0),
53 fParamLengths(nullptr),
54 fParamFormats(nullptr),
55 fNumResultRows(0),
56 fNumResultCols(0)
57{
58 // Given fRes not used, we retrieve the statement using the connection.
59 if (fStmt->fRes != nullptr) {
60 PQclear(fStmt->fRes);
61 }
62
63 fStmt->fRes = PQdescribePrepared(fStmt->fConn,"preparedstmt");
64 unsigned long paramcount = PQnparams(fStmt->fRes);
65 fNumResultCols = PQnfields(fStmt->fRes);
66 fIterationCount = -1;
67
68 if (paramcount>0) {
69 fWorkingMode = 1;
70 SetBuffersNumber(paramcount);
71 } else {
72 fWorkingMode = 2;
73 SetBuffersNumber(fNumResultCols);
74 }
75}
76
77////////////////////////////////////////////////////////////////////////////////
78/// Destructor.
79
81{
82 Close();
83}
84
85////////////////////////////////////////////////////////////////////////////////
86/// Close statement.
87
89{
90 if (fStmt->fRes)
91 PQclear(fStmt->fRes);
92
93 fStmt->fRes = nullptr;
94
95 PGresult *res=PQexec(fStmt->fConn,"DEALLOCATE preparedstmt;");
96 PQclear(res);
97
99 //TPgSQLServers responsibility to free connection
100 fStmt->fConn = nullptr;
101 delete fStmt;
102}
103
104
105// Reset error and check that statement exists
106#define CheckStmt(method, res) \
107 { \
108 ClearError(); \
109 if (fStmt==0) { \
110 SetError(-1,"Statement handle is 0",method); \
111 return res; \
112 } \
113 }
114
115#define CheckErrNo(method, force, wtf) \
116 { \
117 int stmterrno = PQresultStatus(fStmt->fRes); \
118 if ((stmterrno!=0) || force) { \
119 const char* stmterrmsg = PQresultErrorMessage(fStmt->fRes); \
120 if (stmterrno==0) { stmterrno = -1; stmterrmsg = "PgSQL statement error"; } \
121 SetError(stmterrno, stmterrmsg, method); \
122 return wtf; \
123 } \
124 }
125
126#define CheckErrResult(method, pqresult, retVal) \
127 { \
128 ExecStatusType stmterrno=PQresultStatus(pqresult); \
129 if (!pgsql_success(stmterrno)) { \
130 const char* stmterrmsg = PQresultErrorMessage(fStmt->fRes); \
131 SetError(stmterrno, stmterrmsg, method); \
132 PQclear(res); \
133 return retVal; \
134 } \
135 }
136
137#define RollBackTransaction(method) \
138 { \
139 PGresult *resnum=PQexec(fStmt->fConn,"COMMIT"); \
140 CheckErrResult("RollBackTransaction", resnum, kFALSE); \
141 PQclear(res); \
142 }
143
144// check last pgsql statement error code
145#define CheckGetField(method, res) \
146 { \
147 ClearError(); \
148 if (!IsResultSetMode()) { \
149 SetError(-1,"Cannot get statement parameters",method); \
150 return res; \
151 } \
152 if ((npar<0) || (npar>=fNumBuffers)) { \
153 SetError(-1,Form("Invalid parameter number %d", npar),method); \
154 return res; \
155 } \
156 }
157
158////////////////////////////////////////////////////////////////////////////////
159/// Process statement.
160
162{
163 CheckStmt("Process",kFALSE);
164
165 // We create the prepared statement below, MUST delete the old one
166 // from our constructor first!
167 if (fStmt->fRes != NULL) {
168 PQclear(fStmt->fRes);
169 }
170
171 if (IsSetParsMode()) {
172 fStmt->fRes= PQexecPrepared(fStmt->fConn,"preparedstmt",fNumBuffers,
173 (const char* const*)fBind,
176 0);
177
178 } else { //result set mode
179 fStmt->fRes= PQexecPrepared(fStmt->fConn,"preparedstmt",0,(const char* const*) nullptr, nullptr, nullptr,0);
180 }
181 ExecStatusType stat = PQresultStatus(fStmt->fRes);
182 if (!pgsql_success(stat))
183 CheckErrNo("Process",kTRUE, kFALSE);
184 return kTRUE;
185}
186
187////////////////////////////////////////////////////////////////////////////////
188/// Return number of affected rows after statement is processed.
189
191{
192 CheckStmt("GetNumAffectedRows", -1);
193
194 return (Int_t) atoi(PQcmdTuples(fStmt->fRes));
195}
196
197////////////////////////////////////////////////////////////////////////////////
198/// Return number of statement parameters.
199
201{
202 CheckStmt("GetNumParameters", -1);
203
204 if (IsSetParsMode()) {
205 return fNumBuffers;
206 } else {
207 return 0;
208 }
209}
210
211////////////////////////////////////////////////////////////////////////////////
212/// Store result of statement processing to access them
213/// via GetInt(), GetDouble() and so on methods.
214
216{
217 int i;
218 for (i=0;i<fNumResultCols;i++){
219 fFieldName[i] = PQfname(fStmt->fRes,i);
220 fParamFormats[i]=PQftype(fStmt->fRes,i);
221 fParamLengths[i]=PQfsize(fStmt->fRes,i);
222
223 }
224 fNumResultRows=PQntuples(fStmt->fRes);
225 ExecStatusType stat = PQresultStatus(fStmt->fRes);
226 fWorkingMode = 2;
227 if (!pgsql_success(stat))
228 CheckErrNo("StoreResult",kTRUE, kFALSE);
229 return kTRUE;
230}
231
232////////////////////////////////////////////////////////////////////////////////
233/// Return number of fields in result set.
234
236{
237 if (fWorkingMode==1)
238 return fNumBuffers;
239 if (fWorkingMode==2)
240 return fNumResultCols;
241 return -1;
242}
243
244////////////////////////////////////////////////////////////////////////////////
245/// Returns field name in result set.
246
247const char* TPgSQLStatement::GetFieldName(Int_t nfield)
248{
249 if (!IsResultSetMode() || (nfield<0) || (nfield>=fNumBuffers)) return 0;
250
251 return fFieldName[nfield];
252}
253
254////////////////////////////////////////////////////////////////////////////////
255/// Shift cursor to nect row in result set.
256
258{
259 if ((fStmt==0) || !IsResultSetMode()) return kFALSE;
260
261 Bool_t res=kTRUE;
262
265 res=kFALSE;
266 return res;
267}
268
269////////////////////////////////////////////////////////////////////////////////
270/// Increment iteration counter for statement, where parameter can be set.
271/// Statement with parameters of previous iteration
272/// automatically will be applied to database.
273
275{
276 ClearError();
277
278 if (!IsSetParsMode() || (fBind==0)) {
279 SetError(-1,"Cannot call for that statement","NextIteration");
280 return kFALSE;
281 }
282
284
285 if (fIterationCount==0) return kTRUE;
286
287 fStmt->fRes= PQexecPrepared(fStmt->fConn,"preparedstmt",fNumBuffers,
288 (const char* const*)fBind,
291 0);
292 ExecStatusType stat = PQresultStatus(fStmt->fRes);
293 if (!pgsql_success(stat) ){
294 CheckErrNo("NextIteration", kTRUE, kFALSE) ;
295 return kFALSE;
296 }
297 return kTRUE;
298}
299
300////////////////////////////////////////////////////////////////////////////////
301/// Release all buffers, used by statement.
302
304{
305 //individual field names free()'ed by PQclear of fStmt->fRes
306 if (fFieldName)
307 delete[] fFieldName;
308
309 if (fBind){
310 for (Int_t i=0;i<fNumBuffers;i++)
311 delete [] fBind[i];
312 delete[] fBind;
313 }
314
315 if (fParamLengths)
316 delete [] fParamLengths;
317
318 if (fParamFormats)
319 delete [] fParamFormats;
320
321 fFieldName = nullptr;
322 fBind = nullptr;
323 fNumBuffers = 0;
324 fParamLengths = nullptr;
325 fParamFormats = nullptr;
326}
327
328////////////////////////////////////////////////////////////////////////////////
329/// Allocate buffers for statement parameters/ result fields.
330
332{
333 FreeBuffers();
334 if (numpars<=0) return;
335
336 fNumBuffers = numpars;
337
338 fBind = new char*[fNumBuffers];
339 for(int i=0; i<fNumBuffers; ++i){
340 fBind[i] = new char[kBindStringSize];
341 }
342 fFieldName = new char*[fNumBuffers];
343
344 fParamLengths = new int[fNumBuffers];
345 memset(fParamLengths, 0, sizeof(int)*fNumBuffers);
346
347 fParamFormats = new int[fNumBuffers];
348 memset(fParamFormats, 0, sizeof(int)*fNumBuffers);
349}
350
351////////////////////////////////////////////////////////////////////////////////
352/// Convert field value to string.
353
355{
356 const char *buf = PQgetvalue(fStmt->fRes, fIterationCount, npar);
357 return buf;
358}
359
360////////////////////////////////////////////////////////////////////////////////
361/// Convert field to numeric.
362
364{
365 if (PQgetisnull(fStmt->fRes,fIterationCount,npar))
366 return (long double)0;
367
368 return (long double) atof(PQgetvalue(fStmt->fRes,fIterationCount,npar));
369}
370
371////////////////////////////////////////////////////////////////////////////////
372/// Checks if field value is null.
373
375{
376 CheckGetField("IsNull", kTRUE);
377
378 return PQgetisnull(fStmt->fRes,fIterationCount,npar);
379}
380
381////////////////////////////////////////////////////////////////////////////////
382/// Get integer.
383
385{
386 if (PQgetisnull(fStmt->fRes,fIterationCount,npar))
387 return (Int_t)0;
388
389 return (Int_t) atoi(PQgetvalue(fStmt->fRes,fIterationCount,npar));
390}
391
392////////////////////////////////////////////////////////////////////////////////
393/// Get unsigned integer.
394
396{
397 if (PQgetisnull(fStmt->fRes,fIterationCount,npar))
398 return (UInt_t)0;
399
400 return (UInt_t) atoi(PQgetvalue(fStmt->fRes,fIterationCount,npar));
401}
402
403////////////////////////////////////////////////////////////////////////////////
404/// Get long.
405
407{
408 if (PQgetisnull(fStmt->fRes,fIterationCount,npar))
409 return (Long_t)0;
410
411 return (Long_t) atol(PQgetvalue(fStmt->fRes,fIterationCount,npar));
412}
413
414////////////////////////////////////////////////////////////////////////////////
415/// Get long64.
416
418{
419 if (PQgetisnull(fStmt->fRes,fIterationCount,npar))
420 return (Long64_t)0;
421
422#ifndef R__WIN32
423 return (Long64_t) atoll(PQgetvalue(fStmt->fRes,fIterationCount,npar));
424#else
425 return (Long64_t) _atoi64(PQgetvalue(fStmt->fRes,fIterationCount,npar));
426#endif
427}
428
429////////////////////////////////////////////////////////////////////////////////
430/// Return field value as unsigned 64-bit integer
431
433{
434 if (PQgetisnull(fStmt->fRes,fIterationCount,npar))
435 return (ULong64_t)0;
436
437#ifndef R__WIN32
438 return (ULong64_t) atoll(PQgetvalue(fStmt->fRes,fIterationCount,npar));
439#else
440 return (ULong64_t) _atoi64(PQgetvalue(fStmt->fRes,fIterationCount,npar));
441#endif
442}
443
444////////////////////////////////////////////////////////////////////////////////
445/// Return field value as double.
446
448{
449 if (PQgetisnull(fStmt->fRes,fIterationCount,npar))
450 return (Double_t)0;
451 return (Double_t) atof(PQgetvalue(fStmt->fRes,fIterationCount,npar));
452}
453
454////////////////////////////////////////////////////////////////////////////////
455/// Return field value as string.
456
457const char *TPgSQLStatement::GetString(Int_t npar)
458{
459 return PQgetvalue(fStmt->fRes,fIterationCount,npar);
460}
461
462////////////////////////////////////////////////////////////////////////////////
463/// Return field value as binary array.
464/// Note PQgetvalue mallocs/frees and ROOT classes expect new/delete.
465
466Bool_t TPgSQLStatement::GetBinary(Int_t npar, void* &mem, Long_t& size)
467{
468 size_t sz;
469 char *cptr = PQgetvalue(fStmt->fRes,fIterationCount,npar);
470 unsigned char * mptr = PQunescapeBytea((const unsigned char*)cptr,&sz);
471 if ((Long_t)sz>size) {
472 delete [] (unsigned char*) mem;
473 mem = (void*) new unsigned char[sz];
474 }
475 size=sz;
476 memcpy(mem,mptr,sz);
477 PQfreemem(mptr);
478 return kTRUE;
479}
480
481////////////////////////////////////////////////////////////////////////////////
482/// Return large object whose oid is in the given field.
483
484Bool_t TPgSQLStatement::GetLargeObject(Int_t npar, void* &mem, Long_t& size)
485{
486 Int_t objID = atoi(PQgetvalue(fStmt->fRes,fIterationCount,npar));
487
488 // All this needs to happen inside a transaction, or it will NOT work.
489 PGresult *res=PQexec(fStmt->fConn,"BEGIN");
490
491 CheckErrResult("GetLargeObject", res, kFALSE);
492 PQclear(res);
493
494 Int_t lObjFD = lo_open(fStmt->fConn, objID, INV_READ);
495
496 if (lObjFD<0) {
497 Error("GetLargeObject", "SQL Error on lo_open: %s", PQerrorMessage(fStmt->fConn));
498 RollBackTransaction("GetLargeObject");
499 return kFALSE;
500 }
501 // Object size is not known beforehand.
502 // Possible fast ways to get it are:
503 // (1) Create a function that does fopen, fseek, ftell on server
504 // (2) Query large object table with size()
505 // Both can not be expected to work in general,
506 // as (1) needs permissions and changes DB,
507 // and (2) needs permission.
508 // So we use
509 // (3) fopen, fseek and ftell locally.
510
511 lo_lseek(fStmt->fConn, lObjFD, 0, SEEK_END);
512 Long_t sz = lo_tell(fStmt->fConn, lObjFD);
513 lo_lseek(fStmt->fConn, lObjFD, 0, SEEK_SET);
514
515 if ((Long_t)sz>size) {
516 delete [] (unsigned char*) mem;
517 mem = (void*) new unsigned char[sz];
518 size=sz;
519 }
520
521 Int_t readBytes = lo_read(fStmt->fConn, lObjFD, (char*)mem, size);
522
523 if (readBytes != sz) {
524 Error("GetLargeObject", "SQL Error on lo_read: %s", PQerrorMessage(fStmt->fConn));
525 RollBackTransaction("GetLargeObject");
526 return kFALSE;
527 }
528
529 if (lo_close(fStmt->fConn, lObjFD) != 0) {
530 Error("GetLargeObject", "SQL Error on lo_close: %s", PQerrorMessage(fStmt->fConn));
531 RollBackTransaction("GetLargeObject");
532 return kFALSE;
533 }
534
535 res=PQexec(fStmt->fConn,"COMMIT");
536
537 ExecStatusType stat = PQresultStatus(res);
538 if (!pgsql_success(stat)) {
539 Error("GetLargeObject", "SQL Error on COMMIT: %s", PQerrorMessage(fStmt->fConn));
540 RollBackTransaction("GetLargeObject");
541 return kFALSE;
542 }
543 PQclear(res);
544
545 return kTRUE;
546}
547
548////////////////////////////////////////////////////////////////////////////////
549/// Return field value as date, in UTC.
550
551Bool_t TPgSQLStatement::GetDate(Int_t npar, Int_t& year, Int_t& month, Int_t& day)
552{
553 TString val=PQgetvalue(fStmt->fRes,fIterationCount,npar);
554 TDatime d = TDatime(val.Data());
555 year = d.GetYear();
556 month = d.GetMonth();
557 day= d.GetDay();
558 Int_t hour = d.GetHour();
559 Int_t min = d.GetMinute();
560 Int_t sec = d.GetSecond();
561 ConvertTimeToUTC(val, year, month, day, hour, min, sec);
562 return kTRUE;
563}
564
565////////////////////////////////////////////////////////////////////////////////
566/// Return field as time, in UTC.
567
568Bool_t TPgSQLStatement::GetTime(Int_t npar, Int_t& hour, Int_t& min, Int_t& sec)
569{
570 TString val=PQgetvalue(fStmt->fRes,fIterationCount,npar);
571 TDatime d = TDatime(val.Data());
572 hour = d.GetHour();
573 min = d.GetMinute();
574 sec= d.GetSecond();
575 Int_t year = d.GetYear();
576 Int_t month = d.GetMonth();
577 Int_t day = d.GetDay();
578 ConvertTimeToUTC(val, year, month, day, hour, min, sec);
579 return kTRUE;
580}
581
582////////////////////////////////////////////////////////////////////////////////
583/// Return field value as date & time, in UTC.
584
585Bool_t TPgSQLStatement::GetDatime(Int_t npar, Int_t& year, Int_t& month, Int_t& day, Int_t& hour, Int_t& min, Int_t& sec)
586{
587 TString val=PQgetvalue(fStmt->fRes,fIterationCount,npar);
588 TDatime d = TDatime(val.Data());
589 year = d.GetYear();
590 month = d.GetMonth();
591 day= d.GetDay();
592 hour = d.GetHour();
593 min = d.GetMinute();
594 sec= d.GetSecond();
595 ConvertTimeToUTC(val, year, month, day, hour, min, sec);
596 return kTRUE;
597}
598
599////////////////////////////////////////////////////////////////////////////////
600/// Convert timestamp value to UTC if a zone is included.
601
602void TPgSQLStatement::ConvertTimeToUTC(const TString &PQvalue, Int_t& year, Int_t& month, Int_t& day, Int_t& hour, Int_t& min, Int_t& sec)
603{
604 Ssiz_t p = PQvalue.Last(':');
605 // Check if timestamp has timezone
606 TSubString *s_zone = nullptr;
607 Bool_t hasZone = kFALSE;
608 Ssiz_t tzP = PQvalue.Last('+');
609 if ((tzP != kNPOS) && (tzP > p) ) {
610 s_zone = new TSubString(PQvalue(tzP+1,PQvalue.Length()-tzP));
611 hasZone=kTRUE;
612 } else {
613 Ssiz_t tzM = PQvalue.Last('-');
614 if ((tzM != kNPOS) && (tzM > p) ) {
615 s_zone = new TSubString(PQvalue(tzM+1,PQvalue.Length()-tzM));
616 hasZone = kTRUE;
617 }
618 }
619 if (hasZone == kTRUE) {
620 // Parse timezone, might look like e.g. +00 or -00:00
621 Int_t hourOffset, minuteOffset = 0;
622 Int_t conversions=sscanf(s_zone->Data(), "%2d:%2d", &hourOffset, &minuteOffset);
623 Int_t secondOffset = hourOffset*3600;
624 if (conversions>1) {
625 // Use sign from hour also for minute
626 secondOffset += (TMath::Sign(minuteOffset, hourOffset))*60;
627 }
628 // Use TTimeStamp so we do not have to take care of over-/underflows
629 TTimeStamp ts(year, month, day, hour, min, sec, 0, kTRUE, -secondOffset);
630 UInt_t uyear, umonth, uday, uhour, umin, usec;
631 ts.GetDate(kTRUE, 0, &uyear, &umonth, &uday);
632 ts.GetTime(kTRUE, 0, &uhour, &umin, &usec);
633 year=uyear;
634 month=umonth;
635 day=uday;
636 hour=uhour;
637 min=umin;
638 sec=usec;
639 delete s_zone;
640 }
641}
642
643////////////////////////////////////////////////////////////////////////////////
644/// Return field as timestamp, in UTC.
645/// Second fraction is to be interpreted as in the following example:
646/// 2013-01-12 12:10:23.093854+02
647/// Fraction is '93854', precision is fixed in this method to 6 decimal places.
648/// This means the returned frac-value is always in microseconds.
649
650Bool_t TPgSQLStatement::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)
651{
652 TString val=PQgetvalue(fStmt->fRes,fIterationCount,npar);
653 TDatime d(val.Data());
654 year = d.GetYear();
655 month = d.GetMonth();
656 day= d.GetDay();
657 hour = d.GetHour();
658 min = d.GetMinute();
659 sec= d.GetSecond();
660
661 ConvertTimeToUTC(val, year, month, day, hour, min, sec);
662
663 Ssiz_t p = val.Last('.');
664 TSubString s_frac = val(p,val.Length()-p+1);
665
666 // atoi ignores timezone part.
667 // We MUST use atof here to correctly convert the fraction of
668 // "12:23:01.093854" and put a limitation on precision,
669 // as we can only return an Int_t.
670 frac=(Int_t) (atof(s_frac.Data())*1.E6);
671
672 return kTRUE;
673}
674
675////////////////////////////////////////////////////////////////////////////////
676/// Return value of parameter in form of TTimeStamp
677/// Be aware, that TTimeStamp does not allow dates before 1970-01-01
678
680{
681 Int_t year, month, day, hour, min, sec, microsec;
682 GetTimestamp(npar, year, month, day, hour, min, sec, microsec);
683
684 if (year < 1970) {
685 SetError(-1, "Date before year 1970 does not supported by TTimeStamp type", "GetTimestamp");
686 return kFALSE;
687 }
688
689 tm.Set(year, month, day, hour, min, sec, microsec*1000, kTRUE, 0);
690
691 return kTRUE;
692}
693
694////////////////////////////////////////////////////////////////////////////////
695/// Set parameter type to be used as buffer.
696/// Also verifies parameter index and memory allocation
697
698Bool_t TPgSQLStatement::SetSQLParamType(Int_t npar, Bool_t isbinary, Int_t param_len, Int_t maxsize)
699{
700 if ((npar < 0) || (npar >= fNumBuffers)) return kFALSE;
701
702 if (maxsize < 0) {
703 if (fBind[npar]) delete [] fBind[npar];
704 fBind[npar] = nullptr;
705 } else if (maxsize > kBindStringSize) {
706 if (fBind[npar]) delete [] fBind[npar];
707 fBind[npar] = new char[maxsize];
708 } else if (!fBind[npar]) {
709 fBind[npar] = new char[kBindStringSize];
710 }
711 fParamFormats[npar] = isbinary ? 1 : 0;
712 fParamLengths[npar] = isbinary ? param_len : 0;
713
714 return kTRUE;
715}
716
717////////////////////////////////////////////////////////////////////////////////
718/// Set NULL as parameter value.
719
721{
722 if (!SetSQLParamType(npar, kFALSE, 0, -1)) return kFALSE;
723
724 return kTRUE;
725}
726
727////////////////////////////////////////////////////////////////////////////////
728/// Set parameter value as integer.
729
731{
732 if (!SetSQLParamType(npar)) return kFALSE;
733
734 snprintf(fBind[npar],kBindStringSize,"%d",value);
735
736 return kTRUE;
737}
738
739////////////////////////////////////////////////////////////////////////////////
740/// Set parameter value as unsinged integer.
741
743{
744 if (!SetSQLParamType(npar)) return kFALSE;
745
746 snprintf(fBind[npar],kBindStringSize,"%u",value);
747
748 return kTRUE;
749}
750
751////////////////////////////////////////////////////////////////////////////////
752/// Set parameter value as long.
753
755{
756 if (!SetSQLParamType(npar)) return kFALSE;
757
758 snprintf(fBind[npar],kBindStringSize,"%ld",value);
759
760 return kTRUE;
761}
762
763////////////////////////////////////////////////////////////////////////////////
764/// Set parameter value as 64-bit integer.
765
767{
768 if (!SetSQLParamType(npar)) return kFALSE;
769
770 snprintf(fBind[npar],kBindStringSize,"%lld",(Long64_t)value);
771
772 return kTRUE;
773}
774
775////////////////////////////////////////////////////////////////////////////////
776/// Set parameter value as unsinged 64-bit integer.
777
779{
780 if (!SetSQLParamType(npar)) return kFALSE;
781
782 snprintf(fBind[npar],kBindStringSize,"%llu",(ULong64_t)value);
783
784 return kTRUE;
785}
786
787////////////////////////////////////////////////////////////////////////////////
788/// Set parameter value as double value.
789
791{
792 if (!SetSQLParamType(npar)) return kFALSE;
793
794 snprintf(fBind[npar],kBindStringSize,"%lf",value);
795
796 return kTRUE;
797}
798
799////////////////////////////////////////////////////////////////////////////////
800/// Set parameter value as string.
801
802Bool_t TPgSQLStatement::SetString(Int_t npar, const char* value, Int_t maxsize)
803{
804 if (!SetSQLParamType(npar, kFALSE, 0, maxsize)) return kFALSE;
805
806 strlcpy(fBind[npar], value, maxsize);
807
808 return kTRUE;
809}
810
811////////////////////////////////////////////////////////////////////////////////
812/// Set parameter value as binary data.
813
814Bool_t TPgSQLStatement::SetBinary(Int_t npar, void* mem, Long_t size, Long_t maxsize)
815{
816 if (size > maxsize) maxsize = size;
817
818 if (!SetSQLParamType(npar, kTRUE, size, maxsize)) return kFALSE;
819
820 memcpy(fBind[npar], mem, size);
821
822 return kTRUE;
823}
824
825////////////////////////////////////////////////////////////////////////////////
826/// Set parameter value to large object and immediately insert the large object into DB.
827
828Bool_t TPgSQLStatement::SetLargeObject(Int_t npar, void* mem, Long_t size, Long_t /*maxsize*/)
829{
830 // All this needs to happen inside a transaction, or it will NOT work.
831 PGresult *res=PQexec(fStmt->fConn,"BEGIN");
832
833 CheckErrResult("GetLargeObject", res, kFALSE);
834 PQclear(res);
835
836 Int_t lObjID = lo_creat(fStmt->fConn, INV_READ | INV_WRITE);
837 if (lObjID<0) {
838 Error("SetLargeObject", "Error in SetLargeObject: %s", PQerrorMessage(fStmt->fConn));
839 RollBackTransaction("GetLargeObject");
840 return kFALSE;
841 }
842
843 Int_t lObjFD = lo_open(fStmt->fConn, lObjID, INV_READ | INV_WRITE);
844 if (lObjFD<0) {
845 Error("SetLargeObject", "Error in SetLargeObject: %s", PQerrorMessage(fStmt->fConn));
846 RollBackTransaction("GetLargeObject");
847 return kFALSE;
848 }
849
850 Int_t writtenBytes = lo_write(fStmt->fConn, lObjFD, (char*)mem, size);
851
852 if (writtenBytes != size) {
853 Error("SetLargeObject", "SQL Error on lo_write: %s", PQerrorMessage(fStmt->fConn));
854 RollBackTransaction("GetLargeObject");
855 return kFALSE;
856 }
857
858 if (lo_close(fStmt->fConn, lObjFD) != 0) {
859 Error("SetLargeObject", "SQL Error on lo_close: %s", PQerrorMessage(fStmt->fConn));
860 RollBackTransaction("GetLargeObject");
861 return kFALSE;
862 }
863
864 res=PQexec(fStmt->fConn,"COMMIT");
865 ExecStatusType stat = PQresultStatus(res);
866 if (!pgsql_success(stat)) {
867 Error("SetLargeObject", "SQL Error on COMMIT: %s", PQerrorMessage(fStmt->fConn));
868 PQclear(res);
869 return kFALSE;
870 }
871 PQclear(res);
872
873 snprintf(fBind[npar],kBindStringSize,"%d",lObjID);
874
875 return kTRUE;
876}
877
878////////////////////////////////////////////////////////////////////////////////
879/// Set parameter value as date.
880
882{
883 if (!SetSQLParamType(npar)) return kFALSE;
884
885 TDatime d(year,month,day,0,0,0);
886 snprintf(fBind[npar],kBindStringSize,"%s",(char*)d.AsSQLString());
887
888 return kTRUE;
889}
890
891////////////////////////////////////////////////////////////////////////////////
892/// Set parameter value as time.
893
895{
896 if (!SetSQLParamType(npar)) return kFALSE;
897
898 TDatime d(2000,1,1,hour,min,sec);
899 snprintf(fBind[npar],kBindStringSize,"%s",(char*)d.AsSQLString());
900 return kTRUE;
901}
902
903////////////////////////////////////////////////////////////////////////////////
904/// Set parameter value as date & time, in UTC.
905
906Bool_t TPgSQLStatement::SetDatime(Int_t npar, Int_t year, Int_t month, Int_t day, Int_t hour, Int_t min, Int_t sec)
907{
908 if (!SetSQLParamType(npar)) return kFALSE;
909
910 TDatime d(year,month,day,hour,min,sec);
911 snprintf(fBind[npar],kBindStringSize,"%s+00",(char*)d.AsSQLString());
912 return kTRUE;
913}
914
915////////////////////////////////////////////////////////////////////////////////
916/// Set parameter value as timestamp, in UTC.
917/// Second fraction is assumed as value in microseconds,
918/// i.e. as a fraction with six decimal places.
919/// See GetTimestamp() for an example.
920
921Bool_t TPgSQLStatement::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)
922{
923 if (!SetSQLParamType(npar)) return kFALSE;
924
925 TDatime d(year,month,day,hour,min,sec);
926 snprintf(fBind[npar],kBindStringSize,"%s.%06d+00",(char*)d.AsSQLString(),frac);
927 return kTRUE;
928}
929
930////////////////////////////////////////////////////////////////////////////////
931/// Set parameter value as timestamp from TTimeStamp object
932
934{
935 if (!SetSQLParamType(npar)) return kFALSE;
936
937 snprintf(fBind[npar], kBindStringSize, "%s.%06d+00", (char*)tm.AsString("s"), TMath::Nint(tm.GetNanoSec() / 1000.0));
938 return kTRUE;
939}
940
941#else
942
943////////////////////////////////////////////////////////////////////////////////
944/// Normal constructor.
945/// For PgSQL version < 8.2 no statement is supported.
946
948{
949}
950
951////////////////////////////////////////////////////////////////////////////////
952/// Destructor.
953
955{
956}
957
958////////////////////////////////////////////////////////////////////////////////
959/// Close statement.
960
962{
963}
964
965////////////////////////////////////////////////////////////////////////////////
966/// Process statement.
967
969{
970 return kFALSE;
971}
972
973////////////////////////////////////////////////////////////////////////////////
974/// Return number of affected rows after statement is processed.
975
977{
978 return 0;
979}
980
981////////////////////////////////////////////////////////////////////////////////
982/// Return number of statement parameters.
983
985{
986 return 0;
987}
988
989////////////////////////////////////////////////////////////////////////////////
990/// Store result of statement processing to access them
991/// via GetInt(), GetDouble() and so on methods.
992
994{
995 return kFALSE;
996}
997
998////////////////////////////////////////////////////////////////////////////////
999/// Return number of fields in result set.
1000
1002{
1003 return 0;
1004}
1005
1006////////////////////////////////////////////////////////////////////////////////
1007/// Returns field name in result set.
1008
1010{
1011 return 0;
1012}
1013
1014////////////////////////////////////////////////////////////////////////////////
1015/// Shift cursor to nect row in result set.
1016
1018{
1019 return kFALSE;
1020}
1021
1022
1023////////////////////////////////////////////////////////////////////////////////
1024/// Increment iteration counter for statement, where parameter can be set.
1025/// Statement with parameters of previous iteration
1026/// automatically will be applied to database.
1027
1029{
1030 return kFALSE;
1031}
1032
1033////////////////////////////////////////////////////////////////////////////////
1034/// Release all buffers, used by statement.
1035
1037{
1038}
1039
1040////////////////////////////////////////////////////////////////////////////////
1041/// Allocate buffers for statement parameters/ result fields.
1042
1044{
1045}
1046
1047////////////////////////////////////////////////////////////////////////////////
1048/// Convert field value to string.
1049
1051{
1052 return 0;
1053}
1054
1055////////////////////////////////////////////////////////////////////////////////
1056/// Convert field to numeric value.
1057
1059{
1060 return 0;
1061}
1062
1063////////////////////////////////////////////////////////////////////////////////
1064/// Checks if field value is null.
1065
1067{
1068 return kTRUE;
1069}
1070
1071////////////////////////////////////////////////////////////////////////////////
1072/// Return field value as integer.
1073
1075{
1076 return 0;
1077}
1078
1079////////////////////////////////////////////////////////////////////////////////
1080/// Return field value as unsigned integer.
1081
1083{
1084 return 0;
1085}
1086
1087////////////////////////////////////////////////////////////////////////////////
1088/// Return field value as long integer.
1089
1091{
1092 return 0;
1093}
1094
1095////////////////////////////////////////////////////////////////////////////////
1096/// Return field value as 64-bit integer.
1097
1099{
1100 return 0;
1101}
1102
1103////////////////////////////////////////////////////////////////////////////////
1104/// Return field value as unsigned 64-bit integer.
1105
1107{
1108 return 0;
1109}
1110
1111////////////////////////////////////////////////////////////////////////////////
1112/// Return field value as double.
1113
1115{
1116 return 0.;
1117}
1118
1119////////////////////////////////////////////////////////////////////////////////
1120/// Return field value as string.
1121
1123{
1124 return 0;
1125}
1126
1127////////////////////////////////////////////////////////////////////////////////
1128/// Return field value as binary array.
1129
1131{
1132 return kFALSE;
1133}
1134
1135////////////////////////////////////////////////////////////////////////////////
1136/// Return large object whose oid is in the given field.
1137
1139{
1140 return kFALSE;
1141}
1142
1143////////////////////////////////////////////////////////////////////////////////
1144/// Return field value as date.
1145
1147{
1148 return kFALSE;
1149}
1150
1151////////////////////////////////////////////////////////////////////////////////
1152/// Return field value as time.
1153
1155{
1156 return kFALSE;
1157}
1158
1159////////////////////////////////////////////////////////////////////////////////
1160/// Return field value as date & time.
1161
1163{
1164 return kFALSE;
1165}
1166
1167////////////////////////////////////////////////////////////////////////////////
1168/// Return field value as time stamp.
1169
1171{
1172 return kFALSE;
1173}
1174
1175////////////////////////////////////////////////////////////////////////////////
1176/// Return value of parameter in form of TTimeStamp
1177/// Be aware, that TTimeStamp does not allow dates before 1970-01-01
1178
1180{
1181 return kFALSE;
1182}
1183
1184////////////////////////////////////////////////////////////////////////////////
1185/// Set parameter type to be used as buffer.
1186
1188{
1189 return kFALSE;
1190}
1191
1192////////////////////////////////////////////////////////////////////////////////
1193/// Set NULL as parameter value.
1194
1196{
1197 return kFALSE;
1198}
1199
1200////////////////////////////////////////////////////////////////////////////////
1201/// Set parameter value as integer.
1202
1204{
1205 return kFALSE;
1206}
1207
1208////////////////////////////////////////////////////////////////////////////////
1209/// Set parameter value as unsigned integer.
1210
1212{
1213 return kFALSE;
1214}
1215
1216////////////////////////////////////////////////////////////////////////////////
1217/// Set parameter value as long integer.
1218
1220{
1221 return kFALSE;
1222}
1223
1224////////////////////////////////////////////////////////////////////////////////
1225/// Set parameter value as 64-bit integer.
1226
1228{
1229 return kFALSE;
1230}
1231
1232////////////////////////////////////////////////////////////////////////////////
1233/// Set parameter value as unsigned 64-bit integer.
1234
1236{
1237 return kFALSE;
1238}
1239
1240////////////////////////////////////////////////////////////////////////////////
1241/// Set parameter value as double.
1242
1244{
1245 return kFALSE;
1246}
1247
1248////////////////////////////////////////////////////////////////////////////////
1249/// Set parameter value as string.
1250
1252{
1253 return kFALSE;
1254}
1255
1256////////////////////////////////////////////////////////////////////////////////
1257/// Set parameter value as binary data.
1258
1260{
1261 return kFALSE;
1262}
1263
1264////////////////////////////////////////////////////////////////////////////////
1265/// Set parameter value to large object and immediately insert the large object into DB.
1266
1268{
1269 return kFALSE;
1270}
1271
1272////////////////////////////////////////////////////////////////////////////////
1273/// Set parameter value as date.
1274
1276{
1277 return kFALSE;
1278}
1279
1280////////////////////////////////////////////////////////////////////////////////
1281/// Set parameter value as time.
1282
1284{
1285 return kFALSE;
1286}
1287
1288////////////////////////////////////////////////////////////////////////////////
1289/// Set parameter value as date & time.
1290
1292{
1293 return kFALSE;
1294}
1295
1296////////////////////////////////////////////////////////////////////////////////
1297/// Set parameter value as timestamp.
1298
1300{
1301 return kFALSE;
1302}
1303
1304////////////////////////////////////////////////////////////////////////////////
1305/// Set parameter value as timestamp from TTimeStamp object
1306
1308{
1309 return kFALSE;
1310}
1311
1312#endif //PG_VERSION_NUM
#define d(i)
Definition: RSha256.hxx:102
const Ssiz_t kNPOS
Definition: RtypesCore.h:113
int Int_t
Definition: RtypesCore.h:43
int Ssiz_t
Definition: RtypesCore.h:65
unsigned int UInt_t
Definition: RtypesCore.h:44
const Bool_t kFALSE
Definition: RtypesCore.h:90
long Long_t
Definition: RtypesCore.h:52
bool Bool_t
Definition: RtypesCore.h:61
double Double_t
Definition: RtypesCore.h:57
long long Long64_t
Definition: RtypesCore.h:71
unsigned long long ULong64_t
Definition: RtypesCore.h:72
const Bool_t kTRUE
Definition: RtypesCore.h:89
const char Option_t
Definition: RtypesCore.h:64
#define ClassImp(name)
Definition: Rtypes.h:361
#define CheckErrNo(method, force, res)
#define CheckGetField(method, defres)
#define pgsql_success(x)
#define CheckStmt(method, res)
#define snprintf
Definition: civetweb.c:1540
This class stores the date and time with a precision of one second in an unsigned 32 bit word (950130...
Definition: TDatime.h:37
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:891
PgSQL_Stmt_t * fStmt
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.
void ConvertTimeToUTC(const TString &PQvalue, Int_t &year, Int_t &month, Int_t &day, Int_t &hour, Int_t &min, Int_t &sec)
void SetBuffersNumber(Int_t n)
Allocate buffers for statement parameters/ result fields.
Int_t fNumResultRows
data type (OID)
UInt_t GetUInt(Int_t npar) final
Return field value as unsigned integer.
Bool_t SetTime(Int_t npar, Int_t hour, Int_t min, Int_t sec) final
Set parameter value as time.
long double ConvertToNumeric(Int_t npar)
Convert field to numeric value.
Bool_t GetTime(Int_t npar, Int_t &hour, Int_t &min, Int_t &sec) final
Return field value as time.
Bool_t SetLargeObject(Int_t npar, void *mem, Long_t size, Long_t maxsize=0x1000) final
Set parameter value to large object and immediately insert the large object into DB.
Bool_t IsResultSetMode() const
TPgSQLStatement(PgSQL_Stmt_t *stmt, Bool_t errout=kTRUE)
Normal constructor.
int * fParamLengths
number of iteration
Bool_t GetDate(Int_t npar, Int_t &year, Int_t &month, Int_t &day) final
Return field value as date.
Int_t GetInt(Int_t npar) final
Return field value as integer.
Int_t GetNumParameters() final
Return number of statement parameters.
const char * GetString(Int_t npar) final
Return field value as string.
Bool_t SetDate(Int_t npar, Int_t year, Int_t month, Int_t day) final
Set parameter value as date.
Bool_t GetLargeObject(Int_t npar, void *&mem, Long_t &size) final
Return large object whose oid is in the given field.
Bool_t SetInt(Int_t npar, Int_t value) final
Set parameter value as integer.
ULong64_t GetULong64(Int_t npar) final
Return field value as unsigned 64-bit integer.
Long_t GetLong(Int_t npar) final
Return field value as long integer.
Bool_t SetSQLParamType(Int_t npar, Bool_t isbinary=kFALSE, Int_t param_len=0, Int_t maxsize=0)
Set parameter type to be used as buffer.
Int_t fIterationCount
1 - setting parameters, 2 - retrieving results
Int_t fNumBuffers
executed statement
Int_t fWorkingMode
array of column names
Bool_t GetBinary(Int_t npar, void *&mem, Long_t &size) final
Return field value as binary array.
Bool_t IsSetParsMode() const
Bool_t IsNull(Int_t npar) final
Checks if field value is null.
Int_t GetNumFields() final
Return number of fields in result set.
Double_t GetDouble(Int_t npar) final
Return field value as double.
Bool_t SetDouble(Int_t npar, Double_t value) final
Set parameter value as double.
Bool_t NextResultRow() final
Shift cursor to nect row in result set.
Long64_t GetLong64(Int_t npar) final
Return field value as 64-bit integer.
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.
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.
Int_t GetNumAffectedRows() final
Return number of affected rows after statement is processed.
Bool_t SetLong(Int_t npar, Long_t value) final
Set parameter value as long integer.
Bool_t StoreResult() final
Store result of statement processing to access them via GetInt(), GetDouble() and so on methods.
Bool_t SetUInt(Int_t npar, UInt_t value) final
Set parameter value as unsigned integer.
const char * GetFieldName(Int_t nfield) final
Returns field name in result set.
Bool_t SetNull(Int_t npar) final
Set NULL as parameter value.
const char * ConvertToString(Int_t npar)
Convert field value to string.
Bool_t SetULong64(Int_t npar, ULong64_t value) final
Set parameter value as unsigned 64-bit integer.
char ** fBind
number of statement parameters
void FreeBuffers()
Release all buffers, used by statement.
Bool_t SetLong64(Int_t npar, Long64_t value) final
Set parameter value as 64-bit integer.
virtual ~TPgSQLStatement()
Destructor.
Bool_t SetString(Int_t npar, const char *value, Int_t maxsize=256) final
Set parameter value as string.
Bool_t SetBinary(Int_t npar, void *mem, Long_t size, Long_t maxsize=0x1000) final
Set parameter value as binary data.
Bool_t Process() final
Process statement.
int * fParamFormats
length of column
char ** fFieldName
array of data for input
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 value as time stamp.
Bool_t NextIteration() final
Increment iteration counter for statement, where parameter can be set.
void Close(Option_t *="") final
Close statement.
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
Basic string class.
Definition: TString.h:131
Ssiz_t Length() const
Definition: TString.h:405
const char * Data() const
Definition: TString.h:364
Ssiz_t Last(char c) const
Find last occurrence of a character c.
Definition: TString.cxx:892
A zero length substring is legal.
Definition: TString.h:77
const char * Data() const
Definition: TString.h:721
The TTimeStamp encapsulates seconds and ns since EPOCH.
Definition: TTimeStamp.h:71
void Set()
Set Date/Time to current time as reported by the system.
Definition: TTimeStamp.cxx:556
Int_t GetNanoSec() const
Definition: TTimeStamp.h:136
const char * AsString(const Option_t *option="") const
Return the date & time as a string.
Definition: TTimeStamp.cxx:271
Int_t Nint(T x)
Round to nearest integer. Rounds half integers to the nearest even integer.
Definition: TMath.h:703
T1 Sign(T1 a, T2 b)
Definition: TMathBase.h:165
PGconn * fConn
PGresult * fRes