Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MySQLResultSet.cxx
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file MySQLResultSet.cxx
1 // $Id: MySQLResultSet.cxx,v 1.1.1.1 2004/02/18 20:58:02 dave Exp $
2 //*-- Author : Valeriy Onuchin 26/02/2001
3 //
4 // RDBC driver to MySQL database implemented with MySQL C API.
5 //
6 // ++ The code consists of some parts stolen from mm JDBC and
7 // MyODBC ODBC drivers and other mysql-related open sources.
8 //
9 
10 //
12 //
13 // A TSQLResultSet provides access to a table of data. A
14 // TSQLResultSet object is usually generated by executing
15 // TSQLStatement.
16 //
17 // A TSQLResultSet maintains a cursor pointing to its current row
18 // of data. Initially the cursor is positioned before the first
19 // row. The Next() method moves the cursor to the next row.
20 //
21 // The GetXXX methods retrieve column values for the current row.
22 // You can retrieve values using either the index number of the
23 // column or the name of the column. In general,using the column
24 // index will be more efficient. Columns are numbered from 1.
25 //
26 // For maximum portability, TSQLResultSet columns within each row
27 // should be read in left-to-right order and each column should be
28 // read only once.
29 //
30 // For the GetXXX methods, the driver attempts to convert the
31 // underlying data to the specified ROOT type and returns a suitable
32 // value. See the specification for allowable mappings
33 // from SQL types to ROOT types with the TSQLResultSet::GetXXX
34 // methods.
35 //
36 // Column names used as input to GetXXX methods are case
37 // insensitive. When performing a GetXXX using a column name,
38 // if several columns have the same name, then the value of the
39 // first matching column will be returned. The column name option
40 // is designed to be used when column names are used in the SQL
41 // query. For columns that are NOT explicitly named in the query,
42 // it is best to use column numbers. If column names are used, there
43 // is no way for the programmer to guarantee that they actually refer
44 // to the intended columns.
45 //
46 // A TSQLResultSet is automatically closed by the TSQLStatement that
47 // generated it when that TSQLStatement is closed, re-executed,
48 // or used to retrieve the next result from a sequence of multiple
49 // results.
50 //
51 // The number, types and properties of a TSQLResultSet's columns are
52 // provided by the TSQLResulSetMetaData object returned by the
53 // GetMetaData() method.
54 //
55 // See also:
56 // TSQLStatement::ExecuteQuery(const TString&),
57 // TSQLStatement::GetResultSet(), TSQLResultSetMetaData
58 //
59 //___________________________________________________________________
60 //
61 // kCONCUR_READ_ONLY
62 //
63 // The concurrency mode for a TSQLResultSet object that may
64 // NOT be updated.
65 //___________________________________________________________________
66 //
67 // kCONCUR_UPDATABLE
68 //
69 // The concurrency mode for a TSQLResultSet
70 // object that may be updated.
71 //___________________________________________________________________
72 //
73 // kFETCH_FORWARD
74 //
75 // The rows in a result set will be
76 // processed in a forward direction; first-to-last.
77 //___________________________________________________________________
78 //
79 // kFETCH_REVERSE
80 //
81 // The rows in a result set will be
82 // processed in a reverse direction; last-to-first.
83 //___________________________________________________________________
84 //
85 // kFETCH_UNKNOWN
86 //
87 // The order in which rows in a result set
88 // will be processed is unknown.
89 //___________________________________________________________________
90 //
91 // kTYPE_FORWARD_ONLY
92 //
93 // The type for a TSQLResultSet object whose
94 // cursor may move only forward.
95 //___________________________________________________________________
96 //
97 // kTYPE_SCROLL_INSENSITIVE
98 //
99 // The type for a TSQLResultSet object that is
100 // scrollable but generally not sensitive to changes made by
101 // others.
102 //___________________________________________________________________
103 //
104 // kTYPE_SCROLL_SENSITIVE
105 //
106 // The type for a TSQLResultSet object that is
107 // scrollable and generally sensitive to changes made by
108 // others.
109 //
111 
112 #include <RDBC/TSQLResultSet.h>
114 #include <RDBC/TSQLStatement.h>
115 #include <TList.h>
116 #include <TMath.h>
117 #include <TStopwatch.h>
118 #include <TBuffer.h>
119 #include <TTree.h>
120 #include <TRandom.h>
121 #include <TBranch.h>
122 #include <iostream>
123 #include <sstream>
124 #include <ctype.h>
125 #include <time.h>
126 
127 #include <TSQLRow.h>
128 #include "MySQLResultSetPrivate.h"
129 
131 
132 
133 //
134 // MySQLRow rewritten from TMySQLRow
135 //
137 class MySQLRow: public TSQLRow
138 {
139 friend class TSQLResultSet;
140 
141 private:
142 
143  MYSQL_RES *fResult; // current result set
144  MYSQL_ROW fFields; // current row
145  ULong_t *fFieldLength; // length of each field in the row
146 
147  MySQLRow(void *res)
148  {
149  fResult = (MYSQL_RES *) res;
150  fFields = (MYSQL_ROW)fResult->current_row;
151  fFieldLength = 0;
152  }
153 
154  MySQLRow* Set(void *res)
155  {
156  fResult = (MYSQL_RES *) res;
157  fFields = (MYSQL_ROW)fResult->current_row;
158  fFieldLength = 0;
159  return this;
160  }
161 
162  virtual ~MySQLRow()
163  {
164  if(fFields) Close();
165  }
166 
167  void Close(Option_t *opt="")
168  {
169  // Close row.
170 
171  if (!fFields) return;
172 
173  fFields = 0;
174  fResult = 0;
175  fFieldLength = 0;
176  }
177 
178  Bool_t IsValid(Int_t field)
179  {
180  // Check if row is open and field index within range.
181 
182  if (!fFields) {
183  // Error("IsValid", "row closed");
184  return kFALSE;
185  }
186 
187  if (field < 0 || field >= (Int_t)mysql_num_fields(fResult)) {
188  //Error("IsValid", "field index out of bounds");
189  return kFALSE;
190  }
191  return kTRUE;
192  }
193 
194  ULong_t GetFieldLength(Int_t field)
195  {
196  // Get length in bytes of specified field.
197 
198  if (!IsValid(field)) return 0;
199 
200  if (!fFieldLength)
201  fFieldLength = mysql_fetch_lengths(fResult);
202 
203  if (!fFieldLength) {
204 // Error("GetFieldLength", "cannot get field length");
205  return 0;
206  }
207 
208  return fFieldLength[field];
209  }
210 
211  const char* GetField(Int_t field)
212  {
213  // Get specified field from row (0 <= field < GetFieldCount()).
214 
215  if (!IsValid(field)) return 0;
216 
217  return fFields[field];
218  }
219 };
220 
222 //___________________________________________________________________
224 {
225  // ctor
226 
227  fStatement = stmt;
229  fRow = new RDBCRow(pd->fMYSQL_RES);
230  fMetaData = 0; // create it later, when TSQLResultSet::GetMetaData()
231 }
232 
233 //___________________________________________________________________
235 {
236  // destructor.
237 
239 
240  if(fMetaData) delete fMetaData;
241  if(fRow) delete fRow;
242  if(imp) delete imp;
243 
244  Destroyed();
245 }
246 
247 //___________________________________________________________________
249 {
250  // Reports whether the last column read had a value of SQL NULL.
251  // Note that you must first call GetXXX on a column to try to
252  // read its value and then call WasNull() to see if the value
253  // read was SQL NULL.
254  //
255  // Returns:
256  // kTRUE if last column read was SQL NULL and
257  // kFALSE - otherwise
258  // Throws:
259  // TSQLException - if a database access error occurs
260 
262  return imp->fWasNull;
263 }
264 
265 //___________________________________________________________________
266 TString TSQLResultSet::GetString( Int_t columnIndex )
267 {
268  // Gets the value of a column in the current row as a TString.
269  //
270  // Parameters:
271  // columnIndex - the first column is 1, the second is 2, ...
272  // Returns:
273  // the column value; if the value is SQL NULL, the result
274  // is null
275  // Throws:
276  // TSQLException - if a database access error occurs
277 
279 
280  if(!imp->fMYSQL_RES->field_count) {
281  Throw(new TSQLException("Query generated no fields for ResultSet", "S1002"));
282  return "";
283  }
284 
285  if( (UInt_t)(columnIndex-1) >= imp->fMYSQL_RES->field_count ) {
286  Throw(new TSQLException(Form("Invalid column number ( %d > %d )",columnIndex,imp->fMYSQL_RES->field_count+1),"S1002",);
287  return "";
288  }
289 
290  return imp->fMYSQL_RES->current_row[columnIndex-1];
291 }
292 
293 //___________________________________________________________________
294 Bool_t TSQLResultSet::GetBoolean( Int_t columnIndex )
295 {
296  // Gets the value of a column in the current row as a boolean.
297  //
298  // Parameters:
299  // columnIndex - the first column is 1, the second is 2, ...
300  // Returns:
301  // the column value; if the value is SQL NULL, the result is
302  // kFALSE
303  // Throws:
304  // TSQLException - if a database access error occurs
305 
307 
308  if(!imp->fMYSQL_RES->field_count) {
309  Throw(new TSQLException("Query generated no fields for ResultSet", "S1002",));
310  return kFALSE;
311  }
312 
313  if( (UInt_t)(columnIndex-1) >= imp->fMYSQL_RES->field_count ) {
314  Throw(new TSQLException(Form("Invalid column number ( %d > %d )",columnIndex,imp->fMYSQL_RES->field_count+1),"S1002",);
315  return kFALSE;
316  }
317 
318  const char* str = imp->fMYSQL_RES->current_row[columnIndex-1];
319 
320  return ( str && strlen(str) ) ?
321  (str[0] == 't') || (str[0] == 'T') ||
322  (str[0] == 'y') || (str[0] == 'Y') ||
323  (str[0] == '1') || (str[0] == '1') : kFALSE;
324 }
325 
326 //___________________________________________________________________
327 Char_t TSQLResultSet::GetByte( Int_t columnIndex )
328 {
329  // Gets the value of a column in the current row as a byte.
330  //
331  // Parameters:
332  // columnIndex - the first column is 1, the second is 2, ...
333  // Returns:
334  // the column value; if the value is SQL NULL,
335  // the result is 0
336  // Throws:
337  // TSQLException - if a database access error occurs
338 
339  Char_t return_value = 0;
340 
342 
343  if(!imp->fMYSQL_RES->field_count) {
344  Throw(new TSQLException("Query generated no fields for ResultSet", "S1002"));
345  return 0;
346  }
347 
348  if( (UInt_t)(columnIndex-1) >= imp->fMYSQL_RES->field_count ) {
349  Throw(new TSQLException(Form("Invalid column number ( %d > %d )",columnIndex,imp->fMYSQL_RES->field_count+1),"S1002",);
350  return 0;
351  }
352 
353  const char* str = imp->fMYSQL_RES->current_row[columnIndex-1];
354 
355  switch( imp->MYSQL_RES->fields[column-1].type ) {
356  case FIELD_TYPE_DECIMAL:
357  case FIELD_TYPE_TINY:
358  case FIELD_TYPE_SHORT:
359  case FIELD_TYPE_LONG:
360  case FIELD_TYPE_FLOAT:
361  case FIELD_TYPE_DOUBLE:
362  case FIELD_TYPE_LONGLONG:
363  case FIELD_TYPE_INT24:
364  return (Char_t)atoi(str);
365  default:
366  return str[0];
367  }
368  return 0; // not reached
369 }
370 
371 //___________________________________________________________________
372 Short_t TSQLResultSet::GetShort( Int_t columnIndex )
373 {
374  // Gets the value of a column in the current row as a Short_t.
375  //
376  // Parameters:
377  // columnIndex - the first column is 1, the second is 2, ...
378  // Returns:
379  // the column value; if the value is SQL NULL,
380  // the result is 0
381  // Throws:
382  // TSQLException - if a database access error occurs
383 
385 
386  if(!imp->fMYSQL_RES->field_count) {
387  Throw(new TSQLException("Query generated no fields for ResultSet", "S1002"));
388  return 0;
389  }
390 
391  if( (UInt_t)(columnIndex-1) >= imp->fMYSQL_RES->field_count ) {
392  Throw(new TSQLException(Form("Invalid column number ( %d > %d )",columnIndex,imp->fMYSQL_RES->field_count+1),"S1002",);
393  return 0;
394  }
395 
396  return (Short_t)atoi(imp->fMYSQL_RES->current_row[columnIndex-1]);
397 }
398 
399 //___________________________________________________________________
400 Int_t TSQLResultSet::GetInt( Int_t columnIndex )
401 {
402  // Gets the value of a column in the current row as a Int_t.
403  //
404  // Parameters:
405  // columnIndex - the first column is 1, the second is 2, ...
406  // Returns:
407  // the column value; if the value is SQL NULL,
408  // the result is 0
409  // Throws:
410  // TSQLException - if a database access error occurs
411 
413 
414  if(!imp->fMYSQL_RES->field_count) {
415  Throw(new TSQLException("Query generated no fields for ResultSet", "S1002"));
416  return 0;
417  }
418 
419  if( (UInt_t)(columnIndex-1) >= imp->fMYSQL_RES->field_count ) {
420  Throw(new TSQLException(Form("Invalid column number ( %d > %d )",columnIndex,imp->fMYSQL_RES->field_count+1),"S1002",);
421  return 0;
422  }
423 
424  return (Int_t)atoi(imp->fMYSQL_RES->current_row[columnIndex-1]);
425 }
426 
427 //___________________________________________________________________
428 Long_t TSQLResultSet::GetLong( Int_t columnIndex )
429 {
430  // Gets the value of a column in the current row as a Long_t.
431  //
432  // Parameters:
433  // columnIndex - the first column is 1, the second is 2, ...
434  // Returns:
435  // the column value; if the value is SQL NULL,
436  // the result is 0
437  // Throws:
438  // TSQLException - if a database access error occurs
439 
441 
442  if(!imp->fMYSQL_RES->field_count) {
443  Throw(new TSQLException("Query generated no fields for ResultSet", "S1002"));
444  return 0;
445  }
446 
447  if( (UInt_t)(columnIndex-1) >= imp->fMYSQL_RES->field_count ) {
448  Throw(new TSQLException(Form("Invalid column number ( %d > %d )",columnIndex,imp->fMYSQL_RES->field_count+1),"S1002",);
449  return 0;
450  }
451 
452  char* value = imp->fMYSQL_RES->current_row[columnIndex-1];
453  Int_t length = strlen(value);
454 
455  // .... MyDOBC says "Check if it could be a date...... :)"
456 
457  if( length >= 10 && value[4] == '-' && value[7] == '-' && (!value[10] || value[10] == ' ') ) {
458  return ((Long_t) atol(value)*10000L+(Long_t) atol(value+5)*100L+(Long_t) atol(value+8));
459  } else {
460  return (Long_t)atol(value);
461  }
462 }
463 
464 //___________________________________________________________________
465 Float_t TSQLResultSet::GetFloat( Int_t columnIndex )
466 {
467  // Gets the value of a column in the current row as a Float_t.
468  //
469  // Parameters:
470  // columnIndex - the first column is 1, the second is 2, ...
471  // Returns:
472  // the column value; if the value is SQL NULL,
473  // the result is 0
474  // Throws:
475  // TSQLException - if a database access error occurs
476 
478 
479  if(!imp->fMYSQL_RES->field_count) {
480  Throw(new TSQLException("Query generated no fields for ResultSet", "S1002"));
481  return 0;
482  }
483 
484  if( (UInt_t)(columnIndex-1) >= imp->fMYSQL_RES->field_count ) {
485  Throw(new TSQLException(Form("Invalid column number ( %d > %d )",columnIndex,imp->fMYSQL_RES->field_count+1),"S1002",);
486  return 0;
487  }
488 
489  return (Float_t)atof(imp->fMYSQL_RES->current_row[columnIndex-1]);
490 }
491 
492 //___________________________________________________________________
493 Double_t TSQLResultSet::GetDouble( Int_t columnIndex )
494 {
495  // Gets the value of a column in the current row as a Double_t.
496  //
497  // Parameters:
498  // columnIndex - the first column is 1, the second is 2, ...
499  // Returns:
500  // the column value; if the value is SQL NULL,
501  // the result is 0
502  // Throws:
503  // TSQLException - if a database access error occurs
504 
506 
507  if(!imp->fMYSQL_RES->field_count) {
508  Throw(new TSQLException("Query generated no fields for ResultSet", "S1002"));
509  return 0;
510  }
511 
512  if( (UInt_t)(columnIndex-1) >= imp->fMYSQL_RES->field_count ) {
513  Throw(new TSQLException(Form("Invalid column number ( %d > %d )",columnIndex,imp->fMYSQL_RES->field_count+1),"S1002",);
514  return 0;
515  }
516 
517  return (Double_t)atof(imp->fMYSQL_RES->current_row[columnIndex-1]);
518 }
519 
520 //___________________________________________________________________
521 TArrayC TSQLResultSet::GetBytes( Int_t columnIndex )
522 {
523  // Gets the value of a column in the current row as a char array.
524  // The chars represent the raw values returned by the driver.
525  //
526  // Parameters:
527  // columnIndex - the first column is 1, the second is 2, ...
528  // Returns:
529  // the column value; if the value is SQL NULL,
530  // the result is null
531  // Throws:
532  // TSQLException - if a database access error occurs
533 
534  TArrayC array;
535 
537 
538  if(!imp->fMYSQL_RES->field_count) {
539  Throw(new TSQLException("Query generated no fields for ResultSet", "S1002"));
540  return array;
541  }
542 
543  if( (UInt_t)(columnIndex-1) >= imp->fMYSQL_RES->field_count ) {
544  Throw(new TSQLException(Form("Invalid column number ( %d > %d )",columnIndex,imp->fMYSQL_RES->field_count+1),"S1002",);
545  return array;
546  }
547 
548  return array;
549 }
550 
551 //___________________________________________________________________
552 TSQLDate TSQLResultSet::GetDate( Int_t columnIndex )
553 {
554  // Gets the value of a column in the current row as a TSQLDate
555  // object.
556  //
557  // Parameters:
558  // columnIndex - the first column is 1, the second is 2, ...
559  // Returns:
560  // the column value; if the value is SQL NULL,
561  // the result is null
562  // Throws:
563  // TSQLException - if a database access error occurs
564 
565  TSQLDate return_value;
566 
568 
569  if(!imp->fMYSQL_RES->field_count) {
570  Throw(new TSQLException("Query generated no fields for ResultSet", "S1002"));
571  return ;
572  }
573 
574  if( (UInt_t)(columnIndex-1) >= imp->fMYSQL_RES->field_count ) {
575  Throw(new TSQLException(Form("Invalid column number ( %d > %d )",columnIndex,imp->fMYSQL_RES->field_count+1),"S1002",);
576  return ;
577  }
578 
579  return return_value;
580 }
581 
582 //___________________________________________________________________
583 TSQLTime TSQLResultSet::GetTime( Int_t columnIndex )
584 {
585  // Gets the value of a column in the current row as a TSQLTime
586  // object.
587  //
588  // Parameters:
589  // columnIndex - the first column is 1, the second is 2, ...
590  // Returns:
591  // the column value; if the value is SQL NULL,
592  // the result is null
593  // Throws:
594  // TSQLException - if a database access error occurs
595 
596  TSQLTime return_value;
597 
599 
600  if(!imp->fMYSQL_RES->field_count) {
601  Throw(new TSQLException("Query generated no fields for ResultSet", "S1002"));
602  return ;
603  }
604 
605  if( (UInt_t)(columnIndex-1) >= imp->fMYSQL_RES->field_count ) {
606  Throw(new TSQLException(Form("Invalid column number ( %d > %d )",columnIndex,imp->fMYSQL_RES->field_count+1),"S1002",);
607  return ;
608  }
609 
610  return return_value;
611 }
612 
613 //___________________________________________________________________
615 {
616  // Gets the value of a column in the current row as a
617  // TSQLTimestamp object.
618  //
619  // Parameters:
620  // columnIndex - the first column is 1, the second is 2, ...
621  // Returns:
622  // the column value; if the value is SQL NULL,
623  // the result is null
624  // Throws:
625  // TSQLException - if a database access error occurs
626 
627  TSQLTimestamp return_value;
628 
630 
631  if(!imp->fMYSQL_RES->field_count) {
632  Throw(new TSQLException("Query generated no fields for ResultSet", "S1002"));
633  return ;
634  }
635 
636  if( (UInt_t)(columnIndex-1) >= imp->fMYSQL_RES->field_count ) {
637  Throw(new TSQLException(Form("Invalid column number ( %d > %d )",columnIndex,imp->fMYSQL_RES->field_count+1),"S1002",);
638  return ;
639  }
640 
641  return return_value;
642 }
643 
644 //___________________________________________________________________
645 TBuffer* TSQLResultSet::GetAsciiStream( Int_t columnIndex )
646 {
647  // Gets the value of a column in the current row as a stream
648  // of ASCII characters. The value can then be read in chunks from
649  // the stream. This method is particularly suitable for
650  // retrieving large LONGVARCHAR values. The driver will do
651  // any necessary conversion from the database format into ASCII.
652  //
653  // Note: All the data in the returned stream must be read prior
654  // to getting the value of any other column. The next call to
655  // a get method implicitly closes the stream. Also, a stream
656  // may return 0 when the method available is called whether
657  // there is data available or not.
658  //
659  // Parameters:
660  // columnIndex - the first column is 1, the second is 2, ...
661  // Returns:
662  // A TBuffer that delivers the database column
663  // value as a stream of one char ASCII characters.
664  // If the value is SQL NULL then the result is null.
665  //
666  // Throws:
667  // TSQLException - if a database access error occurs
668 
669  TBuffer* buffer = 0;
670 
672 
673  if(!imp->fMYSQL_RES->field_count) {
674  Throw(new TSQLException("Query generated no fields for ResultSet", "S1002"));
675  return buffer;
676  }
677 
678  if( (UInt_t)(columnIndex-1) >= imp->fMYSQL_RES->field_count ) {
679  Throw(new TSQLException(Form("Invalid column number ( %d > %d )",columnIndex,imp->fMYSQL_RES->field_count+1),"S1002",);
680  return buffer;
681  }
682 
683  return buffer;
684 }
685 
686 //___________________________________________________________________
687 TBuffer* TSQLResultSet::GetBinaryStream( Int_t columnIndex )
688 {
689  // Gets the value of a column in the current row as a stream of
690  // uninterpreted chars. The value can then be read in chunks
691  // from the stream. This method is particularly suitable for
692  // retrieving large LONGVARBINARY values.
693  //
694  // Note: All the data in the returned stream must be read
695  // prior to getting the value of any other column. The next
696  // call to a Get method implicitly closes the stream. Also,
697  // a stream may return 0 when the method available is called
698  // whether there is data available or not.
699  //
700  // Parameters:
701  // columnIndex - the first column is 1, the second is 2, ...
702  // Returns:
703  // TBuffer that delivers the database column
704  // value as a stream of uninterpreted chars. If the value
705  // is SQL NULL then the result is null.
706  // Throws:
707  // TSQLException - if a database access error occurs
708 
709  TBuffer* buffer = 0;
710 
712 
713  if(!imp->fMYSQL_RES->field_count) {
714  Throw(new TSQLException("Query generated no fields for ResultSet", "S1002"));
715  return buffer;
716  }
717 
718  if( (UInt_t)(columnIndex-1) >= imp->fMYSQL_RES->field_count ) {
719  Throw(new TSQLException(Form("Invalid column number ( %d > %d )",columnIndex,imp->fMYSQL_RES->field_count+1),"S1002",);
720  return buffer;
721  }
722 
723  return buffer;
724 }
725 
726 //___________________________________________________________________
727 TObject* TSQLResultSet::GetObject( Int_t columnIndex )
728 {
729  // Gets the value of a column in the current row as ROOT object.
730  //
731  // Parameters:
732  // columnIndex - the first column is 1, the second is 2, ...
733  // Returns:
734  // TObject
735  // Throws:
736  // TSQLException - if a database access error occurs
737 
738  TObject* obj =0;
739 
741 
742  if(!imp->fMYSQL_RES->field_count) {
743  Throw(new TSQLException("Query generated no fields for ResultSet", "S1002"));
744  return obj;
745  }
746 
747  if( (UInt_t)(columnIndex-1) >= imp->fMYSQL_RES->field_count ) {
748  Throw(new TSQLException(Form("Invalid column number ( %d > %d )",columnIndex,imp->fMYSQL_RES->field_count+1),"S1002",);
749  return obj;
750  }
751 
752  TBuffer *b = GetBinaryStream(columnIndex);
753  obj = b->ReadObject(TObject::Class());
754  b->DetachBuffer();
755  delete b;
756  return obj;
757 }
758 
759 //___________________________________________________________________
760 TString TSQLResultSet::GetString( const TString& columnName )
761 {
762  // Gets the value of a column in the current row as a TString.
763  //
764  // Parameters:
765  // columnName - the SQL name of the column
766  // Returns:
767  // the column value; if the value is SQL NULL,
768  // the result is null
769  // Throws:
770  // TSQLException - if a database access error occurs
771 
772  return GetString(FindColumn(columnName));
773 }
774 
775 //___________________________________________________________________
776 Bool_t TSQLResultSet::GetBoolean( const TString& columnName )
777 {
778  // Gets the value of a column in the current row as a boolean.
779  //
780  // Parameters:
781  // columnName - the SQL name of the column
782  // Returns:
783  // the column value; if the value is SQL NULL,
784  // the result is kFALSE
785  // Throws:
786  // TSQLException - if a database access error occurs
787 
788  return GetBoolean(FindColumn(columnName));
789 }
790 
791 //___________________________________________________________________
792 Char_t TSQLResultSet::GetByte( const TString& columnName )
793 {
794  // Gets the value of a column in the current row as a Char_t.
795  //
796  // Parameters:
797  // columnName - the SQL name of the column
798  // Returns:
799  // the column value; if the value is SQL NULL,
800  // the result is 0
801  // Throws:
802  // TSQLException - if a database access error occurs
803 
804  return GetByte(FindColumn(columnName));
805 }
806 
807 //___________________________________________________________________
808 Short_t TSQLResultSet::GetShort( const TString& columnName )
809 {
810  // Gets the value of a column in the current row as a Short_t.
811  //
812  // Parameters:
813  // columnName - the SQL name of the column
814  // Returns:
815  // the column value; if the value is SQL NULL,
816  // the result is 0
817  // Throws:
818  // TSQLException - if a database access error occurs
819 
820  return GetShort(FindColumn(columnName));
821 }
822 
823 //___________________________________________________________________
824 Int_t TSQLResultSet::GetInt( const TString& columnName )
825 {
826  // Gets the value of a column in the current row as a Int_t.
827  //
828  // Parameters:
829  // columnName - the SQL name of the column
830  // Returns:
831  // the column value; if the value is SQL NULL,
832  // the result is 0
833  // Throws:
834  // TSQLException - if a database access error occurs
835 
836  return GetInt(FindColumn(columnName));
837 }
838 
839 //___________________________________________________________________
840 Long_t TSQLResultSet::GetLong( const TString& columnName )
841 {
842  // Gets the value of a column in the current row as a Long_t.
843  //
844  // Parameters:
845  // columnName - the SQL name of the column
846  // Returns:
847  // the column value; if the value is SQL NULL,
848  // the result is 0
849  // Throws:
850  // TSQLException - if a database access error occurs
851 
852  return GetLong(FindColumn(columnName));
853 }
854 
855 //___________________________________________________________________
856 Float_t TSQLResultSet::GetFloat( const TString& columnName )
857 {
858  // Gets the value of a column in the current row as a Float_t.
859  //
860  // Parameters:
861  // columnName - the SQL name of the column
862  // Returns:
863  // the column value; if the value is SQL NULL,
864  // the result is 0
865  // Throws:
866  // TSQLException - if a database access error occurs
867 
868  return GetFloat(FindColumn(columnName));
869 }
870 
871 //___________________________________________________________________
872 Double_t TSQLResultSet::GetDouble( const TString& columnName )
873 {
874  // Gets the value of a column in the current row as a Double_t.
875  //
876  // Parameters:
877  // columnName - the SQL name of the column
878  // Returns:
879  // the column value; if the value is SQL NULL,
880  // the result is 0
881  // Throws:
882  // TSQLException - if a database access error occurs
883 
884  return GetDouble(FindColumn(columnName));
885 }
886 
887 //___________________________________________________________________
888 TArrayC TSQLResultSet::GetBytes( const TString& columnName )
889 {
890  // Gets the value of a column in the current row as a char
891  // array. The chars represent the raw values returned by the
892  // driver.
893  //
894  // Parameters:
895  // columnName - the SQL name of the column
896  // Returns:
897  // the column value; if the value is SQL NULL,
898  // the result is null
899  // Throws:
900  // TSQLException - if a database access error occurs
901 
902  return GetBytes(FindColumn(columnName));
903 }
904 
905 //___________________________________________________________________
906 TSQLDate TSQLResultSet::GetDate( const TString& columnName )
907 {
908  // Gets the value of a column in the current row as a TSQLDate
909  // object.
910  //
911  // Parameters:
912  // columnName - the SQL name of the column
913  // Returns:
914  // the column value; if the value is SQL NULL,
915  // the result is null
916  // Throws:
917  // TSQLException - if a database access error occurs
918 
919  return GetDate(FindColumn(columnName));
920 }
921 
922 //___________________________________________________________________
923 TSQLTime TSQLResultSet::GetTime( const TString& columnName )
924 {
925  // Gets the value of a column in the current row as a TSQLTime
926  // object.
927  //
928  // Parameters:
929  // columnName - the SQL name of the column
930  // Returns:
931  // the column value; if the value is SQL NULL,
932  // the result is null
933  // Throws:
934  // TSQLException - if a database access error occurs
935 
936  return GetTime(FindColumn(columnName));
937 }
938 
939 //___________________________________________________________________
940 TSQLTimestamp TSQLResultSet::GetTimestamp( const TString& columnName )
941 {
942  // Gets the value of a column in the current row as a
943  // TSQLTimestamp object.
944  //
945  // Parameters:
946  // columnName - the SQL name of the column
947  // Returns:
948  // the column value; if the value is SQL NULL,
949  // the result is null
950  // Throws:
951  // TSQLException - if a database access error occurs
952 
953  return GetTimestamp(FindColumn(columnName));
954 }
955 
956 //___________________________________________________________________
957 TBuffer* TSQLResultSet::GetAsciiStream( const TString& columnName )
958 {
959  // Gets the value of a column in the current row as a stream
960  // of ASCII characters. The value can then be read in chunks
961  // from the stream. This method is particularly suitable for
962  // retrieving large LONGVARCHAR values. The driver will do
963  // any necessary conversion from the database format into ASCII.
964  //
965  // Note: All the data in the returned stream must be read prior
966  // to getting the value of any other column. The next call to
967  // a Get method implicitly closes the stream. Also, a stream
968  // may return 0 when the method available is called whether
969  // there is data available or not.
970  //
971  // Parameters:
972  // columnName - the SQL name of the column
973  // Returns:
974  // TBuffer that delivers the database column
975  // value as a stream of one char ASCII characters. If
976  // the value is SQL NULL then the result is null.
977  // Throws:
978  // TSQLException - if a database access error occurs
979 
980  return GetAsciiStream(FindColumn(columnName));
981 }
982 
983 //___________________________________________________________________
984 TBuffer* TSQLResultSet::GetBinaryStream( const TString& columnName )
985 {
986  // Gets the value of a column in the current row as a stream of
987  // uninterpreted chars. The value can then be read in chunks
988  // from the stream. This method is particularly suitable for
989  // retrieving large LONGVARBINARY values. The driver will
990  // do any necessary conversion from the database format into
991  // uninterpreted chars.
992  //
993  // Note: All the data in the returned stream must be read
994  // prior to getting the value of any other column. The next
995  // call to a Get method implicitly closes the stream. Also,
996  // a stream may return 0 when the method available is called
997  // whether there is data available or not.
998  //
999  // Parameters:
1000  // columnName - the SQL name of the column
1001  // Returns:
1002  // TBuffer that delivers the database column
1003  // value as a stream of uninterpreted chars. If the value
1004  // is SQL NULL then the result is null.
1005  // Throws:
1006  // TSQLException - if a database access error occurs
1007 
1008  return GetBinaryStream(FindColumn(columnName));
1009 }
1010 
1011 //___________________________________________________________________
1012 TObject* TSQLResultSet::GetObject( const TString& columnName )
1013 {
1014  // Gets the value of a column in the current row as ROOT object.
1015  //
1016  // Parameters:
1017  // columnIndex - the first column is 1, the second is 2, ...
1018  // Returns:
1019  // TObject
1020  // Throws:
1021  // TSQLException - if a database access error occurs
1022 
1023  return GetObject(FindColumn(columnName));
1024 }
1025 
1026 //___________________________________________________________________
1028 {
1029  // Gets the name of the SQL cursor used by this TSQLResultSet.
1030  //
1031  // In SQL, a result table is retrieved through a cursor that
1032  // is named. The current row of a result can be updated or
1033  // deleted using a positioned Update/Delete statement that
1034  // references the cursor name. To insure that the cursor has
1035  // the proper isolation level to support update, the cursor's
1036  // select statement should be of the form 'SELECT FOR UPDATE'.
1037  // If the 'FOR UPDATE' clause is omitted the positioned
1038  // updates may fail.
1039  // The current row of a TSQLResultSet is also the current row
1040  // of this SQL cursor.
1041  //
1042  // Note: If positioned update is not supported a
1043  // SQLException is thrown
1044  // Returns:
1045  // the TSQLResultSet's SQL cursor name
1046  // Throws:
1047  // TSQLException - if a database access error occurs
1048 
1049  return "NO_NAME"; // no cursors supported ...
1050 }
1051 
1052 //___________________________________________________________________
1054 {
1055  // Retrieves the number, types and properties of a
1056  // TSQLResultSet's columns.
1057  //
1058  // Returns:
1059  // the description of a TSQLResultSet's columns
1060  // Throws:
1061  // TSQLException - if a database access error occurs
1062 
1063  return fMetaData ? fMetaData : fMetaData = new TSQLResultSetMetaData(this,fImp);
1064 }
1065 
1066 //___________________________________________________________________
1067 Int_t TSQLResultSet::FindColumn( const TString& columnName )
1068 {
1069  // Maps the given resultset column name to its TSQLResultSet
1070  // column index.
1071  //
1072  // Parameters:
1073  // columnName - the name of the column
1074  // Returns:
1075  // the column index
1076  // Throws:
1077  // TSQLException - if a database access error occurs
1078 
1080 
1081  for( int i=0; i < imp->fMYSQL_RES->field_count; i++ ) {
1082  !strcmp(columnName.Data(),imp->fMYSQL_RES->fields[i].name) ? return i :;;
1083  }
1084  return 0;
1085 }
1086 
1087 //___________________________________________________________________
1089 {
1090  // Indicates whether the cursor is before the first row in
1091  // the result set.
1092  //
1093  // Returns:
1094  // kTRUE if the cursor is before the first row,
1095  // kFALSE otherwise. Returns kFALSE when the
1096  // result set contains no rows.
1097  // Throws:
1098  // TSQLException - if a database access error occurs
1099 
1101  return (!imp->fMYSQL_RES->row_count) ? kFALSE : (fCurrentRow == -1);
1102 }
1103 
1104 //___________________________________________________________________
1106 {
1107  // Indicates whether the cursor is after the last row in
1108  // the result set.
1109  //
1110  // Returns:
1111  // kTRUE if the cursor is after the last row,
1112  // kFALSE otherwise. Returns kFALSE when the
1113  // result set contains no rows.
1114  // Throws:
1115  // TSQLException - if a database access error occurs
1116 
1118  return (!imp->fMYSQL_RES->row_count) ? kFALSE : (fCurrentRow == imp->fMYSQL_RES->row_count);
1119 }
1120 
1121 //___________________________________________________________________
1123 {
1124  // Indicates whether the cursor is on the first row of
1125  // the result set.
1126  //
1127  // Returns:
1128  // kTRUE if the cursor is on the first row,
1129  // kFALSE otherwise.
1130  // Throws:
1131  // TSQLException - if a database access error occurs
1132 
1134  return (!imp->fMYSQL_RES->row_count) ? kFALSE : (fCurrentRow == 0);
1135 }
1136 
1137 //___________________________________________________________________
1139 {
1140  // Indicates whether the cursor is on the last row of the
1141  // result set.
1142  //
1143  // Note: Calling the method IsLast() may be expensive because
1144  // the driver might need to fetch ahead one row in
1145  // order to determine whether the current row is the
1146  // last row in the result set.
1147  //
1148  // Returns:
1149  // kTRUE if the cursor is on the last row,
1150  // kFALSE otherwise.
1151  // Throws:
1152  // TSQLException - if a database access error occurs
1153 
1155  return (!imp->fMYSQL_RES->row_count) ? kFALSE : (fCurrentRow == imp->fMYSQL_RES->row_count-1);
1156 }
1157 
1158 //___________________________________________________________________
1160 {
1161  // Moves the cursor to the front of the result set, just before
1162  // the first row. Has no effect if the result set contains no
1163  // rows.
1164  //
1165  // Throws:
1166  // TSQLException - if a database access error occurs or
1167  // the result set type is kTYPE_FORWARD_ONLY
1168 
1170 
1171  if( imp->fOnInsertRow ) imp->fOnInsertRow = kFALSE;
1172  if( imp->fDoingUpdates ) imp->fDoingUpdates = kFALSE;
1173 
1174  if( !imp->fMYSQL_RES->row_count ) return;
1175  else {
1176  imp->fCurrentRow = -1;
1177  This_Row = null;
1178  }
1179 }
1180 
1181 //___________________________________________________________________
1183 {
1184  // Moves the cursor to the end of the result set, just after
1185  // the last row. Has no effect if the result set contains no
1186  // rows.
1187  //
1188  // Throws:
1189  // TSQLException - if a database access error occurs or
1190  // the result set type is kTYPE_FORWARD_ONLY
1191 
1193 
1194  if( imp->fOnInsertRow ) imp->fOnInsertRow = kFALSE;
1195  if( imp->fDoingUpdates ) imp->fDoingUpdates = kFALSE;
1196 
1197  if( !imp->fMYSQL_RES->row_count ) {
1198  imp->fRurrentRow = imp->fMYSQL_RES->row_count;
1199  This_Row = null;
1200  }
1201 }
1202 
1203 //___________________________________________________________________
1205 {
1206  // Retrieves the current row number. The first row is number 1,
1207  // the second number 2, and so on.
1208  //
1209  // Returns:
1210  // the current row number; 0 if there is no current row
1211  // Throws:
1212  // TSQLException - if a database access error occurs
1213 
1215 
1216  return ( imp->fCurrentRow < 0 ||
1217  imp->fCurrentRow > imp->fMYSQL_RES->row_count ) ? 0 : imp->fCurrentRow+1;
1218 }
1219 
1220 //___________________________________________________________________
1221 //void TSQLResultSet::SetFetchDirection(Int_t direction)
1222 //{
1223  // Gives a hint as to the direction in which the rows in this
1224  // result set will be processed. The initial value is determined
1225  // by the TSQLStatement that produced the result set.
1226  // The fetch direction may be changed at any time.
1227  //
1228  // Throws:
1229  // TSQLException - if a database access error occurs or
1230  // the result set type is kTYPE_FORWARD_ONLY and the fetch
1231  // direction is not forward
1232 //
1233 //}
1234 
1235 //___________________________________________________________________
1236 //Int_t TSQLResultSet::GetFetchDirection()
1237 //{
1238  // Returns the fetch direction for this result set.
1239  //
1240  // Returns:
1241  // the current fetch direction for this result set
1242  // Throws:
1243  // TSQLException - if a database access error occurs
1244 //
1245 // using namespace odbc;
1246 // odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
1247 // return_value = rs->getFetchDirection();
1248 //}
1249 
1250 //___________________________________________________________________
1252 {
1253  // Gives the driver a hint as to the number of rows that
1254  // should be fetched from the database when more rows are needed
1255  // for this result set. If the fetch size specified is zero,
1256  // the driver ignores the value and is free to make its own
1257  // best guess as to what the fetch size should be. The default
1258  // value is set by the statement that created the result set.
1259  // The fetch size may be changed at any time.
1260  //
1261  // Parameters:
1262  // rows - the number of rows to fetch
1263  // Throws:
1264  // TSQLException - if a database access error occurs or the
1265  // condition 0 <= rows <= GetMaxRows() is not satisfied.
1266 
1267  if (rows < 0 /* || rows > getMaxRows()*/) {
1268  throw new SQLException("Value must be between 0 and getMaxRows()", "S1009");
1269  }
1270 
1271  _fetch_size = rows;
1272 }
1273 
1274 //___________________________________________________________________
1276 {
1277  // Returns the fetch size for this result set.
1278  //
1279  // Returns:
1280  // the current fetch size for this result set
1281  // Throws:
1282  // TSQLException - if a database access error occurs
1283 
1284  Int_t return_value = 0;
1285 
1286  return return_value;
1287 }
1288 
1289 //___________________________________________________________________
1291 {
1292  // Returns the type of this result set. The type is
1293  // determined by the TSQLStatement that created the result set.
1294  //
1295  // Returns:
1296  // kTYPE_FORWARD_ONLY, kTYPE_SCROLL_INSENSITIVE, or
1297  // kTYPE_SCROLL_SENSITIVE
1298  // Throws:
1299  // TSQLException - if a database access error occurs
1300 
1301  Int_t return_value = kTYPE_SCROLL_INSENSITIVE;
1302  return return_value;
1303 }
1304 
1305 //___________________________________________________________________
1307 {
1308  // Returns the concurrency mode of this result set. The
1309  // concurrency used is determined by the TSQLStatement that
1310  // created the result set.
1311  //
1312  // Returns:
1313  // the concurrency type, kCONCUR_READ_ONLY or
1314  // kCONCUR_UPDATABLE
1315  // Throws:
1316  // TSQLException - if a database access error occurs
1317 
1318  Int_t return_value = 0;
1319 
1320  return return_value;
1321 }
1322 
1323 //___________________________________________________________________
1325 {
1326  // Indicates whether the current row has been updated. The
1327  // value returned depends on whether or not the result set
1328  // can detect updates.
1329  //
1330  // Returns:
1331  // kTRUE if the row has been visibly updated by
1332  // the owner or another, and updates are detected
1333  // Throws:
1334  // TSQLException - if a database access error occurs
1335  // See Also:
1336  // TSQLDatabaseMetaData::updatesAreDetected(Int_t)
1337 
1338  Bool_t return_value = kFALSE;
1339 
1340  return return_value;
1341 }
1342 
1343 //___________________________________________________________________
1345 {
1346  // Indicates whether the current row has had an insertion.
1347  // The value returned depends on whether or not the
1348  // result set can detect visible inserts.
1349  //
1350  // Returns:
1351  // kTRUE if a row has had an insertion and insertions
1352  // are detected
1353  // Throws:
1354  // TSQLException - if a database access error occurs
1355  // See Also:
1356  // TSQLDatabaseMetaData::insertsAreDetected(Int_t)
1357 
1358  Bool_t return_value = kFALSE;
1359 
1360  return return_value;
1361 }
1362 
1363 //___________________________________________________________________
1365 {
1366  // Indicates whether a row has been deleted. A deleted row
1367  // may leave a visible "hole" in a result set. This method
1368  // can be used to detect holes in a result set. The value
1369  // returned depends on whether or not the result set can
1370  // detect deletions.
1371  //
1372  // Returns:
1373  // kTRUE if a row was deleted and deletions are detected
1374  // Throws:
1375  // TSQLException - if a database access error occurs
1376  // See Also:
1377  // TSQLDatabaseMetaData::deletesAreDetected(Int_t)
1378 
1379  Bool_t return_value = kFALSE;
1380 
1381  return return_value;
1382 }
1383 
1384 //___________________________________________________________________
1385 void TSQLResultSet::UpdateNull( Int_t columnIndex )
1386 {
1387  // Give a nullable column a null value. The UpdateXXX methods
1388  // are used to update column values in the current row,
1389  // or the insert row. The UpdateXXX methods do not update the
1390  // underlying database; instead the UpdateRow() or InsertRow()
1391  // methods are called to update the database.
1392  //
1393  // Parameters:
1394  // columnIndex - the first column is 1, the second is 2, ...
1395  // Throws:
1396  // TSQLException - if a database access error occurs
1397 
1398 }
1399 
1400 //___________________________________________________________________
1401 void TSQLResultSet::UpdateBoolean( Int_t columnIndex,Bool_t x )
1402 {
1403  // Updates a column with a boolean value. The UpdateXXX
1404  // methods are used to update column values in the current row,
1405  // or the insert row. The UpdateXXX methods do not update the
1406  // underlying database; instead the UpdateRow() or InsertRow()
1407  // methods are called to update the database.
1408  //
1409  // Parameters:
1410  // columnIndex - the first column is 1, the second is 2, ...
1411  // x - the new column value
1412  // Throws:
1413  // TSQLException - if a database access error occurs
1414 
1415 }
1416 
1417 //___________________________________________________________________
1418 void TSQLResultSet::UpdateByte( Int_t columnIndex,Char_t x )
1419 {
1420  // Updates a column with a Char_t value. The UpdateXXX methods
1421  // are used to update column values in the current row,
1422  // or the insert row. The UpdateXXX methods do not update the
1423  // underlying database; instead the UpdateRow() or InsertRow()
1424  // methods are called to update the database.
1425  //
1426  // Parameters:
1427  // columnIndex - the first column is 1, the second is 2, ...
1428  // x - the new column value
1429  // Throws:
1430  // TSQLException - if a database access error occurs
1431 
1432 }
1433 
1434 //___________________________________________________________________
1435 void TSQLResultSet::UpdateShort( Int_t columnIndex,Short_t x )
1436 {
1437  // Updates a column with a Short_t value. The UpdateXXX methods
1438  // are used to update column values in the current row,
1439  // or the insert row. The UpdateXXX methods do not update the
1440  // underlying database; instead the UpdateRow() or InsertRow()
1441  // methods are called to update the database.
1442  //
1443  // Parameters:
1444  // columnIndex - the first column is 1, the second is 2, ...
1445  // x - the new column value
1446  // Throws:
1447  // TSQLException - if a database access error occurs
1448 
1449 }
1450 
1451 //___________________________________________________________________
1452 void TSQLResultSet::UpdateInt( Int_t columnIndex,Int_t x )
1453 {
1454  // Updates a column with an integer value. The UpdateXXX
1455  // methods are used to update column values in the current row,
1456  // or the insert row. The UpdateXXX methods do not update the
1457  // underlying database; instead the UpdateRow() or InsertRow()
1458  // methods are called to update the database.
1459  //
1460  // Parameters:
1461  // columnIndex - the first column is 1, the second is 2, ...
1462  // x - the new column value
1463  // Throws:
1464  // TSQLException - if a database access error occurs
1465 
1466 }
1467 
1468 //___________________________________________________________________
1469 void TSQLResultSet::UpdateLong( Int_t columnIndex,Long_t x )
1470 {
1471  // Updates a column with a Long_t value. The UpdateXXX methods
1472  // are used to update column values in the current row,
1473  // or the insert row. The UpdateXXX methods do not update the
1474  // underlying database; instead the UpdateRow() or InsertRow()
1475  // methods are called to update the database.
1476  //
1477  // Parameters:
1478  // columnIndex - the first column is 1, the second is 2, ...
1479  // x - the new column value
1480  // Throws:
1481  // TSQLException - if a database access error occurs
1482 
1483 }
1484 
1485 //___________________________________________________________________
1486 void TSQLResultSet::UpdateFloat( Int_t columnIndex,Float_t x )
1487 {
1488  // Updates a column with a Float_t value. The UpdateXXX methods
1489  // are used to update column values in the current row,
1490  // or the insert row. The UpdateXXX methods do not update the
1491  // underlying database; instead the UpdateRow() or InsertRow()
1492  // methods are called to update the database.
1493  //
1494  // Parameters:
1495  // columnIndex - the first column is 1, the second is 2, ...
1496  // x - the new column value
1497  // Throws:
1498  // TSQLException - if a database access error occurs
1499 
1500 }
1501 
1502 //___________________________________________________________________
1503 void TSQLResultSet::UpdateDouble( Int_t columnIndex,
1504  Double_t x )
1505 {
1506  // Updates a column with a Double value. The UpdateXXX
1507  // methods are used to update column values in the current row,
1508  // or the insert row. The UpdateXXX methods do not update the
1509  // underlying database; instead the UpdateRow() or InsertRow()
1510  // methods are called to update the database.
1511  //
1512  // Parameters:
1513  // columnIndex - the first column is 1, the second is 2, ...
1514  // x - the new column value
1515  // Throws:
1516  // TSQLException - if a database access error occurs
1517 
1518 }
1519 
1520 //___________________________________________________________________
1521 void TSQLResultSet::UpdateString( Int_t columnIndex,
1522  const TString& x )
1523 {
1524  // Updates a column with a TString value. The UpdateXXX
1525  // methods are used to update column values in the current row,
1526  // or the insert row. The UpdateXXX methods do not update the
1527  // underlying database; instead the UpdateRow() or InsertRow()
1528  // methods are called to update the database.
1529  //
1530  // Parameters:
1531  // columnIndex - the first column is 1, the second is 2, ...
1532  // x - the new column value
1533  // Throws:
1534  // TSQLException - if a database access error occurs
1535 
1536 }
1537 
1538 //___________________________________________________________________
1539 void TSQLResultSet::UpdateBytes( Int_t columnIndex,
1540  const TArrayC& x )
1541 {
1542  // Updates a column with a Char_t array value. The UpdateXXX
1543  // methods are used to update column values in the current row,
1544  // or the insert row. The UpdateXXX methods do not update the
1545  // underlying database; instead the UpdateRow() or InsertRow()
1546  // methods are called to update the database.
1547  //
1548  // Parameters:
1549  // columnIndex - the first column is 1, the second is 2, ...
1550  // x - the new column value
1551  // Throws:
1552  // TSQLException - if a database access error occurs
1553 
1554 }
1555 
1556 //___________________________________________________________________
1557 void TSQLResultSet::UpdateDate( Int_t columnIndex,
1558  const TSQLDate& x )
1559 {
1560  // Updates a column with a TSQLDate value. The UpdateXXX methods
1561  // are used to update column values in the current row,
1562  // or the insert row. The UpdateXXX methods do not update the
1563  // underlying database; instead the UpdateRow() or InsertRow()
1564  // methods are called to update the database.
1565  //
1566  // Parameters:
1567  // columnIndex - the first column is 1, the second is 2, ...
1568  // x - the new column value
1569  // Throws:
1570  // TSQLException - if a database access error occurs
1571 
1572 }
1573 
1574 //___________________________________________________________________
1575 void TSQLResultSet::UpdateTime( Int_t columnIndex,
1576  const TSQLTime& x )
1577 {
1578  // Updates a column with a TSQLTime value. The UpdateXXX methods
1579  // are used to update column values in the current row,
1580  // or the insert row. The UpdateXXX methods do not update the
1581  // underlying database; instead the UpdateRow() or InsertRow()
1582  // methods are called to update the database.
1583  //
1584  // Parameters:
1585  // columnIndex - the first column is 1, the second is 2, ...
1586  // x - the new column value
1587  // Throws:
1588  // TSQLException - if a database access error occurs
1589 
1590 }
1591 
1592 //___________________________________________________________________
1593 void TSQLResultSet::UpdateTimestamp( Int_t columnIndex,
1594  const TSQLTimestamp& x )
1595 {
1596  // Updates a column with a TSQLTimestamp value. The UpdateXXX
1597  // methods are used to update column values in the current row,
1598  // or the insert row. The UpdateXXX methods do not update the
1599  // underlying database; instead the UpdateRow() or InsertRow()
1600  // methods are called to update the database.
1601  //
1602  // Parameters:
1603  // columnIndex - the first column is 1, the second is 2, ...
1604  // x - the new column value
1605  // Throws:
1606  // TSQLException - if a database access error occurs
1607 
1608 }
1609 
1610 //___________________________________________________________________
1611 void TSQLResultSet::UpdateAsciiStream( Int_t columnIndex,
1612  TBuffer* x,
1613  Int_t length )
1614 {
1615  // Updates a column with an ascii stream value. The UpdateXXX
1616  // methods are used to update column values in the current row,
1617  // or the insert row. The UpdateXXX methods do not update the
1618  // underlying database; instead the UpdateRow() or InsertRow()
1619  // methods are called to update the database.
1620  //
1621  // Parameters:
1622  // columnIndex - the first column is 1, the second is 2, ...
1623  // x - the new column value
1624  // length - length of stream
1625  // Throws:
1626  // TSQLException - if a database access error occurs
1627 
1628 }
1629 
1630 //___________________________________________________________________
1631 void TSQLResultSet::UpdateBinaryStream( Int_t columnIndex,
1632  TBuffer* x,
1633  Int_t length )
1634 {
1635  // Updates a column with a binary stream value. The UpdateXXX
1636  // methods are used to update column values in the current row,
1637  // or the insert row. The UpdateXXX methods do not update the
1638  // underlying database; instead the UpdateRow() or InsertRow()
1639  // methods are called to update the database.
1640  //
1641  // Parameters:
1642  // columnIndex - the first column is 1, the second is 2, ...
1643  // x - the new column value
1644  // length - length of stream
1645  // Throws:
1646  // TSQLException - if a database access error occurs
1647 
1648 }
1649 
1650 //___________________________________________________________________
1651 void TSQLResultSet::UpdateObject( Int_t columnIndex,TObject* x )
1652 {
1653  // Updates a column with a ROOT object. The UpdateXXX
1654  // methods are used to update column values in the current row,
1655  // or the insert row. The UpdateXXX methods do not update the
1656  // underlying database; instead the UpdateRow() or InsertRow()
1657  // methods are called to update the database.
1658  //
1659  // Parameters:
1660  // columnIndex - the first column is 1, the second is 2, ...
1661  // x - the new column value
1662  // length - length of stream
1663  // Throws:
1664  // TSQLException - if a database access error occurs
1665 
1666  TBuffer *b = new TBuffer(TBuffer::kWrite);
1667  b->WriteObject(x);
1668  UpdateBinaryStream(columnIndex,b,b->BufferSize());
1669  b->DetachBuffer();
1670  delete b;
1671 }
1672 
1673 //___________________________________________________________________
1674 void TSQLResultSet::UpdateNull( const TString& columnName )
1675 {
1676  // Updates a column with a null value. The UpdateXXX methods
1677  // are used to update column values in the current row,
1678  // or the insert row. The UpdateXXX methods do not update the
1679  // underlying database; instead the UpdateRow() or InsertRow()
1680  // methods are called to update the database.
1681  //
1682  // Parameters:
1683  // columnIndex - the first column is 1, the second is 2, ...
1684  // x - the new column value
1685  // Throws:
1686  // TSQLException - if a database access error occurs
1687 
1688  UpdateNull(FindColumn(columnName));
1689 }
1690 
1691 //___________________________________________________________________
1692 void TSQLResultSet::UpdateBoolean( const TString& columnName,Bool_t x )
1693 {
1694  // Updates a column with a boolean value. The UpdateXXX methods
1695  // are used to update column values in the current row,
1696  // or the insert row. The UpdateXXX methods do not update the
1697  // underlying database; instead the UpdateRow() or InsertRow()
1698  // methods are called to update the database.
1699  //
1700  // Parameters:
1701  // columnIndex - the first column is 1, the second is 2, ...
1702  // x - the new column value
1703  // Throws:
1704  // TSQLException - if a database access error occurs
1705 
1706  UpdateBoolean(FindColumn(columnName),x);
1707 }
1708 
1709 //___________________________________________________________________
1710 void TSQLResultSet::UpdateByte( const TString& columnName,Char_t x )
1711 {
1712  // Updates a column with a Char_t value. The UpdateXXX methods
1713  // are used to update column values in the current row,
1714  // or the insert row. The UpdateXXX methods do not update the
1715  // underlying database; instead the UpdateRow() or InsertRow()
1716  // methods are called to update the database.
1717  //
1718  // Parameters:
1719  // columnIndex - the first column is 1, the second is 2, ...
1720  // x - the new column value
1721  // Throws:
1722  // TSQLException - if a database access error occurs
1723 
1724  UpdateByte(FindColumn(columnName),x);
1725 }
1726 
1727 //___________________________________________________________________
1728 void TSQLResultSet::UpdateShort( const TString& columnName,Short_t x )
1729 {
1730  // Updates a column with a short value. The UpdateXXX methods
1731  // are used to update column values in the current row,
1732  // or the insert row. The UpdateXXX methods do not update the
1733  // underlying database; instead the UpdateRow() or InsertRow()
1734  // methods are called to update the database.
1735  //
1736  // Parameters:
1737  // columnIndex - the first column is 1, the second is 2, ...
1738  // x - the new column value
1739  // Throws:
1740  // TSQLException - if a database access error occurs
1741 
1742  UpdateShort(FindColumn(columnName),x);
1743 }
1744 
1745 //___________________________________________________________________
1746 void TSQLResultSet::UpdateInt( const TString& columnName,Int_t x )
1747 {
1748  // Updates a column with an integer value. The UpdateXXX methods
1749  // are used to update column values in the current row,
1750  // or the insert row. The UpdateXXX methods do not update the
1751  // underlying database; instead the UpdateRow() or InsertRow()
1752  // methods are called to update the database.
1753  //
1754  // Parameters:
1755  // columnIndex - the first column is 1, the second is 2, ...
1756  // x - the new column value
1757  // Throws:
1758  // TSQLException - if a database access error occurs
1759 
1760  UpdateInt(FindColumn(columnName),x);
1761 }
1762 
1763 //___________________________________________________________________
1764 void TSQLResultSet::UpdateLong( const TString& columnName,Long_t x )
1765 {
1766  // Updates a column with a long value. The UpdateXXX methods
1767  // are used to update column values in the current row,
1768  // or the insert row. The UpdateXXX methods do not update the
1769  // underlying database; instead the UpdateRow() or InsertRow()
1770  // methods are called to update the database.
1771  //
1772  // Parameters:
1773  // columnIndex - the first column is 1, the second is 2, ...
1774  // x - the new column value
1775  // Throws:
1776  // TSQLException - if a database access error occurs
1777 
1778  UpdateLong(FindColumn(columnName),x);
1779 }
1780 
1781 //___________________________________________________________________
1782 void TSQLResultSet::UpdateFloat( const TString& columnName,Float_t x )
1783 {
1784  // Updates a column with a float value. The UpdateXXX methods
1785  // are used to update column values in the current row,
1786  // or the insert row. The UpdateXXX methods do not update the
1787  // underlying database; instead the UpdateRow() or InsertRow()
1788  // methods are called to update the database.
1789  //
1790  // Parameters:
1791  // columnIndex - the first column is 1, the second is 2, ...
1792  // x - the new column value
1793  // Throws:
1794  // TSQLException - if a database access error occurs
1795 
1796  UpdateFloat(FindColumn(columnName),x);
1797 }
1798 
1799 //___________________________________________________________________
1800 void TSQLResultSet::UpdateDouble( const TString& columnName,Double_t x )
1801 {
1802  // Updates a column with a double value. The UpdateXXX methods
1803  // are used to update column values in the current row,
1804  // or the insert row. The UpdateXXX methods do not update the
1805  // underlying database; instead the UpdateRow() or InsertRow()
1806  // methods are called to update the database.
1807  //
1808  // Parameters:
1809  // columnIndex - the first column is 1, the second is 2, ...
1810  // x - the new column value
1811  // Throws:
1812  // TSQLException - if a database access error occurs
1813 
1814  UpdateDouble(FindColumn(columnName),x);
1815 }
1816 
1817 //___________________________________________________________________
1818 void TSQLResultSet::UpdateString( const TString& columnName,
1819  const TString& x )
1820 {
1821  // Updates a column with a TString value. The UpdateXXX methods
1822  // are used to update column values in the current row,
1823  // or the insert row. The UpdateXXX methods do not update the
1824  // underlying database; instead the UpdateRow() or InsertRow()
1825  // methods are called to update the database.
1826  //
1827  // Parameters:
1828  // columnIndex - the first column is 1, the second is 2, ...
1829  // x - the new column value
1830  // Throws:
1831  // TSQLException - if a database access error occurs
1832 
1833  UpdateString(FindColumn(columnName),x);
1834 }
1835 
1836 //___________________________________________________________________
1837 void TSQLResultSet::UpdateBytes( const TString& columnName,
1838  const TArrayC& x )
1839 {
1840  // Updates a column with a bytes array value. The update methods
1841  // are used to update column values in the current row,
1842  // or the insert row. The UpdateXXX methods do not update the
1843  // underlying database; instead the UpdateRow() or InsertRow()
1844  // methods are called to update the database.
1845  //
1846  // Parameters:
1847  // columnIndex - the first column is 1, the second is 2, ...
1848  // x - the new column value
1849  // Throws:
1850  // TSQLException - if a database access error occurs
1851 
1852  UpdateBytes(FindColumn(columnName),x);
1853 }
1854 
1855 //___________________________________________________________________
1856 void TSQLResultSet::UpdateDate( const TString& columnName,
1857  const TSQLDate& x )
1858 {
1859  // Updates a column with a TSQLDate value. The UpdateXXX methods
1860  // are used to update column values in the current row,
1861  // or the insert row. The UpdateXXX methods do not update the
1862  // underlying database; instead the UpdateRow() or InsertRow()
1863  // methods are called to update the database.
1864  //
1865  // Parameters:
1866  // columnIndex - the first column is 1, the second is 2, ...
1867  // x - the new column value
1868  // Throws:
1869  // TSQLException - if a database access error occurs
1870 
1871  UpdateDate(FindColumn(columnName),x);
1872 }
1873 
1874 //___________________________________________________________________
1875 void TSQLResultSet::UpdateTime( const TString& columnName,
1876  const TSQLTime& x )
1877 {
1878  // Updates a column with a TSQLTime value. The UpdateXXX methods
1879  // are used to update column values in the current row,
1880  // or the insert row. The UpdateXXX methods do not update the
1881  // underlying database; instead the UpdateRow() or InsertRow()
1882  // methods are called to update the database.
1883  //
1884  // Parameters:
1885  // columnIndex - the first column is 1, the second is 2, ...
1886  // x - the new column value
1887  // Throws:
1888  // TSQLException - if a database access error occurs
1889 
1890  UpdateTime(FindColumn(columnName),x);
1891 }
1892 
1893 //___________________________________________________________________
1894 void TSQLResultSet::UpdateTimestamp( const TString& columnName,
1895  const TSQLTimestamp& x )
1896 {
1897  // Updates a column with a TSQLTimestamp value. The update methods
1898  // are used to update column values in the current row,
1899  // or the insert row. The UpdateXXX methods do not update the
1900  // underlying database; instead the UpdateRow() or InsertRow()
1901  // methods are called to update the database.
1902  //
1903  // Parameters:
1904  // columnIndex - the first column is 1, the second is 2, ...
1905  // x - the new column value
1906  // Throws:
1907  // TSQLException - if a database access error occurs
1908 
1909  UpdateTimestamp(FindColumn(columnName),x);
1910 }
1911 
1912 //___________________________________________________________________
1913 void TSQLResultSet::UpdateAsciiStream( const TString& columnName,
1914  TBuffer* x,
1915  Int_t length )
1916 {
1917  // Updates a column with an ascii stream value. The update methods
1918  // are used to update column values in the current row,
1919  // or the insert row. The UpdateXXX methods do not update the
1920  // underlying database; instead the UpdateRow() or InsertRow()
1921  // methods are called to update the database.
1922  //
1923  // Parameters:
1924  // columnIndex - the first column is 1, the second is 2, ...
1925  // x - the new column value
1926  // length - length of stream
1927  // Throws:
1928  // TSQLException - if a database access error occurs
1929 
1930  UpdateAsciiStream(FindColumn(columnName),x,length);
1931 }
1932 
1933 //___________________________________________________________________
1934 void TSQLResultSet::UpdateBinaryStream( const TString& columnName,
1935  TBuffer* x,
1936  Int_t length )
1937 {
1938  // Updates a column with a binary stream value. The update methods
1939  // are used to update column values in the current row,
1940  // or the insert row. The UpdateXXX methods do not update the
1941  // underlying database; instead the UpdateRow() or InsertRow()
1942  // methods are called to update the database.
1943  //
1944  // Parameters:
1945  // columnIndex - the first column is 1, the second is 2, ...
1946  // x - the new column value
1947  // length - length of stream
1948  // Throws:
1949  // TSQLException - if a database access error occurs
1950 
1951  UpdateBinaryStream(FindColumn(columnName),x,length);
1952 }
1953 
1954 //___________________________________________________________________
1955 void TSQLResultSet::UpdateObject(const TString& columnName,TObject* x)
1956 {
1957  // Updates a column with a ROOT object. The update methods
1958  // are used to update column values in the current row,
1959  // or the insert row. The UpdateXXX methods do not update the
1960  // underlying database; instead the UpdateRow() or InsertRow()
1961  // methods are called to update the database.
1962  //
1963  // Parameters:
1964  // columnIndex - the first column is 1, the second is 2, ...
1965  // x - the new column value
1966  // length - length of stream
1967  // Throws:
1968  // TSQLException - if a database access error occurs
1969 
1970  UpdateObject(FindColumn(columnName),x);
1971 }
1972 
1973 //___________________________________________________________________
1975 {
1976  // Inserts the contents of the insert row into the result set
1977  // and the database. Must be on the insert row when this method
1978  // is called.
1979  //
1980  // Throws:
1981  // TSQLException - if a database access error occurs, if
1982  // called when not on the insert row, or if not all of
1983  // non-nullable columns in the insert row have been given
1984  // a value.
1985 
1986 
1987 }
1988 
1989 //___________________________________________________________________
1991 {
1992  // Updates the underlying database with the new contents of
1993  // the current row. Cannot be called when on the insert row.
1994  //
1995  // Throws:
1996  // TSQLException - if a database access error occurs or if
1997  // called when on the insert row
1998 
1999 }
2000 
2001 //___________________________________________________________________
2003 {
2004  // Deletes the current row from the result set and the underlying
2005  // database. Cannot be called when on the insert row.
2006  //
2007  // Throws:
2008  // TSQLException - if a database access error occurs or
2009  // if called when on the insert row.
2010 
2011 }
2012 
2013 //___________________________________________________________________
2015 {
2016  // Refreshes the current row with its most recent value in
2017  // the database. Cannot be called when on the insert row.
2018  // The RefreshRow() method provides a way for an application to
2019  // explicitly tell the driver to refetch a row(s) from the
2020  // database. An application may want to call RefreshRow() when
2021  // caching or prefetching is being done by the driver to
2022  // fetch the latest value of a row from the database. The
2023  // driver may actually refresh multiple rows at once if the
2024  // fetch size is greater than one. All values are refetched
2025  // subject to the transaction isolation level and cursor
2026  // sensitivity. If RefreshRow() is called after calling UpdateXXX,
2027  // but before calling UpdateRow(), then the updates made to the
2028  // row are lost. Calling the method RefreshRow() frequently will
2029  // likely slow performance.
2030  //
2031  // Throws:
2032  // TSQLException - if a database access error occurs or
2033  // if called when on the insert row
2034 
2035 
2036 }
2037 
2038 //___________________________________________________________________
2040 {
2041  // Cancels the updates made to a row. This method may be
2042  // called after calling an UpdateXXX method(s) and before
2043  // calling UpdateRow() to rollback the updates made to a row.
2044  // If no updates have been made or UpdateRow() has already been
2045  // called then this method has no effect.
2046  //
2047  // Throws:
2048  // TSQLException - if a database access error occurs or if
2049  // called when on the insert row
2050 
2051 }
2052 
2053 //___________________________________________________________________
2055 {
2056  // Moves the cursor to the insert row. The current cursor
2057  // position is remembered while the cursor is positioned on
2058  // the insert row. The insert row is a special row associated
2059  // with an updatable result set. It is essentially a buffer
2060  // where a new row may be constructed by calling the UpdateXXX
2061  // methods prior to inserting the row into the result set.
2062  // Only the UpdateXXX, GetXXX, and InsertRow() methods may be
2063  // called when the cursor is on the insert row.
2064  // All of the columns in a result set must be given a value
2065  // each time this method is called before calling InsertRow().
2066  // The method UpdateXXX must be called before a GetXXX method
2067  // can be called on a column value.
2068  //
2069  // Throws:
2070  // TSQLException - if a database access error occurs
2071  // or the result set is not updatable
2072 
2073 }
2074 
2075 //___________________________________________________________________
2077 {
2078  // Moves the cursor to the remembered cursor position,
2079  // usually the current row. This method has no effect if the
2080  // cursor is not on the insert row.
2081  //
2082  // Throws:
2083  // TSQLException - if a database access error occurs or
2084  // the result set is not updatable
2085 
2086 
2087 }
2088 
2089 //___________________________________________________________________
2091 {
2092  // Returns the TSQLStatement that produced this TSQLResultSet
2093  // object. If the result set was generated some other way, such
2094  // as by a TSQLDatabaseMetaData method,this method returns null.
2095  //
2096  // Returns:
2097  // the TSQLStatment that produced the result set or null
2098  // if the result set was produced some other way
2099  // Throws:
2100  // TSQLException - if a database access error occurs
2101 
2102  return fStatement;
2103 }
2104 
2105 //___________________________________________________________________
2107 {
2108  // Moves the cursor down one row from its current position. A
2109  // TSQLResultSet cursor is initially positioned before the first
2110  // row; the first call to next makes the first row the current
2111  // row; the second call makes the second row the current row,
2112  // and so on.
2113  //
2114  // If an input stream is open for the current row, a call to the
2115  // method next will implicitly close it. The TSQLResultSet's
2116  // warning chain is cleared when a new row is read.
2117  //
2118  // Returns:
2119  // pointer to TSQLRow(kTRUE) if the new current row is valid;
2120  // null(kFALSE) if there are no more rows
2121  // Throws:
2122  // TSQLException - if a database access error occurs
2123 
2125 
2126  if( imp->fOnInsertRow ) imp->fOnInsertRow = kFALSE;
2127  if( imp->fDoingUpdates ) imp->fDoingUpdates = kFALSE;
2128 
2129  if( !imp->fMYSQL_RES->row_count ) return;
2130 
2131  return return_value ? fRow->Set(this) : 0;
2132 }
2133 
2134 //___________________________________________________________________
2136 {
2137  // Moves the cursor to the first row in the result set.
2138  //
2139  // Returns:
2140  // pointer to TSQLRow(kTRUE) if the cursor is on a valid row;
2141  // null(kFALSE) if there are no rows in the result set
2142  // Throws:
2143  // TSQLException - if a database access error occurs or
2144  // the result set type is kTYPE_FORWARD_ONLY
2145 
2147  MySQLStatementPrivate* stmt = (MySQLStatementPrivate*)fStatement->fImp;
2149 
2150  if( imp->fCurrentRow || imp->fCursorType != kTYPE_FORWARD_ONLY ) {
2151  Throw();
2152  return 0;
2153  }
2154 
2155  if( imp->fOnInsertRow ) imp->fOnInsertRow = kFALSE;
2156 
2157  if( !imp->fMYSQL_RES->row_count || con->fMYSQL->status==MYSQL_STATUS_USE_RESULT ) return 0;
2158  else {
2159  if( imp->fDoingUpdates ) imp->fDoingUpdates = kFALSE;
2160  imp->fCurrentRow = 0;
2161  mysql_data_seek(imp->fMYSQL_RES,0L);
2162 
2163  return fRow->Set(imp->fMYSQL_RES);
2164  }
2165 }
2166 
2167 //___________________________________________________________________
2168 TSQLRow* TSQLResultSet::Absolute( Int_t row )
2169 {
2170  // Moves the cursor to the given row number in the result set.
2171  // If the row number is positive, the cursor moves to the
2172  // given row number with respect to the beginning of the
2173  // result set. The first row is row 1, the second is row 2,
2174  // and so on.
2175  //
2176  // If the given row number is negative, the cursor moves to an
2177  // absolute row position with respect to the end of the result
2178  // set. For example, calling Absolute(-1) positions the cursor
2179  // on the last row, Absolute(-2) indicates the next-to-last row,
2180  // and so on.
2181  //
2182  // An attempt to position the cursor beyond the first/last row
2183  // in the result set leaves the cursor before/after the first/last
2184  // row, respectively.
2185  //
2186  // Note: calling Absolute(1) is the same as calling First().
2187  // calling Absolute(-1) is the same as calling Last().
2188  //
2189  // Returns:
2190  // pointer to TSQLRow(kTRUE) if the cursor is on the result set;
2191  // null(kFALSE) otherwise
2192  // Throws:
2193  // TSQLException - if a database access error occurs or
2194  // row is 0, or result set type is kTYPE_FORWARD_ONLY
2195 
2196  if (row == 0) {
2197  throw new SQLException("Cannot absolute position to row 0", "S1009");
2198  }
2199 
2200  if (_on_insert_row) {
2201  _on_insert_row = false;
2202  }
2203 
2204  if (_doing_updates) {
2205  _doing_updates = false;
2206  }
2207 
2208  if (row == 1) {
2209  return first();
2210  }
2211  else if (row == -1) {
2212  return last();
2213  }
2214 
2215  if (row > Rows.size()) {
2216  afterLast();
2217 
2218  return false;
2219  }
2220  else if (row < 0) {
2221 
2222  // adjust to reflect after end of result set
2223  int new_row_position = Rows.size() + row + 1;
2224 
2225  if (new_row_position <= 0) {
2226  beforeFirst();
2227 
2228  return false;
2229  }
2230  else {
2231  return absolute(new_row_position);
2232  }
2233  }
2234  else {
2235  row--; // adjust for index difference
2236  currentRow = row;
2237  This_Row = (byte[][])Rows.elementAt(currentRow);
2238 
2239  return true;
2240  }
2241 }
2242 
2243 //___________________________________________________________________
2245 {
2246  // Moves the cursor a relative number of rows, either positive or
2247  // negative. Attempting to move beyond the first/last row in
2248  // the result set positions the cursor before/after the the
2249  // first/last row. Calling Relative(0) is valid, but does not
2250  // change the cursor position.
2251  //
2252  // Note: Calling Relative(1) is different from calling Next()
2253  // because is makes sense to call Next() when there is
2254  // no current row, for example, when the cursor is
2255  // positioned before the first row or after the last row
2256  // of the result set.
2257  // Returns:
2258  // pointer to TSQLRow(kTRUE) if the cursor is on a row;
2259  // null(kFALSE) otherwise
2260  // Throws:
2261  // TSQLException - if a database access error occurs,
2262  // there is no current row, or the result set type
2263  // is kTYPE_FORWARD_ONLY
2264 
2265  int new_row_position = currentRow + rows + 1;
2266 }
2267 
2268 //___________________________________________________________________
2270 {
2271  // Moves the cursor to the previous row in the result set.
2272  //
2273  // Note: Previous() is not the same as Relative(-1)
2274  // because it makes sense to call Previous()
2275  // when there is no current row.
2276  //
2277  // Returns:
2278  // pointer to TSQLRow(kTRUE) if the cursor is on a valid row;
2279  // null(kFALSE) if it is off the result set
2280  // Throws:
2281  // TSQLException - if a database access error occurs or
2282  // the result set type is kTYPE_FORWARD_ONLY
2283 
2284  Bool_t return_value = kFALSE;
2285 
2286  return return_value ? fRow->Set(this) : 0;
2287 }
2288 
2289 //___________________________________________________________________
2291 {
2292  // Moves the cursor to the last row in the result set.
2293  //
2294  // Returns:
2295  // pointer to TSQLRow(kTRUE) if the cursor is on a valid row;
2296  // null(kFALSE) if there are norows in the result set
2297  //
2298  // Throws:
2299  // TSQLException - if a database access error occurs or
2300  // the result set type is kTYPE_FORWARD_ONLY
2301 
2302  Bool_t return_value = kFALSE;
2303  return return_value ? fRow->Set(this) : 0;
2304 }
2305 
2306 //___________________________________________________________________
2308 {
2309  // Get number of fields(aka columns) in result.
2310 
2312  return imp->fMYSQL_RES->field_count;
2313 }
2314 
2315 //___________________________________________________________________
2317 {
2318  // Get name of specified field( aka column ).
2319 
2321 
2322  if( (column > imp->fMYSQL_RES->field_count) || (column < 1) ) {
2323  return (set_stmt_error(stmt,"S1002","Invalid column number",0));
2324  return "";
2325  }
2326 
2327  return imp->MYSQL_RES->fields[column-1].name;
2328 }
2329 
2330 //___________________________________________________________________
2331 void TSQLResultSet::Close(Option_t *option)
2332 {
2333  // Releases this TSQLResultSet object's database and resources
2334  // immediately instead of waiting for this to happen when it is
2335  // automatically closed.
2336  //
2337  // Note: A TSQLResultSet is automatically closed by the
2338  // statement that generated it when that statement
2339  // is closed, re-executed, or is used to retrieve the next
2340  // result from a sequence of multiple results. A TSQLResultSet
2341  // is also automatically closed when it is garbage collected.
2342  //
2343  // Throws:
2344  // TSQLException - if a database access error occurs
2345 
2346 
2347  fMetaData = 0;
2348  fRow = 0;
2349  fImp = 0;
2350  Destroyed();
2351 }
2352 
2354 //___________________________________________________________________
2355 Int_t GetValueFromOption(const TString& pattern,const TString& option)
2356 {
2357  // internal use func.
2358 
2359  Ssiz_t t1,t2;
2360  const char* tmp;
2361 
2362  TString stropt = option;
2363  stropt.ReplaceAll(" ",""); // strip blanks
2364  stropt.ToLower();
2365 
2366  t1 = stropt.Index(pattern.Data());
2367  t1 = t2 = stropt.Index("=",t1) + 1;
2368  TString str = stropt(t1,1024); //
2369  tmp = str.Data();
2370 
2371  for(int i=0;isdigit(tmp[i])!=0;i++) t2=i+1;
2372  str = stropt(t1,t2);
2373  return atoi(str.Data());
2374 }
2375 
2376 //___________________________________________________________________
2377 void TSQLResultSet::Print(Option_t *option)
2378 {
2379  // Print a resultset contents
2380  //
2381  // The following options are valid:
2382  //
2383  // begin=nnn - start print from #nnn'th row, for example Print("begin=100")
2384  // end=nnn - end print at #nnn'th row, for example Print("begin=100 end=1000")
2385  // nrows=nnn - print #nnn rows, for example Print("begin=100 nrows=1000")
2386 
2387  if(!fImp) {
2388  Warning("Print()","TSQLResultSet is destroyed\n");
2389  Throw(new TSQLException("TSQLResultSet is destroyed"));
2390  Destroyed();
2391  return;
2392  }
2393 
2394  TString colname;
2395  Int_t ds;
2396  Int_t dl;
2397  Int_t* nn;
2398  Int_t* pd1;
2399  Int_t pd2;
2400  TString str;
2401  Int_t save_row = GetRow();
2402  Int_t cur_row;
2403  Int_t nr = 0;
2404 
2405  Int_t srow = save_row; // start from srow, default is current
2406  Int_t nrows = -1; // -1 - stand for "all rows"
2407  Int_t erow = -1; // -1 - stand for "to the last row"
2408 
2409  TString stropt = option;
2410  stropt.ToLower();
2411 
2412  if(stropt.Contains("begin")) {
2413  srow = GetValueFromOption("begin",stropt);
2414  }
2415 
2416  if (stropt.Contains("end")) {
2417  erow = GetValueFromOption("end",stropt);
2418  }
2419 
2420  if (stropt.Contains("nrows")) {
2421  nrows = GetValueFromOption("nrows",stropt);
2422  }
2423 
2424  Int_t ncols = fMetaData->GetColumnCount();
2425 
2426  nn = new Int_t[ncols+1];
2427  pd1 = new Int_t[ncols+1];
2428 
2429  for(int i=1; i<ncols+1; i++) {
2430  colname = fMetaData->GetColumnName(i);
2431  ds = fMetaData->GetColumnDisplaySize(i)+2;
2432  dl = colname.Length() + 2;
2433  nn[i] = TMath::Max(dl,ds);
2434  pd1[i] = nn[i]-dl;
2435  }
2436 
2437  //
2438  for(int i=1; i<ncols+1; i++) {
2439  cout << "+"; cout.fill('-'); cout.width(nn[i]+1); cout << "+";
2440  } cout << endl;
2441 
2442  for(int i=1; i<ncols+1; i++) {
2443  colname = fMetaData->GetColumnName(i);
2444  cout << "| " << colname << " ";
2445  cout.fill(' '); cout.width(pd1[i]+1); cout << "|";
2446  } cout << endl;
2447 
2448  //
2449  for(int i=1; i<ncols+1; i++) {
2450  cout << "+"; cout.fill('-'); cout.width(nn[i]+1); cout << "+";
2451  } cout << endl;
2452 
2453  cur_row = GetRow();
2454 
2455  if(fStatement) {
2457  Absolute(srow-1);
2458  } else {
2459  if(srow>cur_row) {
2460  while ( Next() && cur_row+2 < srow) cur_row = GetRow();
2461  }
2462  }
2463  }
2464 
2465  static TStopwatch timer;
2466  timer.Start(kTRUE);
2467 
2468  nr = 0;
2469  cur_row = GetRow();
2470 
2471  while ( Next() ) {
2472 
2473  if(nrows > 0 && nr >= nrows) break;
2474  if(erow > 0 && cur_row >= erow ) break;
2475  nr++;
2476  cur_row = GetRow();
2477 
2478  for(int i=1; i<ncols+1; i++) {
2479  str = GetString(i);
2480  cout << "| " << str;
2481  pd2 = nn[i] - str.Length();
2482  cout.fill(' '); cout.width(pd2); cout << "|";
2483  } cout << endl;
2484  }
2485 
2486  for(int i=1; i<ncols+1; i++) {
2487  cout << "+"; cout.fill('-'); cout.width(nn[i]+1); cout << "+";
2488  } cout << endl;
2489 
2490  timer.Stop();
2491  Double_t rtime = timer.RealTime();
2492 // Double_t ctime = timer.CpuTime();
2493  cout << nr << " rows in set. ( Real time: " << rtime << " seconds )" << endl;
2494 
2495  if(fStatement) {
2497  Absolute(save_row);
2498  } else {
2499  Warning("Print","To set cursor to initial position -> re-execute Query.");
2500  }
2501  }
2502  delete [] nn;
2503  delete [] pd1;
2504 }
2505 
2506 //___________________________________________________________________
2507 TTree* TSQLResultSet::Tree(Int_t begin,Int_t end)
2508 {
2509  // Writes resultset content to ROOT tree
2510  //
2511  // This method creates "new TTree".
2512  // To avoid memory leakage it should be deleted if not used.
2513  //
2514  // See also TTree
2515  //
2516  // Comment: this method is experimental nad buggy
2517 
2518  TString leafList; // leaf description string
2519  TString clmname; // column name
2520 
2521  Int_t siz;
2522  Int_t ncollumns;
2523  char* buf;
2524  Int_t type,offset,prec;
2525  TString str;
2526  char tmpstr[40];
2527 
2528  Int_t intg;
2529  Short_t shrt;
2530  Float_t flt;
2531  Double_t dbl;
2532  Int_t yy, mm, dd, hh, mi, ss;
2533  UInt_t t;
2534  struct tm tp;
2535  Int_t save_row = GetRow();
2536  Int_t cur_row;
2537 
2538  Int_t srow = begin > 0 ? begin : save_row;
2539  Int_t erow = end > 0 ? end : -1;
2540  Int_t tmp;
2541 
2542  if(srow>erow) {
2543  tmp = erow;
2544  erow = srow;
2545  srow = tmp;
2546  }
2547 
2548  // calculate "leaf buffer" size
2549  //
2550  ncollumns = fMetaData->GetColumnCount();
2551 
2552  for( int i=1; i <= ncollumns; ++i ) {
2553  type = fMetaData->GetColumnType(i);
2554 
2555  switch( type ) {
2556  case kCHAR:
2557  case kVARCHAR:
2558  siz += fMetaData->GetPrecision(i)+1; // length + zero
2559  break;
2560  case kINTEGER:
2561  siz += sizeof(Int_t);
2562  break;
2563  case kDATE:
2564  case kTIME:
2565  case kTIMESTAMP:
2566  siz += sizeof(UInt_t);
2567  break;
2568  case kBIT:
2569  case kTINYINT:
2570  case kSMALLINT:
2571  siz += sizeof(Short_t);
2572  break;
2573  case kREAL:
2574  siz += sizeof(Float_t);
2575  break;
2576  case kLONGVARCHAR: // not resolved yet how to handle
2577  case kLONGVARBINARY:
2578  case kVARBINARY:
2579  break;
2580  case kBIGINT: // convert all these types to Double_t
2581  case kDECIMAL:
2582  case kNUMERIC:
2583  case kDOUBLE:
2584  case kFLOAT:
2585  default:
2586  siz += sizeof(Double_t);
2587  break;
2588  }
2589  }
2590 
2591  // determine leaf description string
2592  //
2593  for( int i=1; i <= ncollumns; ++i ) {
2594  type = fMetaData->GetColumnType(i);
2595  clmname = fMetaData->GetColumnName(i);
2596 
2597  switch( type ) {
2598  case kCHAR:
2599  case kVARCHAR:
2600  prec = fMetaData->GetPrecision(i)+1;
2601  sprintf(tmpstr,"[%d]",prec);
2602  leafList += clmname + tmpstr + "/C:"; //
2603  break;
2604  case kINTEGER:
2605  leafList += clmname + "/I:"; // signed integer
2606  break;
2607  case kDATE:
2608  case kTIME:
2609  case kTIMESTAMP:
2610  leafList += clmname + "/i:"; // unsigned integer ( time_t format )
2611  break;
2612  case kBIT:
2613  case kTINYINT:
2614  case kSMALLINT:
2615  leafList += clmname + "/S:"; // signed short
2616  break;
2617  case kREAL:
2618  leafList += clmname + "/F:"; // floating point
2619  break;
2620  case kLONGVARCHAR: // not resolved yet how to handle
2621  case kLONGVARBINARY:
2622  case kVARBINARY:
2623  break;
2624  case kBIGINT: // convert all these types to Double_t
2625  case kDECIMAL:
2626  case kNUMERIC:
2627  case kDOUBLE:
2628  case kFLOAT:
2629  default:
2630  leafList += clmname + "/D:"; // double
2631  break;
2632  }
2633  }
2634  if(!leafList.IsNull()) leafList.Resize(leafList.Length()-1); // cut off last ":"
2635 
2636  // Dinamically allocate "leaf buffer"
2637  //
2638  buf = new char[siz]; // buffer
2639 
2640  TString tblname = fMetaData->GetTableName(1);
2641 
2642  if(tblname.IsNull()) { // if table name unknown => generate "random name"
2643  tblname = "table";
2644  sprintf(tmpstr,"%d",gRandom->Integer(1000));
2645  tblname += tmpstr;
2646  }
2647 
2648  // Create a ROOT Tree
2649  //
2650  TTree* tree = new TTree(tblname.Data(),"Created by TSQLResultSet:Tree() method");
2651 
2652  tree->Branch(tblname.Data(),(void*)buf,leafList.Data());
2653 
2654  // skip to start
2655  cur_row = GetRow();
2656 
2657  if(fStatement) {
2659  Absolute(srow-1);
2660  } else {
2661  if(srow>cur_row) {
2662  while ( Next() && cur_row+2 < srow) cur_row = GetRow();
2663  }
2664  }
2665  }
2666  // tree filling
2667  //
2668  while( Next() ) { // iterate rows
2669  offset = 0;
2670 
2671  if(erow>0 && cur_row >= erow) break;
2672  cur_row = GetRow();
2673 
2674  for( int i=1; i <= ncollumns; ++i ) {
2675  type = fMetaData->GetColumnType(i);
2676 
2677  switch( type ) {
2678  case kCHAR:
2679  case kVARCHAR:
2680  siz = fMetaData->GetPrecision(i)+1;
2681  str = GetString(i);
2682  memcpy(&buf[offset],str.Data(),siz);
2683  break;
2684  case kINTEGER:
2685  siz = sizeof(Int_t);
2686  intg = GetInt(i);
2687  memcpy(&buf[offset],&intg,siz);
2688  break;
2689  case kBIT:
2690  case kTINYINT:
2691  case kSMALLINT:
2692  siz = sizeof(Short_t);
2693  shrt = GetShort(i);
2694  memcpy(&buf[offset],&shrt,siz);
2695  break;
2696  case kREAL:
2697  siz = sizeof(Float_t);
2698  dbl = GetFloat(i);
2699  memcpy(&buf[offset],&flt,siz);
2700  break;
2701  case kDATE: // convert all date-times into time_t
2702  case kTIME: // probably not working for kTIME
2703  case kTIMESTAMP:
2704  siz = sizeof(UInt_t);
2705  str = GetString(i);
2706  sscanf(str.Data(), "%d-%d-%d %d:%d:%d",
2707  &yy, &mm, &dd, &hh, &mi, &ss);
2708  tp.tm_year = yy-1900;
2709  tp.tm_mon = mm;
2710  tp.tm_mday = dd;
2711  tp.tm_hour = hh;
2712  tp.tm_min = mi;
2713  tp.tm_sec = ss;
2714  tp.tm_isdst = -1;
2715  t = (UInt_t)mktime(&tp);
2716  memcpy(&buf[offset],&t,siz);
2717  break;
2718  case kLONGVARCHAR: // not resolved how to handle
2719  case kLONGVARBINARY:
2720  case kVARBINARY:
2721  break;
2722  case kBIGINT: // convert all these types to Double_t
2723  case kDECIMAL:
2724  case kNUMERIC:
2725  case kDOUBLE:
2726  case kFLOAT:
2727  default:
2728  siz = sizeof(Double_t);
2729  dbl = GetDouble(i);
2730  memcpy(&buf[offset],&dbl,siz);
2731  break;
2732  }
2733  offset += siz;
2734  }
2735  tree->Fill();
2736  }
2737  delete buf;
2738 
2739  if(fStatement) {
2741  Absolute(save_row);
2742  } else {
2743  Warning("Print","To set cursor to initial position -> re-execute Query.");
2744  }
2745  }
2746  return tree;
2747 }