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