Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TMySQLStatement.cxx
Go to the documentation of this file.
1// @(#)root/mysql:$Id$
2// Author: Sergey Linev 6/02/2006
3
4/*************************************************************************
5 * Copyright (C) 1995-2006, 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 MySQL //
15// //
16// See TSQLStatement class documentation for more details. //
17// //
18//////////////////////////////////////////////////////////////////////////
19
20#include "TMySQLStatement.h"
21#include "TMySQLServer.h"
22#include "TDataType.h"
23#include "TDatime.h"
24#include "snprintf.h"
25#include <cstdlib>
26
28
30
31#if MYSQL_VERSION_ID >= 40100
32
33////////////////////////////////////////////////////////////////////////////////
34/// Normal constructor.
35/// Checks if statement contains parameters tags.
36
38 TSQLStatement(errout),
39 fStmt(stmt)
40{
41 ULong_t paramcount = mysql_stmt_param_count(fStmt);
42
43 if (paramcount>0) {
44 fWorkingMode = 1;
45 SetBuffersNumber(paramcount);
46 fNeedParBind = kTRUE;
47 fIterationCount = -1;
48 }
49}
50
51////////////////////////////////////////////////////////////////////////////////
52/// Destructor.
53
55{
56 Close();
57}
58
59////////////////////////////////////////////////////////////////////////////////
60/// Close statement.
61
63{
64 if (fStmt)
65 mysql_stmt_close(fStmt);
66
67 fStmt = nullptr;
68
70}
71
72
73// Reset error and check that statement exists
74#define CheckStmt(method, res) \
75 { \
76 ClearError(); \
77 if (fStmt==0) { \
78 SetError(-1,"Statement handle is 0",method); \
79 return res; \
80 } \
81 }
82
83// check last mysql statement error code
84#define CheckErrNo(method, force, res) \
85 { \
86 unsigned int stmterrno = mysql_stmt_errno(fStmt); \
87 if ((stmterrno!=0) || force) { \
88 const char* stmterrmsg = mysql_stmt_error(fStmt); \
89 if (stmterrno==0) { stmterrno = 11111; stmterrmsg = "MySQL statement error"; } \
90 SetError(stmterrno, stmterrmsg, method); \
91 return res; \
92 } \
93 }
94
95
96// check last mysql statement error code
97#define CheckGetField(method, res) \
98 { \
99 ClearError(); \
100 if (!IsResultSetMode()) { \
101 SetError(-1,"Cannot get statement parameters",method); \
102 return res; \
103 } \
104 if ((npar<0) || (npar>=fNumBuffers)) { \
105 SetError(-1,Form("Invalid parameter number %d", npar),method); \
106 return res; \
107 } \
108 }
109
110////////////////////////////////////////////////////////////////////////////////
111/// Process statement.
112
114{
115 CheckStmt("Process",kFALSE);
116
117 // if parameters was set, processing just means of closing parameters and variables
118 if (IsSetParsMode()) {
119 if (fIterationCount>=0)
120 if (!NextIteration()) return kFALSE;
121 fWorkingMode = 0;
122 fIterationCount = -1;
123 FreeBuffers();
124 return kTRUE;
125 }
126
127 if (mysql_stmt_execute(fStmt))
128 CheckErrNo("Process",kTRUE, kFALSE);
129
130 return kTRUE;
131}
132
133////////////////////////////////////////////////////////////////////////////////
134/// Return number of affected rows after statement is processed.
135
137{
138 CheckStmt("Process", -1);
139
140 my_ulonglong res = mysql_stmt_affected_rows(fStmt);
141
142 if (res == (my_ulonglong) -1)
143 CheckErrNo("GetNumAffectedRows", kTRUE, -1);
144
145 return (Int_t) res;
146}
147
148////////////////////////////////////////////////////////////////////////////////
149/// Return number of statement parameters.
150
152{
153 CheckStmt("GetNumParameters", -1);
154
155 Int_t res = mysql_stmt_param_count(fStmt);
156
157 CheckErrNo("GetNumParameters", kFALSE, -1);
158
159 return res;
160}
161
162////////////////////////////////////////////////////////////////////////////////
163/// Store result of statement processing to access them
164/// via GetInt(), GetDouble() and so on methods.
165
167{
168 CheckStmt("StoreResult", kFALSE);
169 if (fWorkingMode!=0) {
170 SetError(-1,"Cannot store result for that statement","StoreResult");
171 return kFALSE;
172 }
173
174 if (mysql_stmt_store_result(fStmt))
175 CheckErrNo("StoreResult",kTRUE, kFALSE);
176
177 // allocate memeory for data reading from query
178 MYSQL_RES* meta = mysql_stmt_result_metadata(fStmt);
179 if (meta) {
180 int count = mysql_num_fields(meta);
181
182 SetBuffersNumber(count);
183
184 MYSQL_FIELD *fields = mysql_fetch_fields(meta);
185
186 for (int n=0;n<count;n++) {
187 SetSQLParamType(n, fields[n].type, (fields[n].flags & UNSIGNED_FLAG) == 0, fields[n].length);
188 if (fields[n].name)
189 fBuffer[n].fFieldName = fields[n].name;
190 }
191
192 mysql_free_result(meta);
193 }
194
195 if (!fBind) return kFALSE;
196
197 /* Bind the buffers */
198 if (mysql_stmt_bind_result(fStmt, fBind))
199 CheckErrNo("StoreResult",kTRUE, kFALSE);
200
201 fWorkingMode = 2;
202
203 return kTRUE;
204}
205
206////////////////////////////////////////////////////////////////////////////////
207/// Return number of fields in result set.
208
210{
211 return IsResultSetMode() ? fNumBuffers : -1;
212}
213
214////////////////////////////////////////////////////////////////////////////////
215/// Returns field name in result set.
216
217const char* TMySQLStatement::GetFieldName(Int_t nfield)
218{
219 if (!IsResultSetMode() || (nfield<0) || (nfield>=fNumBuffers)) return nullptr;
220
221 return fBuffer[nfield].fFieldName.empty() ? nullptr : fBuffer[nfield].fFieldName.c_str();
222}
223
224////////////////////////////////////////////////////////////////////////////////
225/// Shift cursor to nect row in result set.
226
228{
229 if ((fStmt==0) || !IsResultSetMode()) return kFALSE;
230
231 Bool_t res = !mysql_stmt_fetch(fStmt);
232
233 if (!res) {
234 fWorkingMode = 0;
235 FreeBuffers();
236 }
237
238 return res;
239}
240
241////////////////////////////////////////////////////////////////////////////////
242/// Increment iteration counter for statement, where parameter can be set.
243/// Statement with parameters of previous iteration
244/// automatically will be applied to database.
245
247{
248 ClearError();
249
250 if (!IsSetParsMode() || (fBind==0)) {
251 SetError(-1,"Cannot call for that statement","NextIteration");
252 return kFALSE;
253 }
254
256
257 if (fIterationCount==0) return kTRUE;
258
259 if (fNeedParBind) {
261 if (mysql_stmt_bind_param(fStmt, fBind))
262 CheckErrNo("NextIteration",kTRUE, kFALSE);
263 }
264
265 if (mysql_stmt_execute(fStmt))
266 CheckErrNo("NextIteration", kTRUE, kFALSE);
267
268 return kTRUE;
269}
270
271////////////////////////////////////////////////////////////////////////////////
272/// Release all buffers, used by statement.
273
275{
276 if (fBuffer) {
277 for (Int_t n=0; n<fNumBuffers;n++) {
278 free(fBuffer[n].fMem);
279 }
280 delete[] fBuffer;
281 }
282
283 if (fBind)
284 delete[] fBind;
285
286 fBuffer = nullptr;
287 fBind = nullptr;
288 fNumBuffers = 0;
289}
290
291////////////////////////////////////////////////////////////////////////////////
292/// Allocate buffers for statement parameters/ result fields.
293
295{
296 FreeBuffers();
297 if (numpars<=0) return;
298
299 fNumBuffers = numpars;
300
302 memset(fBind, 0, sizeof(MYSQL_BIND)*fNumBuffers);
303
304 fBuffer = new TParamData[fNumBuffers];
305 for (int n=0;n<fNumBuffers;++n) {
306 fBuffer[n].fMem = nullptr;
307 fBuffer[n].fSize = 0;
308 fBuffer[n].fSqlType = 0;
310 fBuffer[n].fResLength = 0;
311 fBuffer[n].fResNull = false;
312 fBuffer[n].fStrBuffer.clear();
313 fBuffer[n].fFieldName.clear();
314 }
315}
316
317////////////////////////////////////////////////////////////////////////////////
318/// Convert field value to string.
319
321{
322 if (fBuffer[npar].fResNull)
323 return nullptr;
324
325 void *addr = fBuffer[npar].fMem;
326 Bool_t sig = fBuffer[npar].fSign;
327
328 if (!addr)
329 return nullptr;
330
331 if ((fBind[npar].buffer_type==MYSQL_TYPE_STRING) ||
332 (fBind[npar].buffer_type==MYSQL_TYPE_VAR_STRING))
333 return (const char *) addr;
334
335 constexpr int kSize = 100;
336 char buf[kSize];
337 int len = 0;
338
339 switch(fBind[npar].buffer_type) {
340 case MYSQL_TYPE_LONG:
341 if (sig) len = snprintf(buf, kSize, "%d",*((int*) addr));
342 else len = snprintf(buf, kSize, "%u",*((unsigned int*) addr));
343 break;
344 case MYSQL_TYPE_LONGLONG:
345 if (sig) len = snprintf(buf, kSize, "%lld",*((Long64_t*) addr)); else
346 len = snprintf(buf, kSize, "%llu",*((ULong64_t*) addr));
347 break;
348 case MYSQL_TYPE_SHORT:
349 if (sig) len = snprintf(buf, kSize, "%hd",*((short*) addr)); else
350 len = snprintf(buf, kSize, "%hu",*((unsigned short*) addr));
351 break;
352 case MYSQL_TYPE_TINY:
353 if (sig) len = snprintf(buf, kSize, "%d",*((char*) addr)); else
354 len = snprintf(buf, kSize, "%u",*((unsigned char*) addr));
355 break;
356 case MYSQL_TYPE_FLOAT:
357 len = snprintf(buf, kSize, TSQLServer::GetFloatFormat(), *((float*) addr));
358 break;
359 case MYSQL_TYPE_DOUBLE:
360 len = snprintf(buf, kSize, TSQLServer::GetFloatFormat(), *((double*) addr));
361 break;
362 case MYSQL_TYPE_DATETIME:
363 case MYSQL_TYPE_TIMESTAMP: {
364 MYSQL_TIME* tm = (MYSQL_TIME*) addr;
365 len = snprintf(buf, kSize, "%4.4d-%2.2d-%2.2d %2.2d:%2.2d:%2.2d",
366 tm->year, tm->month, tm->day,
367 tm->hour, tm->minute, tm->second);
368 break;
369 }
370 case MYSQL_TYPE_TIME: {
371 MYSQL_TIME* tm = (MYSQL_TIME*) addr;
372 len = snprintf(buf, kSize, "%2.2d:%2.2d:%2.2d",
373 tm->hour, tm->minute, tm->second);
374 break;
375 }
376 case MYSQL_TYPE_DATE: {
377 MYSQL_TIME* tm = (MYSQL_TIME*) addr;
378 len = snprintf(buf, kSize, "%4.4d-%2.2d-%2.2d",
379 tm->year, tm->month, tm->day);
380 break;
381 }
382 default:
383 return nullptr;
384 }
385
386 if (len >= kSize)
387 SetError(-1, Form("Cannot convert param %d into string - buffer too small", npar));
388
389 fBuffer[npar].fStrBuffer = buf;
390
391 return fBuffer[npar].fStrBuffer.c_str();
392}
393
394////////////////////////////////////////////////////////////////////////////////
395/// Convert field to numeric value.
396
398{
399 if (fBuffer[npar].fResNull) return 0;
400
401 void* addr = fBuffer[npar].fMem;
402 Bool_t sig = fBuffer[npar].fSign;
403
404 if (addr==0) return 0;
405
406 switch(fBind[npar].buffer_type) {
407 case MYSQL_TYPE_LONG:
408 if (sig) return *((int*) addr); else
409 return *((unsigned int*) addr);
410 break;
411 case MYSQL_TYPE_LONGLONG:
412 if (sig) return *((Long64_t*) addr); else
413 return *((ULong64_t*) addr);
414 break;
415 case MYSQL_TYPE_SHORT:
416 if (sig) return *((short*) addr); else
417 return *((unsigned short*) addr);
418 break;
419 case MYSQL_TYPE_TINY:
420 if (sig) return *((char*) addr); else
421 return *((unsigned char*) addr);
422 break;
423 case MYSQL_TYPE_FLOAT:
424 return *((float*) addr);
425 break;
426 case MYSQL_TYPE_DOUBLE:
427 return *((double*) addr);
428 break;
429#if MYSQL_VERSION_ID >= 50022
430 case MYSQL_TYPE_NEWDECIMAL /* new MYSQL_TYPE fixed precision decimal */:
431#endif
432 case MYSQL_TYPE_STRING:
433 case MYSQL_TYPE_VAR_STRING:
434 case MYSQL_TYPE_BLOB: {
435 char* str = (char*) addr;
436 ULong_t len = fBuffer[npar].fResLength;
437 if ((str==0) || (*str==0) || (len==0)) return 0;
438 Int_t size = fBuffer[npar].fSize;
439 if (1.*len<size)
440 str[len] = 0;
441 else
442 str[size-1] = 0;
443 long double buf = 0;
444 sscanf(str,"%Lf",&buf);
445 return buf;
446 break;
447 }
448 case MYSQL_TYPE_DATETIME:
449 case MYSQL_TYPE_TIMESTAMP: {
450 MYSQL_TIME* tm = (MYSQL_TIME*) addr;
451 TDatime rtm(tm->year, tm->month, tm->day,
452 tm->hour, tm->minute, tm->second);
453 return rtm.Get();
454 break;
455 }
456 case MYSQL_TYPE_DATE: {
457 MYSQL_TIME* tm = (MYSQL_TIME*) addr;
458 TDatime rtm(tm->year, tm->month, tm->day, 0, 0, 0);
459 return rtm.GetDate();
460 break;
461 }
462 case MYSQL_TYPE_TIME: {
463 MYSQL_TIME* tm = (MYSQL_TIME*) addr;
464 TDatime rtm(2000, 1, 1, tm->hour, tm->minute, tm->second);
465 return rtm.GetTime();
466 break;
467 }
468
469 default:
470 return 0;
471 }
472}
473
474////////////////////////////////////////////////////////////////////////////////
475/// Checks if field value is null.
476
478{
479 CheckGetField("IsNull", kTRUE);
480
481 return fBuffer[npar].fResNull;
482}
483
484////////////////////////////////////////////////////////////////////////////////
485/// Return field value as integer.
486
488{
489 CheckGetField("GetInt", 0);
490
491 if ((fBuffer[npar].fSqlType==MYSQL_TYPE_LONG) && fBuffer[npar].fSign)
492 return (Int_t) *((int*) fBuffer[npar].fMem);
493
494 return (Int_t) ConvertToNumeric(npar);
495}
496
497////////////////////////////////////////////////////////////////////////////////
498/// Return field value as unsigned integer.
499
501{
502 CheckGetField("GetUInt", 0);
503
504 if ((fBuffer[npar].fSqlType==MYSQL_TYPE_LONG) && !fBuffer[npar].fSign)
505 return (UInt_t) *((unsigned int*) fBuffer[npar].fMem);
506
507 return (UInt_t) ConvertToNumeric(npar);
508}
509
510////////////////////////////////////////////////////////////////////////////////
511/// Return field value as long integer.
512
514{
515 CheckGetField("GetLong", 0);
516
517 if ((fBuffer[npar].fSqlType==MYSQL_TYPE_LONG) && fBuffer[npar].fSign)
518 return (Long_t) *((int*) fBuffer[npar].fMem);
519
520 return (Long_t) ConvertToNumeric(npar);
521}
522
523////////////////////////////////////////////////////////////////////////////////
524/// Return field value as 64-bit integer.
525
527{
528 CheckGetField("GetLong64", 0);
529
530 if ((fBuffer[npar].fSqlType==MYSQL_TYPE_LONGLONG) && fBuffer[npar].fSign)
531 return (Long64_t) *((Long64_t*) fBuffer[npar].fMem);
532
533 return (Long64_t) ConvertToNumeric(npar);
534}
535
536////////////////////////////////////////////////////////////////////////////////
537/// Return field value as unsigned 64-bit integer.
538
540{
541 CheckGetField("GetULong64", 0);
542
543 if ((fBuffer[npar].fSqlType==MYSQL_TYPE_LONGLONG) && !fBuffer[npar].fSign)
544 return (ULong64_t) *((ULong64_t*) fBuffer[npar].fMem);
545
546 return (ULong64_t) ConvertToNumeric(npar);
547}
548
549////////////////////////////////////////////////////////////////////////////////
550/// Return field value as double.
551
553{
554 CheckGetField("GetDouble", 0);
555
556 if (fBuffer[npar].fSqlType==MYSQL_TYPE_DOUBLE)
557 return (Double_t) *((double*) fBuffer[npar].fMem);
558
559 return (Double_t) ConvertToNumeric(npar);
560}
561
562////////////////////////////////////////////////////////////////////////////////
563/// Return field value as string.
564
565const char *TMySQLStatement::GetString(Int_t npar)
566{
567 CheckGetField("GetString", 0);
568
569 if ((fBind[npar].buffer_type==MYSQL_TYPE_STRING)
570 || (fBind[npar].buffer_type==MYSQL_TYPE_BLOB)
571 || (fBind[npar].buffer_type==MYSQL_TYPE_VAR_STRING)
572#if MYSQL_VERSION_ID >= 50022
573 || (fBuffer[npar].fSqlType==MYSQL_TYPE_NEWDECIMAL)
574#endif
575 ) {
576 if (fBuffer[npar].fResNull) return nullptr;
577 char *str = (char *) fBuffer[npar].fMem;
578 ULong_t len = fBuffer[npar].fResLength;
579 Int_t size = fBuffer[npar].fSize;
580 if (1.*len<size) str[len] = 0; else
581 str[size-1] = 0;
582 return str;
583 }
584
585 return ConvertToString(npar);
586}
587
588////////////////////////////////////////////////////////////////////////////////
589/// Return field value as binary array.
590
591Bool_t TMySQLStatement::GetBinary(Int_t npar, void* &mem, Long_t& size)
592{
593 mem = 0;
594 size = 0;
595
596 CheckGetField("GetBinary", kFALSE);
597
598 if ((fBind[npar].buffer_type==MYSQL_TYPE_STRING) ||
599 (fBind[npar].buffer_type==MYSQL_TYPE_VAR_STRING) ||
600 (fBind[npar].buffer_type==MYSQL_TYPE_BLOB) ||
601 (fBind[npar].buffer_type==MYSQL_TYPE_TINY_BLOB) ||
602 (fBind[npar].buffer_type==MYSQL_TYPE_MEDIUM_BLOB) ||
603 (fBind[npar].buffer_type==MYSQL_TYPE_LONG_BLOB)) {
604 if (fBuffer[npar].fResNull) return kTRUE;
605 mem = fBuffer[npar].fMem;
606 size = fBuffer[npar].fResLength;
607 return kTRUE;
608 }
609
610 return kFALSE;
611}
612
613////////////////////////////////////////////////////////////////////////////////
614/// Return field value as date.
615
616Bool_t TMySQLStatement::GetDate(Int_t npar, Int_t& year, Int_t& month, Int_t& day)
617{
618 CheckGetField("GetDate", kFALSE);
619
620 if (fBuffer[npar].fResNull) return kFALSE;
621
622 switch(fBind[npar].buffer_type) {
623 case MYSQL_TYPE_DATETIME:
624 case MYSQL_TYPE_TIMESTAMP:
625 case MYSQL_TYPE_DATE: {
626 MYSQL_TIME* tm = (MYSQL_TIME*) fBuffer[npar].fMem;
627 if (tm==0) return kFALSE;
628 year = tm->year;
629 month = tm->month;
630 day = tm->day;
631 break;
632 }
633 default:
634 return kFALSE;
635 }
636 return kTRUE;
637}
638
639////////////////////////////////////////////////////////////////////////////////
640/// Return field value as time.
641
642Bool_t TMySQLStatement::GetTime(Int_t npar, Int_t& hour, Int_t& min, Int_t& sec)
643{
644 CheckGetField("GetTime", kFALSE);
645
646 if (fBuffer[npar].fResNull) return kFALSE;
647
648 switch(fBind[npar].buffer_type) {
649 case MYSQL_TYPE_DATETIME:
650 case MYSQL_TYPE_TIMESTAMP:
651 case MYSQL_TYPE_TIME: {
652 MYSQL_TIME* tm = (MYSQL_TIME*) fBuffer[npar].fMem;
653 if (tm==0) return kFALSE;
654 hour = tm->hour;
655 min = tm->minute;
656 sec = tm->second;
657 break;
658 }
659 default:
660 return kFALSE;
661 }
662 return kTRUE;
663}
664
665////////////////////////////////////////////////////////////////////////////////
666/// Return field value as date & time.
667
668Bool_t TMySQLStatement::GetDatime(Int_t npar, Int_t& year, Int_t& month, Int_t& day, Int_t& hour, Int_t& min, Int_t& sec)
669{
670 CheckGetField("GetDatime", kFALSE);
671
672 if (fBuffer[npar].fResNull) return kFALSE;
673
674 switch(fBind[npar].buffer_type) {
675 case MYSQL_TYPE_DATETIME:
676 case MYSQL_TYPE_TIMESTAMP: {
677 MYSQL_TIME* tm = (MYSQL_TIME*) fBuffer[npar].fMem;
678 if (tm==0) return kFALSE;
679 year = tm->year;
680 month = tm->month;
681 day = tm->day;
682 hour = tm->hour;
683 min = tm->minute;
684 sec = tm->second;
685 break;
686 }
687 default:
688 return kFALSE;
689 }
690 return kTRUE;
691}
692
693////////////////////////////////////////////////////////////////////////////////
694/// Return field value as time stamp.
695
696Bool_t TMySQLStatement::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)
697{
698 CheckGetField("GetTimstamp", kFALSE);
699
700 if (fBuffer[npar].fResNull) return kFALSE;
701
702 switch(fBind[npar].buffer_type) {
703 case MYSQL_TYPE_DATETIME:
704 case MYSQL_TYPE_TIMESTAMP: {
705 MYSQL_TIME* tm = (MYSQL_TIME*) fBuffer[npar].fMem;
706 if (tm==0) return kFALSE;
707 year = tm->year;
708 month = tm->month;
709 day = tm->day;
710 hour = tm->hour;
711 min = tm->minute;
712 sec = tm->second;
713 frac = 0;
714 break;
715 }
716 default:
717 return kFALSE;
718 }
719 return kTRUE;
720}
721
722////////////////////////////////////////////////////////////////////////////////
723/// Set parameter type to be used as buffer.
724/// Used in both setting data to database and retrieving data from data base.
725/// Initialize proper MYSQL_BIND structure and allocate required buffers.
726
727Bool_t TMySQLStatement::SetSQLParamType(Int_t npar, int sqltype, Bool_t sig, ULong_t sqlsize)
728{
729 if ((npar<0) || (npar>=fNumBuffers)) return kFALSE;
730
731 fBuffer[npar].fMem = nullptr;
732 fBuffer[npar].fSize = 0;
733 fBuffer[npar].fResLength = 0;
734 fBuffer[npar].fResNull = false;
735 fBuffer[npar].fStrBuffer.clear();
736
737 ULong64_t allocsize = 0;
738
739 Bool_t doreset = false;
740
741 switch (sqltype) {
742 case MYSQL_TYPE_LONG: allocsize = sizeof(int); break;
743 case MYSQL_TYPE_LONGLONG: allocsize = sizeof(Long64_t); break;
744 case MYSQL_TYPE_SHORT: allocsize = sizeof(short); break;
745 case MYSQL_TYPE_TINY: allocsize = sizeof(char); break;
746 case MYSQL_TYPE_FLOAT: allocsize = sizeof(float); break;
747 case MYSQL_TYPE_DOUBLE: allocsize = sizeof(double); break;
748#if MYSQL_VERSION_ID >= 50022
749 case MYSQL_TYPE_NEWDECIMAL /* new MYSQL_TYPE fixed precision decimal */:
750#endif
751 case MYSQL_TYPE_STRING: allocsize = sqlsize > 256 ? sqlsize : 256; break;
752 case MYSQL_TYPE_VAR_STRING: allocsize = sqlsize > 256 ? sqlsize : 256; break;
753 case MYSQL_TYPE_MEDIUM_BLOB:
754 case MYSQL_TYPE_LONG_BLOB:
755 case MYSQL_TYPE_BLOB: allocsize = sqlsize >= 65525 ? sqlsize : 65535; break;
756 case MYSQL_TYPE_TINY_BLOB: allocsize = sqlsize > 255 ? sqlsize : 255; break;
757 case MYSQL_TYPE_TIME:
758 case MYSQL_TYPE_DATE:
759 case MYSQL_TYPE_TIMESTAMP:
760 case MYSQL_TYPE_DATETIME: allocsize = sizeof(MYSQL_TIME); doreset = true; break;
761 default: SetError(-1,"Nonsupported SQL type","SetSQLParamType"); return kFALSE;
762 }
763
764 if (allocsize > fgAllocSizeLimit) allocsize = fgAllocSizeLimit;
765
766 fBuffer[npar].fMem = malloc(allocsize);
767 fBuffer[npar].fSize = allocsize;
768 fBuffer[npar].fSqlType = sqltype;
769 fBuffer[npar].fSign = sig;
770
771 if ((allocsize>0) && fBuffer[npar].fMem && doreset)
772 memset(fBuffer[npar].fMem, 0, allocsize);
773
774 fBind[npar].buffer_type = enum_field_types(sqltype);
775 fBind[npar].buffer = fBuffer[npar].fMem;
776 fBind[npar].buffer_length = allocsize;
777 fBind[npar].is_null= &(fBuffer[npar].fResNull);
778 fBind[npar].length = &(fBuffer[npar].fResLength);
779 fBind[npar].is_unsigned = !sig;
780
781 return kTRUE;
782}
783
784////////////////////////////////////////////////////////////////////////////////
785/// Check boundary condition before setting value of parameter.
786/// Return address of parameter buffer.
787
788void *TMySQLStatement::BeforeSet(const char* method, Int_t npar, Int_t sqltype, Bool_t sig, ULong_t size)
789{
790 ClearError();
791
792 if (!IsSetParsMode()) {
793 SetError(-1,"Cannot set parameter for statement", method);
794 return 0;
795 }
796
797 if ((npar<0) || (npar>=fNumBuffers)) {
798 SetError(-1,Form("Invalid parameter number %d",npar), method);
799 return 0;
800 }
801
802 if ((fIterationCount==0) && (fBuffer[npar].fSqlType==0))
803 if (!SetSQLParamType(npar, sqltype, sig, size)) {
804 SetError(-1,"Cannot initialize parameter buffer", method);
805 return 0;
806 }
807
808 if ((fBuffer[npar].fSqlType!=sqltype) ||
809 (fBuffer[npar].fSign != sig)) return 0;
810
811 fBuffer[npar].fResNull = false;
812
813 return fBuffer[npar].fMem;
814}
815
816////////////////////////////////////////////////////////////////////////////////
817/// Set NULL as parameter value.
818/// If NULL should be set for statement parameter during first iteration,
819/// one should call before proper Set... method to identify type of argument for
820/// the future. For instance, if one suppose to have double as type of parameter,
821/// code should look like:
822/// stmt->SetDouble(2, 0.);
823/// stmt->SetNull(2);
824
826{
827 void* addr = BeforeSet("SetNull", npar, MYSQL_TYPE_LONG);
828
829 if (addr!=0)
830 *((int*) addr) = 0;
831
832 if ((npar>=0) && (npar<fNumBuffers))
833 fBuffer[npar].fResNull = true;
834
835 return kTRUE;
836}
837
838////////////////////////////////////////////////////////////////////////////////
839/// Set parameter value as integer.
840
842{
843 void* addr = BeforeSet("SetInt", npar, MYSQL_TYPE_LONG);
844
845 if (addr!=0)
846 *((int*) addr) = value;
847
848 return (addr!=0);
849}
850
851////////////////////////////////////////////////////////////////////////////////
852/// Set parameter value as unsigned integer.
853
855{
856 void* addr = BeforeSet("SetUInt", npar, MYSQL_TYPE_LONG, kFALSE);
857
858 if (addr!=0)
859 *((unsigned int*) addr) = value;
860
861 return (addr!=0);
862}
863
864////////////////////////////////////////////////////////////////////////////////
865/// Set parameter value as long integer.
866
868{
869 void* addr = BeforeSet("SetLong", npar, MYSQL_TYPE_LONG);
870
871 if (addr!=0)
872 *((int*) addr) = value;
873
874 return (addr!=0);
875}
876
877////////////////////////////////////////////////////////////////////////////////
878/// Set parameter value as 64-bit integer.
879
881{
882 void* addr = BeforeSet("SetLong64", npar, MYSQL_TYPE_LONGLONG);
883
884 if (addr!=0)
885 *((Long64_t*) addr) = value;
886
887 return (addr!=0);
888}
889
890////////////////////////////////////////////////////////////////////////////////
891/// Set parameter value as unsigned 64-bit integer.
892
894{
895 void* addr = BeforeSet("SetULong64", npar, MYSQL_TYPE_LONGLONG, kFALSE);
896
897 if (addr!=0)
898 *((ULong64_t*) addr) = value;
899
900 return (addr!=0);
901}
902
903////////////////////////////////////////////////////////////////////////////////
904/// Set parameter value as double.
905
907{
908 void* addr = BeforeSet("SetDouble", npar, MYSQL_TYPE_DOUBLE, kFALSE);
909
910 if (addr!=0)
911 *((double*) addr) = value;
912
913 return (addr!=0);
914}
915
916////////////////////////////////////////////////////////////////////////////////
917/// Set parameter value as string.
918
919Bool_t TMySQLStatement::SetString(Int_t npar, const char* value, Int_t maxsize)
920{
921 Int_t len = value ? strlen(value) : 0;
922
923 void* addr = BeforeSet("SetString", npar, MYSQL_TYPE_STRING, true, maxsize);
924
925 if (addr==0) return kFALSE;
926
927 if (len >= fBuffer[npar].fSize) {
928 free(fBuffer[npar].fMem);
929
930 fBuffer[npar].fMem = malloc(len+1);
931 fBuffer[npar].fSize = len + 1;
932
933 fBind[npar].buffer = fBuffer[npar].fMem;
934 fBind[npar].buffer_length = fBuffer[npar].fSize;
935
936 addr = fBuffer[npar].fMem;
938 }
939
940 if (value) strcpy((char*) addr, value);
941 else ((char*)addr)[0]='\0';
942
943 fBuffer[npar].fResLength = len;
944
945 return kTRUE;
946}
947
948////////////////////////////////////////////////////////////////////////////////
949/// Set parameter value as binary data.
950
951Bool_t TMySQLStatement::SetBinary(Int_t npar, void* mem, Long_t size, Long_t maxsize)
952{
953 if (size>=maxsize) maxsize = size + 1;
954
955 int bin_type = MYSQL_TYPE_BLOB;
956 if (maxsize > 65525) bin_type = MYSQL_TYPE_MEDIUM_BLOB;
957 if (maxsize > 16777205) bin_type = MYSQL_TYPE_LONG_BLOB;
958
959 void* addr = BeforeSet("SetBinary", npar, bin_type, true, maxsize);
960
961 if (addr==0) return kFALSE;
962
963 if (size >= fBuffer[npar].fSize) {
964 free(fBuffer[npar].fMem);
965
966 fBuffer[npar].fMem = malloc(size+1);
967 fBuffer[npar].fSize = size + 1;
968
969 fBind[npar].buffer = fBuffer[npar].fMem;
970 fBind[npar].buffer_length = fBuffer[npar].fSize;
971
972 addr = fBuffer[npar].fMem;
974 }
975
976 memcpy(addr, mem, size);
977
978 fBuffer[npar].fResLength = size;
979
980 return kTRUE;
981}
982
983////////////////////////////////////////////////////////////////////////////////
984/// Set parameter value as date.
985
987{
988 MYSQL_TIME* addr = (MYSQL_TIME*) BeforeSet("SetDate", npar, MYSQL_TYPE_DATE);
989
990 if (addr!=0) {
991 addr->year = year;
992 addr->month = month;
993 addr->day = day;
994 }
995
996 return (addr!=0);
997}
998
999////////////////////////////////////////////////////////////////////////////////
1000/// Set parameter value as time.
1001
1003{
1004 MYSQL_TIME* addr = (MYSQL_TIME*) BeforeSet("SetTime", npar, MYSQL_TYPE_TIME);
1005
1006 if (addr!=0) {
1007 addr->hour = hour;
1008 addr->minute = min;
1009 addr->second = sec;
1010 }
1011
1012 return (addr!=0);
1013}
1014
1015////////////////////////////////////////////////////////////////////////////////
1016/// Set parameter value as date & time.
1017
1018Bool_t TMySQLStatement::SetDatime(Int_t npar, Int_t year, Int_t month, Int_t day, Int_t hour, Int_t min, Int_t sec)
1019{
1020 MYSQL_TIME* addr = (MYSQL_TIME*) BeforeSet("SetDatime", npar, MYSQL_TYPE_DATETIME);
1021
1022 if (addr!=0) {
1023 addr->year = year;
1024 addr->month = month;
1025 addr->day = day;
1026 addr->hour = hour;
1027 addr->minute = min;
1028 addr->second = sec;
1029 }
1030
1031 return (addr!=0);
1032}
1033
1034////////////////////////////////////////////////////////////////////////////////
1035/// Set parameter value as timestamp.
1036
1037Bool_t TMySQLStatement::SetTimestamp(Int_t npar, Int_t year, Int_t month, Int_t day, Int_t hour, Int_t min, Int_t sec, Int_t)
1038{
1039 MYSQL_TIME* addr = (MYSQL_TIME*) BeforeSet("SetTimestamp", npar, MYSQL_TYPE_TIMESTAMP);
1040
1041 if (addr!=0) {
1042 addr->year = year;
1043 addr->month = month;
1044 addr->day = day;
1045 addr->hour = hour;
1046 addr->minute = min;
1047 addr->second = sec;
1048 }
1049
1050 return (addr!=0);
1051}
1052
1053#else
1054
1055////////////////////////////////////////////////////////////////////////////////
1056/// Normal constructor.
1057/// For MySQL version < 4.1 no statement is supported
1058
1060{
1061}
1062
1063////////////////////////////////////////////////////////////////////////////////
1064/// Destructor.
1065
1067{
1068}
1069
1070////////////////////////////////////////////////////////////////////////////////
1071/// Close statement
1072
1074{
1075}
1076
1077////////////////////////////////////////////////////////////////////////////////
1078/// Process statement.
1079
1081{
1082 return kFALSE;
1083}
1084
1085////////////////////////////////////////////////////////////////////////////////
1086/// Return number of affected rows after statement is processed.
1087
1089{
1090 return 0;
1091}
1092
1093////////////////////////////////////////////////////////////////////////////////
1094/// Return number of statement parameters.
1095
1097{
1098 return 0;
1099}
1100
1101////////////////////////////////////////////////////////////////////////////////
1102/// Store result of statement processing to access them
1103/// via GetInt(), GetDouble() and so on methods.
1104
1106{
1107 return kFALSE;
1108}
1109
1110////////////////////////////////////////////////////////////////////////////////
1111/// Return number of fields in result set.
1112
1114{
1115 return 0;
1116}
1117
1118////////////////////////////////////////////////////////////////////////////////
1119/// Returns field name in result set.
1120
1122{
1123 return 0;
1124}
1125
1126////////////////////////////////////////////////////////////////////////////////
1127/// Shift cursor to nect row in result set.
1128
1130{
1131 return kFALSE;
1132}
1133
1134
1135////////////////////////////////////////////////////////////////////////////////
1136/// Increment iteration counter for statement, where parameter can be set.
1137/// Statement with parameters of previous iteration
1138/// automatically will be applied to database.
1139
1141{
1142 return kFALSE;
1143}
1144
1145////////////////////////////////////////////////////////////////////////////////
1146/// Release all buffers, used by statement.
1147
1149{
1150}
1151
1152////////////////////////////////////////////////////////////////////////////////
1153/// Allocate buffers for statement parameters/ result fields.
1154
1156{
1157}
1158
1159////////////////////////////////////////////////////////////////////////////////
1160/// Convert field value to string.
1161
1163{
1164 return 0;
1165}
1166
1167////////////////////////////////////////////////////////////////////////////////
1168/// Convert field to numeric value.
1169
1171{
1172 return 0;
1173}
1174
1175////////////////////////////////////////////////////////////////////////////////
1176/// Checks if field value is null.
1177
1179{
1180 return kTRUE;
1181}
1182
1183////////////////////////////////////////////////////////////////////////////////
1184/// Return field value as integer.
1185
1187{
1188 return 0;
1189}
1190
1191////////////////////////////////////////////////////////////////////////////////
1192/// Return field value as unsigned integer.
1193
1195{
1196 return 0;
1197}
1198
1199////////////////////////////////////////////////////////////////////////////////
1200/// Return field value as long integer.
1201
1203{
1204 return 0;
1205}
1206
1207////////////////////////////////////////////////////////////////////////////////
1208/// Return field value as 64-bit integer.
1209
1211{
1212 return 0;
1213}
1214
1215////////////////////////////////////////////////////////////////////////////////
1216/// Return field value as unsigned 64-bit integer.
1217
1219{
1220 return 0;
1221}
1222
1223////////////////////////////////////////////////////////////////////////////////
1224/// Return field value as double.
1225
1227{
1228 return 0.;
1229}
1230
1231////////////////////////////////////////////////////////////////////////////////
1232/// Return field value as string.
1233
1235{
1236 return 0;
1237}
1238
1239////////////////////////////////////////////////////////////////////////////////
1240/// Return field value as binary array.
1241
1243{
1244 return kFALSE;
1245}
1246
1247
1248////////////////////////////////////////////////////////////////////////////////
1249/// Return field value as date.
1250
1252{
1253 return kFALSE;
1254}
1255
1256////////////////////////////////////////////////////////////////////////////////
1257/// Return field value as time.
1258
1260{
1261 return kFALSE;
1262}
1263
1264////////////////////////////////////////////////////////////////////////////////
1265/// Return field value as date & time.
1266
1268{
1269 return kFALSE;
1270}
1271
1272////////////////////////////////////////////////////////////////////////////////
1273/// Return field value as time stamp.
1274
1276{
1277 return kFALSE;
1278}
1279
1280////////////////////////////////////////////////////////////////////////////////
1281/// Set parameter type to be used as buffer.
1282/// Used in both setting data to database and retriving data from data base.
1283/// Initialize proper MYSQL_BIND structure and allocate required buffers.
1284
1286{
1287 return kFALSE;
1288}
1289
1290////////////////////////////////////////////////////////////////////////////////
1291/// Check boundary condition before setting value of parameter.
1292/// Return address of parameter buffer.
1293
1295{
1296 return 0;
1297}
1298
1299////////////////////////////////////////////////////////////////////////////////
1300/// Set NULL as parameter value.
1301/// If NULL should be set for statement parameter during first iteration,
1302/// one should call before proper Set... method to identify type of argument for
1303/// the future. For instance, if one suppose to have double as type of parameter,
1304/// code should look like:
1305/// stmt->SetDouble(2, 0.);
1306/// stmt->SetNull(2);
1307
1309{
1310 return kFALSE;
1311}
1312
1313////////////////////////////////////////////////////////////////////////////////
1314/// Set parameter value as integer.
1315
1317{
1318 return kFALSE;
1319}
1320
1321////////////////////////////////////////////////////////////////////////////////
1322/// Set parameter value as unsigned integer.
1323
1325{
1326 return kFALSE;
1327}
1328
1329////////////////////////////////////////////////////////////////////////////////
1330/// Set parameter value as long integer.
1331
1333{
1334 return kFALSE;
1335}
1336
1337////////////////////////////////////////////////////////////////////////////////
1338/// Set parameter value as 64-bit integer.
1339
1341{
1342 return kFALSE;
1343}
1344
1345////////////////////////////////////////////////////////////////////////////////
1346/// Set parameter value as unsigned 64-bit integer.
1347
1349{
1350 return kFALSE;
1351}
1352
1353////////////////////////////////////////////////////////////////////////////////
1354/// Set parameter value as double.
1355
1357{
1358 return kFALSE;
1359}
1360
1361////////////////////////////////////////////////////////////////////////////////
1362/// Set parameter value as string.
1363
1365{
1366 return kFALSE;
1367}
1368
1369////////////////////////////////////////////////////////////////////////////////
1370/// Set parameter value as binary data.
1371
1373{
1374 return kFALSE;
1375}
1376
1377////////////////////////////////////////////////////////////////////////////////
1378/// Set parameter value as date.
1379
1381{
1382 return kFALSE;
1383}
1384
1385////////////////////////////////////////////////////////////////////////////////
1386/// Set parameter value as time.
1387
1389{
1390 return kFALSE;
1391}
1392
1393////////////////////////////////////////////////////////////////////////////////
1394/// Set parameter value as date & time.
1395
1397{
1398 return kFALSE;
1399}
1400
1401////////////////////////////////////////////////////////////////////////////////
1402/// Set parameter value as timestamp.
1403
1405{
1406 return kFALSE;
1407}
1408
1409#endif // MYSQL_VERSION_ID > 40100
double
l unsigned short
size_t fSize
int Int_t
Definition RtypesCore.h:45
unsigned int UInt_t
Definition RtypesCore.h:46
const Bool_t kFALSE
Definition RtypesCore.h:92
unsigned long ULong_t
Definition RtypesCore.h:55
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
char name[80]
Definition TGX11.cxx:110
int type
Definition TGX11.cxx:121
#define CheckErrNo(method, force, res)
#define CheckGetField(method, defres)
#define CheckStmt(method, res)
char * Form(const char *fmt,...)
@ kSize
Definition TStructNode.h:26
#define free
Definition civetweb.c:1539
#define snprintf
Definition civetweb.c:1540
#define malloc
Definition civetweb.c:1536
This class stores the date and time with a precision of one second in an unsigned 32 bit word (950130...
Definition TDatime.h:37
static ULong64_t fgAllocSizeLimit
void SetBuffersNumber(Int_t n)
Allocate buffers for statement parameters/ result fields.
Bool_t SetInt(Int_t npar, Int_t value) final
Set parameter value as integer.
void * BeforeSet(const char *method, Int_t npar, Int_t sqltype, Bool_t sig=kTRUE, ULong_t size=0)
Check boundary condition before setting value of parameter.
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.
UInt_t GetUInt(Int_t npar) final
Return field value as unsigned integer.
Bool_t NextIteration() final
Increment iteration counter for statement, where parameter can be set.
Double_t GetDouble(Int_t npar) final
Return field value as double.
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 IsSetParsMode() const
indicates when parameters bind should be called
const char * ConvertToString(Int_t npar)
Convert field value to string.
Bool_t GetDate(Int_t npar, Int_t &year, Int_t &month, Int_t &day) final
Return field value as date.
Bool_t SetDouble(Int_t npar, Double_t value) final
Set parameter value as double.
MYSQL_STMT * fStmt
Bool_t SetUInt(Int_t npar, UInt_t value) final
Set parameter value as unsigned integer.
Bool_t SetTimestamp(Int_t npar, Int_t year, Int_t month, Int_t day, Int_t hour, Int_t min, Int_t sec, Int_t frac=0) final
Set parameter value as timestamp.
Bool_t GetTime(Int_t npar, Int_t &hour, Int_t &min, Int_t &sec) final
Return field value as time.
Bool_t Process() final
Process statement.
Bool_t SetBinary(Int_t npar, void *mem, Long_t size, Long_t maxsize=0x1000) final
Set parameter value as binary data.
void Close(Option_t *="") final
Close statement.
Bool_t SetTime(Int_t npar, Int_t hour, Int_t min, Int_t sec) final
Set parameter value as time.
Int_t fWorkingMode
parameter definition structures
Int_t GetNumParameters() final
Return number of statement parameters.
void FreeBuffers()
Release all buffers, used by statement.
Bool_t IsNull(Int_t npar) final
Checks if field value is null.
Int_t fIterationCount
1 - setting parameters, 2 - retrieving results
ULong64_t GetULong64(Int_t npar) final
Return field value as unsigned 64-bit integer.
Long64_t GetLong64(Int_t npar) final
Return field value as 64-bit integer.
Bool_t IsResultSetMode() const
virtual ~TMySQLStatement()
Destructor.
const char * GetFieldName(Int_t nfield) final
Returns field name in result set.
Bool_t SetSQLParamType(Int_t npar, int sqltype, Bool_t sig, ULong_t sqlsize=0)
Set parameter type to be used as buffer.
Int_t GetInt(Int_t npar) final
Return field value as integer.
TParamData * fBuffer
array of bind data
Int_t GetNumFields() final
Return number of fields in result set.
Bool_t fNeedParBind
number of iteration
Bool_t SetLong(Int_t npar, Long_t value) final
Set parameter value as long integer.
Bool_t SetDate(Int_t npar, Int_t year, Int_t month, Int_t day) final
Set parameter value as date.
Bool_t StoreResult() final
Store result of statement processing to access them via GetInt(), GetDouble() and so on methods.
Int_t fNumBuffers
executed statement
Bool_t SetString(Int_t npar, const char *value, Int_t maxsize=256) final
Set parameter value as string.
Long_t GetLong(Int_t npar) final
Return field value as long integer.
TMySQLStatement(const TMySQLStatement &)=delete
Bool_t SetLong64(Int_t npar, Long64_t value) final
Set parameter value as 64-bit integer.
Int_t GetNumAffectedRows() final
Return number of affected rows after statement is processed.
Bool_t GetBinary(Int_t npar, void *&mem, Long_t &size) final
Return field value as binary array.
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.
long double ConvertToNumeric(Int_t npar)
Convert field to numeric value.
const char * GetString(Int_t npar) final
Return field value as string.
Bool_t SetNull(Int_t npar) final
Set NULL as parameter value.
Bool_t SetULong64(Int_t npar, ULong64_t value) final
Set parameter value as unsigned 64-bit integer.
Bool_t NextResultRow() final
Shift cursor to nect row in result set.
MYSQL_BIND * fBind
number of statement parameters
static const char * GetFloatFormat()
return current printf format for float/double members, default "%e"
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
const Int_t n
Definition legend1.C:16
Bool_t fSign
sqltype of parameter
std::string fFieldName
special buffer to be used for string conversions
ULong_t fResLength
signed - not signed type
Int_t fSize
allocated data buffer
my_bool fResNull
length argument
std::string fStrBuffer
indicates if argument is null
Int_t fSqlType
size of allocated data