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