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