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