Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-03 08:22:05

0001 // $Id: ODBCResultSet.cxx,v 1.3 2007/02/28 21:33:40 phnxbld Exp $
0002 //*-- Author : Valeriy Onuchin 14/02/2000 
0003 //
0004 
0005 /**************************************************************************
0006 
0007    ROOT wrappers of libodbc++ library
0008     
0009    Copyright (C) 1999-2000 Manush Dodunekov <manush@stendahls.net>
0010    
0011    This library is free software; you can redistribute it and/or
0012    modify it under the terms of the GNU Library General Public
0013    License as published by the Free Software Foundation; either
0014    version 2 of the License, or (at your option) any later version.
0015    
0016    This library is distributed in the hope that it will be useful,
0017    but WITHOUT ANY WARRANTY; without even the implied warranty of
0018    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0019    Library General Public License for more details.
0020    
0021    You should have received a copy of the GNU Library General Public License
0022    along with this library; see the file COPYING.  If not, write to
0023    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
0024    Boston, MA 02111-1307, USA.
0025 
0026 **************************************************************************/
0027 
0028 //
0029 /////////////////////////////////////////////////////////////////////
0030 //
0031 // A TSQLResultSet provides access to a table of data. A 
0032 // TSQLResultSet object is usually generated by executing 
0033 // TSQLStatement. 
0034 //
0035 // A TSQLResultSet maintains a cursor pointing to its current row 
0036 // of data. Initially the cursor is positioned before the first
0037 // row. The Next() method moves the cursor to the next row. 
0038 //
0039 // The GetXXX methods retrieve column values for the current row.
0040 // You can retrieve values using either the index number of the 
0041 // column or the name of the column. In general,using the column 
0042 // index will be more efficient. Columns are numbered from 1. 
0043 //
0044 // For maximum portability, TSQLResultSet columns within each row
0045 // should be read in left-to-right order and each column should be 
0046 // read only once. 
0047 //
0048 // For the GetXXX methods, the driver attempts to convert the
0049 // underlying data to the specified ROOT type and returns a suitable 
0050 // value. See the specification for allowable mappings 
0051 // from SQL types to ROOT types with the ODBCResultSet::GetXXX 
0052 // methods. 
0053 //
0054 // Column names used as input to GetXXX methods are case
0055 // insensitive. When performing a GetXXX using a column name, 
0056 // if several columns have the same name, then the value of the 
0057 // first matching column will be returned. The column name option 
0058 // is designed to be used when column names are used in the SQL 
0059 // query. For columns that are NOT explicitly named in the query, 
0060 // it is best to use column numbers. If column names are used, there 
0061 // is no way for the programmer to guarantee that they actually refer 
0062 // to the intended columns. 
0063 //
0064 // A TSQLResultSet is automatically closed by the TSQLStatement that 
0065 // generated it when that TSQLStatement is closed, re-executed, 
0066 // or used  to retrieve the next result from a sequence of multiple 
0067 // results. 
0068 //
0069 // The number, types and properties of a TSQLResultSet's columns are
0070 // provided by the TSQLResulSetMetaData object returned by the 
0071 // GetMetaData() method. 
0072 //
0073 // See also: 
0074 //      TSQLStatement::ExecuteQuery(const TString&),
0075 //      TSQLStatement::GetResultSet(), TSQLResultSetMetaData
0076 //
0077 //___________________________________________________________________
0078 //
0079 //       kCONCUR_READ_ONLY 
0080 //
0081 // The concurrency mode for a TSQLResultSet object that may 
0082 // NOT be updated.
0083 //___________________________________________________________________
0084 //
0085 //       kCONCUR_UPDATABLE 
0086 //
0087 //  The concurrency mode for a TSQLResultSet
0088 //  object that may be updated.
0089 //___________________________________________________________________
0090 //
0091 //       kFETCH_FORWARD 
0092 //
0093 // The rows in a result set will be
0094 // processed in a forward direction; first-to-last.
0095 //___________________________________________________________________
0096 //
0097 //       kFETCH_REVERSE 
0098 //
0099 // The rows in a result set will be
0100 // processed in a reverse direction; last-to-first.
0101 //___________________________________________________________________
0102 //
0103 //       kFETCH_UNKNOWN 
0104 //
0105 // The order in which rows in a result set
0106 // will be processed is unknown.
0107 //___________________________________________________________________
0108 //
0109 //       kTYPE_FORWARD_ONLY 
0110 //
0111 // The type for a TSQLResultSet object whose
0112 // cursor may move only forward.
0113 //___________________________________________________________________
0114 //
0115 //       kTYPE_SCROLL_INSENSITIVE 
0116 //
0117 // The type for a TSQLResultSet object that is
0118 // scrollable but generally not sensitive to changes made by
0119 // others.
0120 //___________________________________________________________________
0121 //
0122 //       kTYPE_SCROLL_SENSITIVE 
0123 // 
0124 // The type for a TSQLResultSet object that is
0125 // scrollable and generally sensitive to changes made by
0126 // others.
0127 //
0128 /////////////////////////////////////////////////////////////////////
0129  
0130 #include <ODBCResultSet.h>
0131 #include <ODBCResultSetMetaData.h>
0132 #include <ODBCStatement.h>
0133 #include <TList.h>
0134 #include <TMath.h>
0135 #include <TStopwatch.h>
0136 #include <TBuffer.h>
0137 #include <TTree.h>
0138 #include <TRandom.h>
0139 #include <TBranch.h>
0140 #include <RDBC/odbc++/resultset.h>
0141 #include <RDBC/odbc++/resultsetmetadata.h>
0142 #include <iostream>
0143 #include <sstream>
0144 #include <ctype.h>
0145 #include <time.h>
0146 #include <TSQLRow.h>
0147 
0148 #if ROOT_VERSION_CODE >= ROOT_VERSION(5,15,0)
0149 #include <TBufferFile.h>
0150 #endif
0151 
0152 using namespace odbc;
0153 using namespace std;
0154 
0155 ClassImpQ(ODBCResultSet)
0156 
0157 /////////////////////////////////////////////////////////////////////
0158 class RDBCRow: public TSQLRow
0159 {
0160 friend  class ODBCResultSet;
0161 
0162 private:
0163    TSQLResultSet* fResultSet; // parent result set
0164    RDBCRow(TSQLResultSet *result=0) { fResultSet=result; }
0165    RDBCRow* Set(TSQLResultSet *result) { fResultSet=result; return this; }
0166    virtual ~RDBCRow() {  fResultSet = 0; }
0167    TString fField;  // selected field
0168 
0169 public:
0170    void        Close(Option_t* /* opt="" */) { fResultSet = 0; }
0171    ULong_t     GetFieldLength(Int_t field) { return fResultSet ? fResultSet->GetMetaData()->GetColumnDisplaySize(field-1) : 0; }
0172    const char* GetField(Int_t field) { fField = fResultSet ? fResultSet->GetString(field-1).Data() : ""; return fField.Data(); }
0173 }; 
0174 
0175 /////////////////////////////////////////////////////////////////////
0176 //___________________________________________________________________
0177 ODBCResultSet::ODBCResultSet(TSQLStatement* stmt,void* imp):
0178    TSQLResultSet(stmt,imp)
0179 {
0180    // ctor
0181    
0182    fStatement = stmt;
0183    odbc::ResultSet* rs = (odbc::ResultSet*)imp;
0184    fImp = rs;
0185    fRow = new RDBCRow(this);
0186    
0187    try {
0188       odbc::ResultSetMetaData* mdimp = rs->getMetaData();
0189       fMetaData = new ODBCResultSetMetaData(this,mdimp);    
0190 
0191    } catch(odbc::SQLException& e) {
0192       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0193                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0194                                 e.getErrorCode()) );
0195    }
0196 }                             
0197 
0198 //___________________________________________________________________
0199 ODBCResultSet::~ODBCResultSet()
0200 {
0201    // destructor. 
0202 
0203    odbc::ResultSet* imp = (odbc::ResultSet*)fImp;  
0204 
0205    try {
0206       if(imp) delete imp; 
0207    } catch(odbc::SQLException& e) {
0208       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0209                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0210                                 e.getErrorCode()) );
0211    }
0212 
0213    fImp = 0; 
0214    
0215    if(fMetaData) delete ((ODBCResultSetMetaData*)fMetaData);
0216    if(fRow) delete fRow;
0217    
0218    ODBCStatement* stmt = (ODBCStatement*)fStatement;
0219    if(stmt->fCurrentResult==this) stmt->fCurrentResult = 0;
0220 
0221    fMetaData = 0;
0222    fRow = 0;
0223 }
0224 
0225 //___________________________________________________________________
0226 Bool_t ODBCResultSet::WasNull()
0227 {
0228    // Reports whether the last column read had a value of SQL NULL. 
0229    // Note that you must first call GetXXX on a column to try to 
0230    // read its value and then call WasNull() to see if the value 
0231    // read was SQL NULL.
0232    //
0233    // Returns:
0234    //       kTRUE if last column read was SQL NULL and 
0235    //       kFALSE - otherwise
0236    //  Throws:
0237    //       TSQLException - if a database access error occurs
0238  
0239    Bool_t return_value = kFALSE;
0240    
0241    if(!fImp) { Destroyed(); return return_value; }
0242    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
0243    
0244    try {
0245       return_value = rs->wasNull();
0246 
0247    } catch(odbc::SQLException& e) {
0248       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0249                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0250                                 e.getErrorCode()) );
0251       return_value = kFALSE;
0252    }
0253    return return_value;
0254 }
0255 
0256 //___________________________________________________________________
0257 TString ODBCResultSet::GetString( Int_t columnIndex )
0258 {
0259    // Gets the value of a column in the current row as a TString.
0260    //
0261    //  Parameters:
0262    //       columnIndex - the first column is 1, the second is 2, ...
0263    //  Returns:
0264    //       the column value; if the value is SQL NULL, the result 
0265    //       is null
0266    //  Throws:
0267    //       TSQLException - if a database access error occurs
0268 
0269    TString str;
0270    
0271    if(!fImp) { Destroyed(); return str; }
0272    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
0273       
0274    try {
0275       str = ODBCXX_STRING_CSTR( rs->getString(columnIndex) );  
0276 
0277    } catch(odbc::SQLException& e) {
0278       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0279                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0280                                 e.getErrorCode()) );
0281       return ""; 
0282    }
0283    return str;
0284 }
0285 
0286 //___________________________________________________________________
0287 Bool_t ODBCResultSet::GetBoolean( Int_t columnIndex )
0288 {
0289    // Gets the value of a column in the current row as a boolean.
0290    //
0291    //  Parameters:
0292    //       columnIndex - the first column is 1, the second is 2, ...
0293    //  Returns:
0294    //       the column value; if the value is SQL NULL, the result is
0295    //       kFALSE
0296    //  Throws:
0297    //       TSQLException - if a database access error occurs
0298 
0299    Bool_t return_value = kFALSE;
0300    
0301    if(!fImp) { Destroyed(); return return_value; }
0302    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
0303    
0304    try {    
0305       return_value =  rs->getBoolean(columnIndex);
0306    
0307    } catch(odbc::SQLException& e) {
0308       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0309                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0310                                 e.getErrorCode()) );
0311       return_value = kFALSE;
0312    }
0313    return return_value;
0314 }
0315 
0316 //___________________________________________________________________
0317 Char_t ODBCResultSet::GetByte( Int_t columnIndex )
0318 {
0319    // Gets the value of a column in the current row as a byte.
0320    //
0321    //  Parameters:
0322    //       columnIndex - the first column is 1, the second is 2, ...
0323    //  Returns:
0324    //       the column value; if the value is SQL NULL, 
0325    //       the result is 0
0326    //  Throws:
0327    //       TSQLException - if a database access error occurs
0328 
0329    Char_t return_value = 0;
0330    
0331    if(!fImp) { Destroyed(); return return_value; }
0332    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
0333    
0334    try {      
0335       return_value =  rs->getByte(columnIndex);
0336       
0337    } catch(odbc::SQLException& e) {
0338       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0339                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0340                                 e.getErrorCode()) );
0341       return_value = 0;
0342    }
0343    return return_value;   
0344 }
0345 
0346 //___________________________________________________________________
0347 Short_t ODBCResultSet::GetShort( Int_t columnIndex )
0348 {
0349    // Gets the value of a column in the current row as a Short_t.
0350    //
0351    //  Parameters:
0352    //       columnIndex - the first column is 1, the second is 2, ...
0353    //  Returns:
0354    //       the column value; if the value is SQL NULL, 
0355    //       the result is 0
0356    //  Throws:
0357    //       TSQLException - if a database access error occurs
0358 
0359    Short_t return_value = 0;
0360    
0361    if(!fImp) { Destroyed(); return return_value; }
0362    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
0363    
0364    try {      
0365       return_value = rs->getShort(columnIndex);
0366 
0367    } catch(odbc::SQLException& e) {
0368       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0369                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0370                                 e.getErrorCode()) );
0371       return_value = 0;
0372    }
0373    return return_value;
0374 }
0375 
0376 //___________________________________________________________________
0377 Int_t ODBCResultSet::GetInt( Int_t columnIndex )
0378 {
0379    // Gets the value of a column in the current row as a Int_t.
0380    //
0381    //  Parameters:
0382    //       columnIndex - the first column is 1, the second is 2, ...
0383    //  Returns:
0384    //       the column value; if the value is SQL NULL, 
0385    //       the result is 0
0386    //  Throws:
0387    //       TSQLException - if a database access error occurs
0388 
0389    Int_t return_value = 0;
0390    
0391    if(!fImp) { Destroyed(); return return_value; }
0392    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
0393    
0394    try {      
0395       return_value = rs->getInt(columnIndex);
0396 
0397    } catch(odbc::SQLException& e) {
0398       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0399                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0400                                 e.getErrorCode()) );
0401       return_value = 0;
0402    }
0403    return return_value;
0404 }
0405 
0406 //___________________________________________________________________
0407 Long_t ODBCResultSet::GetLong( Int_t columnIndex )
0408 {
0409    // Gets the value of a column in the current row as a Long_t.
0410    //
0411    //  Parameters:
0412    //       columnIndex - the first column is 1, the second is 2, ...
0413    //  Returns:
0414    //       the column value; if the value is SQL NULL, 
0415    //       the result is 0
0416    //  Throws:
0417    //       TSQLException - if a database access error occurs
0418 
0419    Long_t return_value = 0;
0420    
0421    if(!fImp) { Destroyed(); return return_value; }
0422    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
0423    
0424    try {      
0425       return_value = rs->getLong(columnIndex);
0426 
0427    } catch(odbc::SQLException& e) {
0428       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0429                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0430                                 e.getErrorCode()) );
0431       return_value = 0;
0432    }
0433    return return_value;
0434 }
0435 
0436 //___________________________________________________________________
0437 Float_t ODBCResultSet::GetFloat( Int_t columnIndex )
0438 {
0439    // Gets the value of a column in the current row as a Float_t.
0440    //
0441    //  Parameters:
0442    //       columnIndex - the first column is 1, the second is 2, ...
0443    //  Returns:
0444    //       the column value; if the value is SQL NULL, 
0445    //       the result is 0
0446    //  Throws:
0447    //       TSQLException - if a database access error occurs
0448    
0449    Float_t return_value = 0;
0450    
0451    if(!fImp) { Destroyed(); return return_value; }
0452    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
0453       
0454    try {      
0455       return_value = rs->getFloat(columnIndex);
0456 
0457    } catch(odbc::SQLException& e) {
0458       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0459                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0460                                 e.getErrorCode()) );
0461       return_value = 0;
0462    }
0463    return return_value;
0464 }
0465 
0466 //___________________________________________________________________
0467 Double_t ODBCResultSet::GetDouble( Int_t columnIndex )
0468 {
0469    // Gets the value of a column in the current row as a Double_t.
0470    //
0471    //  Parameters:
0472    //       columnIndex - the first column is 1, the second is 2, ...
0473    //  Returns:
0474    //       the column value; if the value is SQL NULL, 
0475    //       the result is 0
0476    //  Throws:
0477    //       TSQLException - if a database access error occurs
0478    
0479    Double_t return_value = 0;
0480    
0481    if(!fImp) { Destroyed(); return return_value; }
0482    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
0483       
0484    try {      
0485       return_value = rs->getDouble(columnIndex);
0486 
0487    } catch(odbc::SQLException& e) {
0488       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0489                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0490                                 e.getErrorCode()) );
0491       return_value = 0;
0492    }
0493    return return_value;
0494 }
0495 
0496 //___________________________________________________________________
0497 TArrayC ODBCResultSet::GetBytes( Int_t columnIndex )
0498 {
0499    // Gets the value of a column in the current row as a char array.
0500    // The chars represent the raw values returned by the driver.
0501    //
0502    //  Parameters:
0503    //       columnIndex - the first column is 1, the second is 2, ...
0504    //  Returns:
0505    //       the column value; if the value is SQL NULL, 
0506    //       the result is null
0507    //  Throws:
0508    //       TSQLException - if a database access error occurs
0509  
0510    TArrayC array;
0511    
0512    if(!fImp) { Destroyed(); return array; }
0513    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
0514    
0515    try {           
0516       ODBCXX_BYTES b = rs->getBytes(columnIndex);
0517       
0518       array.Set( (Int_t)ODBCXX_BYTES_SIZE(b),
0519                  (Char_t*)ODBCXX_BYTES_DATA(b) );
0520 
0521    } catch(odbc::SQLException& e) {
0522       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0523                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0524                                 e.getErrorCode()) );
0525    }
0526    return array;
0527 }
0528 
0529 //___________________________________________________________________
0530 TSQLDate ODBCResultSet::GetDate( Int_t columnIndex )
0531 {
0532    // Gets the value of a column in the current row as a TSQLDate
0533    // object.
0534    //
0535    //  Parameters:
0536    //       columnIndex - the first column is 1, the second is 2, ...
0537    //  Returns:
0538    //       the column value; if the value is SQL NULL, 
0539    //       the result is null
0540    //  Throws:
0541    //       TSQLException - if a database access error occurs
0542 
0543    TSQLDate return_value;
0544    
0545    if(!fImp) { Destroyed(); return return_value; }
0546    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
0547    
0548    try {
0549       odbc::Date dt = rs->getDate(columnIndex);
0550       return_value = TSQLDate( dt.getYear(),
0551                                dt.getMonth(),
0552                                dt.getDay() );
0553 
0554    } catch(odbc::SQLException& e) {
0555       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0556                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0557                                 e.getErrorCode()) );
0558    }
0559    return return_value;
0560 }
0561 
0562 //___________________________________________________________________
0563 TSQLTime ODBCResultSet::GetTime( Int_t columnIndex )
0564 {
0565    // Gets the value of a column in the current row as a TSQLTime
0566    // object.
0567    //
0568    // Parameters:
0569    //       columnIndex - the first column is 1, the second is 2, ...
0570    //  Returns:
0571    //       the column value; if the value is SQL NULL, 
0572    //       the result is null
0573    //  Throws:
0574    //       TSQLException - if a database access error occurs
0575 
0576    TSQLTime return_value;
0577    
0578    if(!fImp) { Destroyed(); return return_value; }
0579    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
0580    
0581    try {
0582       odbc::Time tm = rs->getTime(columnIndex);
0583 
0584       return_value = TSQLTime( tm.getHour(),
0585                                tm.getMinute(),
0586                                tm.getSecond() );
0587 
0588    } catch(odbc::SQLException& e) {
0589       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0590                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0591                                 e.getErrorCode()) );
0592    }
0593    return return_value;
0594 }
0595 
0596 //___________________________________________________________________
0597 TSQLTimestamp ODBCResultSet::GetTimestamp( Int_t columnIndex )
0598 {
0599    // Gets the value of a column in the current row as a
0600    // TSQLTimestamp object.
0601    //
0602    //  Parameters:
0603    //       columnIndex - the first column is 1, the second is 2, ...
0604    //  Returns:
0605    //       the column value; if the value is SQL NULL, 
0606    //       the result is null
0607    //  Throws:
0608    //       TSQLException - if a database access error occurs
0609 
0610    TSQLTimestamp return_value;
0611    
0612    if(!fImp) { Destroyed(); return return_value; }
0613    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
0614    
0615    try {
0616       odbc::Timestamp tmstmp = rs->getTimestamp(columnIndex);
0617       return_value = TSQLTimestamp( tmstmp.getYear(),
0618                                     tmstmp.getMonth(),
0619                                     tmstmp.getDay(), 
0620                                     tmstmp.getHour(),
0621                                     tmstmp.getMinute(),
0622                                     tmstmp.getSecond(),
0623                                     tmstmp.getNanos() );
0624 
0625    } catch(odbc::SQLException& e) {
0626       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0627                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0628                                 e.getErrorCode()) );
0629    }
0630    return return_value;
0631 }
0632 
0633 //___________________________________________________________________
0634 TBuffer* ODBCResultSet::GetAsciiStream( Int_t columnIndex )
0635 {
0636    // Gets the value of a column in the current row as a stream 
0637    // of ASCII characters. The value can then be read in chunks from 
0638    // the stream. This method is particularly suitable for 
0639    // retrieving large LONGVARCHAR values. The driver will do 
0640    // any necessary conversion from the database format into ASCII. 
0641    //
0642    //  Note: All the data in the returned stream must be read prior 
0643    //    to getting the value of any other column. The next call to 
0644    //    a get method implicitly closes the stream. Also, a stream 
0645    //    may return 0 when the method available is called whether 
0646    //    there is data available or not.
0647    //
0648    //  Parameters:
0649    //       columnIndex - the first column is 1, the second is 2, ...
0650    //  Returns:
0651    //       A TBuffer that delivers the database column 
0652    //       value as a stream of one char ASCII characters. 
0653    //       If the value is SQL NULL then the result is null.
0654    //
0655    //  Throws:
0656    //       TSQLException - if a database access error occurs
0657 
0658    TBuffer* buffer = 0;
0659 
0660    if(!fImp) { Destroyed(); return buffer; }
0661    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
0662    
0663    try {   
0664       ODBCXX_STREAM* rsStream = rs->getAsciiStream(columnIndex);
0665       Int_t bufsiz = rsStream->rdbuf()->in_avail();
0666       if(bufsiz<=0) return 0;
0667 #if ROOT_VERSION_CODE >= ROOT_VERSION(5,15,0)
0668       buffer  = new TBufferFile(TBuffer::kWrite, bufsiz); 
0669 #else
0670       buffer  = new TBuffer(TBuffer::kWrite, bufsiz); 
0671 #endif
0672       int c;
0673       while ((c = rsStream->get()) != EOF)
0674     {
0675       *buffer << (char) c;
0676     }
0677       buffer->SetBufferOffset();
0678       buffer->SetReadMode();
0679    } catch(odbc::SQLException& e) {
0680       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0681                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0682                                 e.getErrorCode()) );
0683       buffer = 0;
0684    }
0685    return buffer;
0686 }
0687 
0688 //___________________________________________________________________
0689 TBuffer* ODBCResultSet::GetBinaryStream( Int_t columnIndex )
0690 {
0691    // Gets the value of a column in the current row as a stream of
0692    // uninterpreted chars. The value can then be read in chunks 
0693    // from the stream. This method is particularly suitable for
0694    //  retrieving large LONGVARBINARY values. 
0695    //
0696    //  Note: All the data in the returned stream must be read 
0697    //    prior to getting the value of any other column. The next 
0698    //    call to a Get method implicitly closes the stream. Also, 
0699    //    a stream may return 0 when the method available is called 
0700    //    whether there is data available or not.
0701    //
0702    //  Parameters:
0703    //       columnIndex - the first column is 1, the second is 2, ...
0704    //  Returns:
0705    //       TBuffer that delivers the database column 
0706    //       value as a stream of uninterpreted chars. If the value 
0707    //       is SQL NULL then the result is null.
0708    //  Throws:
0709    //       TSQLException - if a database access error occurs
0710 
0711    TBuffer* buffer = 0;
0712 
0713    if(!fImp) { Destroyed(); return buffer; }
0714    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
0715    
0716    try {   
0717       ODBCXX_STREAM* rsStream = rs->getBinaryStream(columnIndex);
0718       Int_t bufsiz = rsStream->rdbuf()->in_avail();
0719       if(bufsiz<=0) return 0;
0720 #if ROOT_VERSION_CODE >= ROOT_VERSION(5,15,0)
0721       buffer  = new TBufferFile(TBuffer::kWrite, bufsiz); 
0722 #else
0723       buffer  = new TBuffer(TBuffer::kWrite, bufsiz); 
0724 #endif
0725       int c;
0726       while ((c = rsStream->get()) != EOF)
0727     {
0728       *buffer << (char) c;
0729     }
0730       buffer->SetBufferOffset();
0731       buffer->SetReadMode();
0732    } catch(odbc::SQLException& e) {
0733       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0734                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0735                                 e.getErrorCode()) );
0736       buffer = 0;
0737    }
0738    return buffer;
0739 }
0740 
0741 //___________________________________________________________________
0742 TObject* ODBCResultSet::GetObject( Int_t columnIndex )
0743 {
0744    // Gets the value of a column in the current row as ROOT object.
0745    //
0746    //  Parameters:
0747    //       columnIndex - the first column is 1, the second is 2, ...
0748    //  Returns:
0749    //       TObject 
0750    //  Throws:
0751    //       TSQLException - if a database access error occurs
0752    
0753    TObject* obj =0;
0754 
0755    TBuffer *b = GetBinaryStream(columnIndex);
0756    obj = (TObject *)b->ReadObjectAny(TObject::Class()); 
0757    // Laurent found that this causes a memory leak, Valeriy Onuchin never responded to this
0758    // b->DetachBuffer();
0759    delete b; 
0760    return obj;
0761 }
0762 
0763 //___________________________________________________________________
0764 TString ODBCResultSet::GetString( const TString& columnName )
0765 {
0766    // Gets the value of a column in the current row as a TString.
0767    //
0768    //  Parameters:
0769    //       columnName - the SQL name of the column
0770    //  Returns:
0771    //       the column value; if the value is SQL NULL, 
0772    //       the result is null
0773    //  Throws:
0774    //       TSQLException - if a database access error occurs
0775 
0776    return GetString(FindColumn(columnName));
0777 }
0778 
0779 //___________________________________________________________________
0780 Bool_t ODBCResultSet::GetBoolean( const TString& columnName )
0781 {
0782    // Gets the value of a column in the current row as a boolean.
0783    //
0784    //  Parameters:
0785    //       columnName - the SQL name of the column
0786    //  Returns:
0787    //       the column value; if the value is SQL NULL, 
0788    //       the result is kFALSE
0789    //  Throws:
0790    //       TSQLException - if a database access error occurs
0791 
0792    return GetBoolean(FindColumn(columnName));
0793 }
0794 
0795 //___________________________________________________________________
0796 Char_t ODBCResultSet::GetByte( const TString& columnName )
0797 {
0798    // Gets the value of a column in the current row as a Char_t.
0799    //
0800    //  Parameters:
0801    //       columnName - the SQL name of the column
0802    //  Returns:
0803    //       the column value; if the value is SQL NULL, 
0804    //       the result is 0
0805    //  Throws:
0806    //       TSQLException - if a database access error occurs
0807 
0808    return GetByte(FindColumn(columnName));
0809 }
0810 
0811 //___________________________________________________________________
0812 Short_t ODBCResultSet::GetShort( const TString& columnName )
0813 {
0814     // Gets the value of a column in the current row as a Short_t.
0815     // 
0816     // Parameters:
0817     //      columnName - the SQL name of the column
0818     // Returns:
0819     //      the column value; if the value is SQL NULL, 
0820     //      the result is 0
0821     // Throws:
0822     //      TSQLException - if a database access error occurs
0823 
0824    return GetShort(FindColumn(columnName));
0825 }
0826 
0827 //___________________________________________________________________
0828 Int_t ODBCResultSet::GetInt( const TString& columnName )
0829 {
0830    // Gets the value of a column in the current row as a Int_t.
0831    //
0832    //  Parameters:
0833    //       columnName - the SQL name of the column
0834    //  Returns:
0835    //       the column value; if the value is SQL NULL, 
0836    //       the result is 0
0837    //  Throws:
0838    //       TSQLException - if a database access error occurs
0839 
0840    return GetInt(FindColumn(columnName));
0841 }
0842 
0843 //___________________________________________________________________
0844 Long_t ODBCResultSet::GetLong( const TString& columnName )
0845 {
0846    // Gets the value of a column in the current row as a Long_t.
0847    //
0848    //  Parameters:
0849    //       columnName - the SQL name of the column
0850    //  Returns:
0851    //       the column value; if the value is SQL NULL,
0852    //       the result is 0
0853    //  Throws:
0854    //       TSQLException - if a database access error occurs
0855 
0856    return GetLong(FindColumn(columnName));
0857 }
0858 
0859 //___________________________________________________________________
0860 Float_t ODBCResultSet::GetFloat( const TString& columnName )
0861 {
0862    // Gets the value of a column in the current row as a Float_t.
0863    //
0864    //  Parameters:
0865    //       columnName - the SQL name of the column
0866    //  Returns:
0867    //       the column value; if the value is SQL NULL, 
0868    //       the result is 0
0869    //  Throws:
0870    //       TSQLException - if a database access error occurs
0871 
0872    return GetFloat(FindColumn(columnName));
0873 }
0874 
0875 //___________________________________________________________________
0876 Double_t ODBCResultSet::GetDouble( const TString& columnName )
0877 {
0878    // Gets the value of a column in the current row as a Double_t.
0879    //
0880    //  Parameters:
0881    //       columnName - the SQL name of the column
0882    //  Returns:
0883    //       the column value; if the value is SQL NULL, 
0884    //       the result is 0
0885    //  Throws:
0886    //       TSQLException - if a database access error occurs
0887 
0888    return GetDouble(FindColumn(columnName));
0889 }
0890 
0891 //___________________________________________________________________
0892 TArrayC ODBCResultSet::GetBytes( const TString& columnName )
0893 {
0894    // Gets the value of a column in the current row as a char
0895    // array. The chars represent the raw values returned by the 
0896    // driver.
0897    //
0898    //  Parameters:
0899    //       columnName - the SQL name of the column
0900    //  Returns:
0901    //       the column value; if the value is SQL NULL, 
0902    //       the result is null
0903    //  Throws:
0904    //       TSQLException - if a database access error occurs
0905 
0906    return GetBytes(FindColumn(columnName));
0907 }
0908 
0909 //___________________________________________________________________
0910 TSQLDate ODBCResultSet::GetDate( const TString& columnName )
0911 {
0912    // Gets the value of a column in the current row as a TSQLDate
0913    //  object.
0914    // 
0915    //  Parameters:
0916    //       columnName - the SQL name of the column
0917    //  Returns:
0918    //       the column value; if the value is SQL NULL, 
0919    //       the result is null
0920    //  Throws:
0921    //       TSQLException - if a database access error occurs
0922    
0923    return GetDate(FindColumn(columnName));
0924 }
0925 
0926 //___________________________________________________________________
0927 TSQLTime ODBCResultSet::GetTime( const TString& columnName )
0928 {
0929   // Gets the value of a column in the current row as a TSQLTime
0930   // object.
0931   //
0932   //   Parameters:
0933   //        columnName - the SQL name of the column
0934   //   Returns:
0935   //        the column value; if the value is SQL NULL,
0936   //        the result is null
0937   //   Throws:
0938   //        TSQLException - if a database access error occurs
0939 
0940   return GetTime(FindColumn(columnName)); 
0941 }
0942 
0943 //___________________________________________________________________
0944 TSQLTimestamp ODBCResultSet::GetTimestamp( const TString& columnName )
0945 {
0946    // Gets the value of a column in the current row as a
0947    // TSQLTimestamp object.
0948    //
0949    //  Parameters:
0950    //       columnName - the SQL name of the column
0951    //  Returns:
0952    //       the column value; if the value is SQL NULL, 
0953    //       the result is null
0954    //  Throws:
0955    //       TSQLException - if a database access error occurs
0956 
0957    return GetTimestamp(FindColumn(columnName));
0958 }
0959 
0960 //___________________________________________________________________
0961 TBuffer* ODBCResultSet::GetAsciiStream( const TString& columnName )
0962 {
0963    // Gets the value of a column in the current row as a stream 
0964    // of ASCII characters. The value can then be read in chunks 
0965    // from the stream. This method is particularly suitable for 
0966    // retrieving large LONGVARCHAR values. The driver will do 
0967    // any necessary conversion from the database format into ASCII. 
0968    //
0969    //  Note: All the data in the returned stream must be read prior
0970    //    to getting the value of any other column. The next call to
0971    //    a  Get method implicitly closes the stream. Also, a stream 
0972    //    may return 0 when the method available is called whether 
0973    //    there is data available or not.
0974    //
0975    //  Parameters:
0976    //       columnName - the SQL name of the column
0977    //  Returns:
0978    //       TBuffer that delivers the database column 
0979    //       value as a stream of one char ASCII characters. If 
0980    //       the value is SQL NULL then the result is null.
0981    //  Throws:
0982    //       TSQLException - if a database access error occurs
0983 
0984    return GetAsciiStream(FindColumn(columnName));
0985 }
0986 
0987 //___________________________________________________________________
0988 TBuffer* ODBCResultSet::GetBinaryStream( const TString& columnName )
0989 {
0990    // Gets the value of a column in the current row as a stream of
0991    // uninterpreted chars. The value can then be read in chunks 
0992    // from the stream. This method is particularly suitable for
0993    // retrieving large LONGVARBINARY values. The driver will 
0994    // do any necessary conversion from the database format into 
0995    // uninterpreted chars. 
0996    //
0997    //  Note: All the data in the returned stream must be read 
0998    //    prior to getting the value of any other column. The next 
0999    //    call to a Get method implicitly closes the stream. Also, 
1000    //    a stream may return 0 when the method available is called 
1001    //    whether there is data available or not.
1002    //
1003    //  Parameters:
1004    //       columnName - the SQL name of the column
1005    //  Returns:
1006    //       TBuffer that delivers the database column 
1007    //       value as a stream of uninterpreted chars. If the value 
1008    //       is SQL NULL then the result is null.
1009    //  Throws:
1010    //       TSQLException - if a database access error occurs
1011 
1012    return GetBinaryStream(FindColumn(columnName));
1013 }
1014 
1015 //___________________________________________________________________
1016 TObject* ODBCResultSet::GetObject( const TString& columnName )
1017 {
1018    // Gets the value of a column in the current row as ROOT object.
1019    //
1020    //  Parameters:
1021    //       columnIndex - the first column is 1, the second is 2, ...
1022    //  Returns:
1023    //       TObject 
1024    //  Throws:
1025    //       TSQLException - if a database access error occurs
1026    
1027    return GetObject(FindColumn(columnName));
1028 }
1029 
1030 //___________________________________________________________________
1031 TString ODBCResultSet::GetCursorName()
1032 {
1033    // Gets the name of the SQL cursor used by this TSQLResultSet. 
1034    //
1035    // In SQL, a result table is retrieved through a cursor that 
1036    // is named. The current row of a result can be updated or 
1037    // deleted using a positioned Update/Delete statement that 
1038    // references the cursor name. To insure that the cursor has 
1039    // the proper isolation level to support update, the cursor's 
1040    // select statement should be of the form 'SELECT FOR UPDATE'. 
1041    // If the 'FOR UPDATE' clause is omitted the positioned 
1042    // updates may fail. 
1043    //    The current row of a TSQLResultSet is also the current row 
1044    // of this SQL cursor. 
1045    //
1046    //  Note: If positioned update is not supported a 
1047    //       SQLException is thrown
1048    //  Returns:
1049    //       the TSQLResultSet's SQL cursor name
1050    //  Throws:
1051    //       TSQLException - if a database access error occurs
1052 
1053    TString str;
1054    
1055    if(!fImp) { Destroyed(); return str; }
1056    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
1057    
1058    try {      
1059       str = ODBCXX_STRING_CSTR( rs->getCursorName() );
1060 
1061    } catch(odbc::SQLException& e) {
1062       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
1063                                 ODBCXX_STRING_CSTR(e.getSQLState()),
1064                                 e.getErrorCode()) );
1065       return "";
1066    }
1067    return str;
1068 }
1069 
1070 //___________________________________________________________________
1071 TSQLResultSetMetaData* ODBCResultSet::GetMetaData()
1072 {
1073    // Retrieves the number, types and properties of a 
1074    // TSQLResultSet's columns.
1075    //
1076    //  Returns:
1077    //       the description of a TSQLResultSet's columns
1078    //  Throws:
1079    //       TSQLException - if a database access error occurs
1080 
1081    return fMetaData;
1082 }
1083 
1084 //___________________________________________________________________
1085 Int_t ODBCResultSet::FindColumn( const TString& columnName )
1086 {
1087    // Maps the given resultset column name to its TSQLResultSet
1088    // column index.
1089    //
1090    //  Parameters:
1091    //       columnName - the name of the column
1092    //  Returns:
1093    //       the column index
1094    //  Throws:
1095    //       TSQLException - if a database access error occurs
1096 
1097    Int_t return_value = 0;
1098    
1099    if(!fImp) { Destroyed(); return return_value; }
1100    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
1101    
1102    try { 
1103       return_value = rs->findColumn( 
1104                                  ODBCXX_STRING_C(columnName.Data()) );
1105 
1106    } catch(odbc::SQLException& e) {
1107       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
1108                                 ODBCXX_STRING_CSTR(e.getSQLState()),
1109                                 e.getErrorCode()) );
1110       return_value = 0;
1111    }
1112    return return_value;
1113 }
1114 
1115 //___________________________________________________________________
1116 Bool_t ODBCResultSet::IsBeforeFirst()
1117 {
1118    // Indicates whether the cursor is before the first row in 
1119    // the result set.
1120    //
1121    //  Returns:
1122    //       kTRUE if the cursor is before the first row, 
1123    //       kFALSE otherwise. Returns kFALSE when the
1124    //       result set contains no rows.
1125    //  Throws:
1126    //       TSQLException - if a database access error occurs
1127 
1128    Bool_t return_value = kFALSE;
1129    
1130    if(!fImp) { Destroyed(); return return_value; }
1131    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
1132    
1133    try {      
1134       return_value = rs->isBeforeFirst();
1135 
1136    } catch(odbc::SQLException& e) {
1137       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
1138                                 ODBCXX_STRING_CSTR(e.getSQLState()),
1139                                 e.getErrorCode()) );
1140       return_value = kFALSE;
1141    }
1142    return return_value;
1143 }
1144 
1145 //___________________________________________________________________
1146 Bool_t ODBCResultSet::IsAfterLast()
1147 {
1148    // Indicates whether the cursor is after the last row in 
1149    // the result set.
1150    //
1151    //  Returns:
1152    //       kTRUE if the cursor is after the last row, 
1153    //       kFALSE otherwise. Returns kFALSE when the
1154    //       result set contains no rows.
1155    //  Throws:
1156    //       TSQLException - if a database access error occurs
1157 
1158    Bool_t return_value = kFALSE;
1159    
1160    if(!fImp) { Destroyed(); return return_value; }
1161    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
1162       
1163    try {      
1164       return_value = rs->isAfterLast();
1165 
1166    } catch(odbc::SQLException& e) {
1167       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
1168                                 ODBCXX_STRING_CSTR(e.getSQLState()),
1169                                 e.getErrorCode()) );
1170       return_value = kFALSE;
1171    }
1172    return return_value;
1173 }
1174           
1175 //___________________________________________________________________
1176 Bool_t ODBCResultSet::IsFirst() 
1177 {
1178    // Indicates whether the cursor is on the first row of 
1179    // the result set.
1180    //
1181    //  Returns:
1182    //       kTRUE if the cursor is on the first row, 
1183    //       kFALSE otherwise.
1184    //  Throws:
1185    //       TSQLException - if a database access error occurs
1186 
1187    Bool_t return_value = kFALSE;
1188    
1189    if(!fImp) { Destroyed(); return return_value; }
1190    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
1191    
1192    try {      
1193       return_value = rs->isFirst();
1194 
1195    } catch(odbc::SQLException& e) {
1196       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
1197                                 ODBCXX_STRING_CSTR(e.getSQLState()),
1198                                 e.getErrorCode()) );
1199       return_value = kFALSE;
1200    }
1201    return return_value;
1202 }
1203 
1204 //___________________________________________________________________
1205 Bool_t ODBCResultSet::IsLast()
1206 {
1207    // Indicates whether the cursor is on the last row of the 
1208    // result set.
1209    //
1210    //  Note: Calling the method IsLast() may be expensive because 
1211    //       the driver might need to fetch ahead one row in 
1212    //       order to determine whether the current row is the 
1213    //       last row in the result set.
1214    //
1215    //  Returns:
1216    //       kTRUE if the cursor is on the last row, 
1217    //       kFALSE otherwise.
1218    //  Throws:
1219    //       TSQLException - if a database access error occurs
1220 
1221    Bool_t return_value = kFALSE;
1222    
1223    if(!fImp) { Destroyed(); return return_value; }
1224    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
1225    
1226    try {
1227       return_value = rs->isLast();
1228 
1229    } catch(odbc::SQLException& e) {
1230       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
1231                                 ODBCXX_STRING_CSTR(e.getSQLState()),
1232                                 e.getErrorCode()) );
1233       return_value = kFALSE;
1234    }
1235    return return_value;
1236 }
1237 
1238 //___________________________________________________________________
1239 void ODBCResultSet::BeforeFirst()
1240 {
1241    // Moves the cursor to the front of the result set, just before 
1242    // the first row. Has no effect if the result set contains no 
1243    // rows.
1244    //
1245    //  Throws:
1246    //       TSQLException - if a database access error occurs or 
1247    //       the result set type is kTYPE_FORWARD_ONLY
1248    
1249    if(!fImp) { Destroyed(); return; }
1250    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
1251    
1252    try {     
1253       rs->beforeFirst();
1254 
1255    } catch(odbc::SQLException& e) {
1256       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
1257                                 ODBCXX_STRING_CSTR(e.getSQLState()),
1258                                 e.getErrorCode()) );
1259    }
1260 }
1261 
1262 //___________________________________________________________________
1263 void ODBCResultSet::AfterLast()
1264 {
1265    // Moves the cursor to the end of the result set, just after 
1266    // the last row. Has no effect if the result set contains no 
1267    // rows.
1268    //
1269    //  Throws:
1270    //       TSQLException - if a database access error occurs or 
1271    //       the result set type is kTYPE_FORWARD_ONLY
1272 
1273    if(!fImp) { Destroyed(); return; }
1274    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
1275       
1276    try {
1277       rs->afterLast();
1278 
1279    } catch(odbc::SQLException& e) {
1280       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
1281                                 ODBCXX_STRING_CSTR(e.getSQLState()),
1282                                 e.getErrorCode()) );
1283    }
1284 }
1285 
1286 //___________________________________________________________________
1287 Int_t ODBCResultSet::GetRow()
1288 {
1289    // Retrieves the current row number. The first row is number 1, 
1290    // the second number 2, and so on.
1291    //
1292    //  Returns:
1293    //       the current row number; 0 if there is no current row
1294    //  Throws:
1295    //       TSQLException - if a database access error occurs
1296 
1297    Int_t return_value = 0;
1298    
1299    if(!fImp) { Destroyed(); return return_value; }
1300    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
1301    
1302    try {
1303       return_value = rs->getRow();
1304 
1305    } catch(odbc::SQLException& e) {
1306       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
1307                                 ODBCXX_STRING_CSTR(e.getSQLState()),
1308                                 e.getErrorCode()) );
1309       return_value = 0;
1310    }
1311    return return_value;
1312 }
1313 
1314 //___________________________________________________________________
1315 void ODBCResultSet::SetFetchDirection(Int_t /* direction */)
1316 {
1317    // Gives a hint as to the direction in which the rows in this
1318    // result set will be processed. The initial value is determined
1319    // by the TSQLStatement that produced the result set.
1320    // The fetch direction may be changed at any time.
1321    //
1322    //  Throws:
1323    //       TSQLException - if a database access error occurs or 
1324    //       the result set type is kTYPE_FORWARD_ONLY and the fetch 
1325    //       direction is not forward
1326 
1327 }
1328 
1329 //___________________________________________________________________
1330 Int_t ODBCResultSet::GetFetchDirection()
1331 {
1332    // Returns the fetch direction for this result set.
1333    //
1334    //  Returns:
1335    //       the current fetch direction for this result set
1336    //  Throws:
1337    //       TSQLException - if a database access error occurs
1338    
1339    return 0;   // not applied
1340 }
1341 
1342 //___________________________________________________________________
1343 void ODBCResultSet::SetFetchSize(Int_t rows)
1344 {
1345    // Gives the driver a hint as to the number of rows that
1346    // should be fetched from the database when more rows are needed 
1347    // for this result set. If the fetch size specified is zero, 
1348    // the driver ignores the value and is free to make its own
1349    // best guess as to what the fetch size should be. The default 
1350    // value is set by the statement that created the result set. 
1351    // The fetch size may be changed at any time.
1352    //
1353    //  Parameters:
1354    //       rows - the number of rows to fetch
1355    //  Throws:
1356    //       TSQLException - if a database access error occurs or the
1357    //       condition 0 <= rows <= GetMaxRows() is not satisfied.
1358    
1359    if(!fImp) { Destroyed(); return; }
1360    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
1361    
1362    try {      
1363       rs->setFetchSize(rows);
1364 
1365    } catch(odbc::SQLException& e) {
1366       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
1367                                 ODBCXX_STRING_CSTR(e.getSQLState()),
1368                                 e.getErrorCode()) );
1369    }
1370 }
1371 
1372 //___________________________________________________________________
1373 Int_t ODBCResultSet::GetFetchSize()
1374 {
1375    // Returns the fetch size for this result set.
1376    //
1377    //  Returns:
1378    //       the current fetch size for this result set
1379    //  Throws:
1380    //       TSQLException - if a database access error occurs
1381 
1382    Int_t return_value = 0;
1383    
1384    if(!fImp) { Destroyed(); return return_value; }
1385    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
1386    
1387    try {      
1388       return_value = rs->getFetchSize();
1389 
1390    } catch(odbc::SQLException& e) {
1391       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
1392                                 ODBCXX_STRING_CSTR(e.getSQLState()),
1393                                 e.getErrorCode()) );
1394       return_value = 0;
1395    }
1396    return return_value;
1397 }
1398 
1399 //___________________________________________________________________
1400 Int_t ODBCResultSet::GetType()
1401 {
1402    // Returns the type of this result set. The type is
1403    // determined by the TSQLStatement that created the result set.
1404    //
1405    //  Returns:
1406    //       kTYPE_FORWARD_ONLY, kTYPE_SCROLL_INSENSITIVE, or
1407    //       kTYPE_SCROLL_SENSITIVE
1408    //  Throws:
1409    //       TSQLException - if a database access error occurs
1410 
1411    Int_t return_value = 0;
1412    
1413    if(!fImp) { Destroyed(); return return_value; }
1414    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
1415    
1416    try {     
1417       return_value = rs->getType();
1418 
1419    } catch(odbc::SQLException& e) {
1420       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
1421                                 ODBCXX_STRING_CSTR(e.getSQLState()),
1422                                 e.getErrorCode()) );
1423       return_value = 0;
1424    }
1425    return return_value;
1426 }
1427 
1428 //___________________________________________________________________
1429 Int_t ODBCResultSet::GetConcurrency()
1430 {
1431    // Returns the concurrency mode of this result set. The
1432    // concurrency used is determined by the TSQLStatement that 
1433    // created the result set.
1434    //
1435    //  Returns:
1436    //       the concurrency type, kCONCUR_READ_ONLY or 
1437    //                             kCONCUR_UPDATABLE
1438    //  Throws:
1439    //       TSQLException - if a database access error occurs
1440    
1441    Int_t return_value = 0;
1442    
1443    if(!fImp) { Destroyed(); return return_value; }
1444    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
1445       
1446    try {      
1447       return_value = rs->getConcurrency();
1448 
1449    } catch(odbc::SQLException& e) {
1450       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
1451                                 ODBCXX_STRING_CSTR(e.getSQLState()),
1452                                 e.getErrorCode()) );
1453       return_value = 0;
1454    }
1455    return return_value;
1456 }
1457 
1458 //___________________________________________________________________
1459 Bool_t ODBCResultSet::RowUpdated()
1460 {
1461    // Indicates whether the current row has been updated. The
1462    // value returned depends on whether or not the result set 
1463    // can detect updates.
1464    //
1465    //  Returns:
1466    //       kTRUE if the row has been visibly updated by 
1467    //       the owner or another, and updates are detected
1468    //  Throws:
1469    //       TSQLException - if a database access error occurs
1470    //  See Also: 
1471    //       TSQLDatabaseMetaData::updatesAreDetected(Int_t)
1472 
1473    Bool_t return_value = kFALSE;
1474    
1475    if(!fImp) { Destroyed(); return return_value; }
1476    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
1477       
1478    try {
1479       return_value = rs->rowUpdated();
1480 
1481    } catch(odbc::SQLException& e) {
1482       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
1483                                 ODBCXX_STRING_CSTR(e.getSQLState()),
1484                                 e.getErrorCode()) );
1485       return_value = kFALSE;
1486    }
1487    return return_value;
1488 }
1489 
1490 //___________________________________________________________________
1491 Bool_t ODBCResultSet::RowInserted()
1492 {
1493    // Indicates whether the current row has had an insertion.
1494    //  The value returned depends on whether or not the 
1495    // result set can detect visible inserts.
1496    //
1497    //  Returns:
1498    //       kTRUE if a row has had an insertion and insertions 
1499    //       are detected
1500    //  Throws:
1501    //       TSQLException - if a database access error occurs
1502    //  See Also: 
1503    //       TSQLDatabaseMetaData::insertsAreDetected(Int_t)
1504 
1505    Bool_t return_value = kFALSE;
1506    
1507    if(!fImp) { Destroyed(); return return_value; }
1508    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
1509    
1510    try {
1511       return_value = rs->rowInserted();
1512 
1513    } catch(odbc::SQLException& e) {
1514       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
1515                                 ODBCXX_STRING_CSTR(e.getSQLState()),
1516                                 e.getErrorCode()) );
1517       return_value = kFALSE;
1518    }
1519    return return_value;
1520 }
1521 
1522 //___________________________________________________________________
1523 Bool_t ODBCResultSet::RowDeleted()
1524 {
1525    // Indicates whether a row has been deleted. A deleted row
1526    // may leave a visible "hole" in a result set. This method 
1527    // can be used to detect holes in a result set. The value 
1528    // returned depends on whether or not the result set can 
1529    // detect deletions.
1530    //
1531    //  Returns:
1532    //       kTRUE if a row was deleted and deletions are detected
1533    //  Throws:
1534    //       TSQLException - if a database access error occurs
1535    //  See Also: 
1536    //       TSQLDatabaseMetaData::deletesAreDetected(Int_t)
1537 
1538    Bool_t return_value = kFALSE;
1539    
1540    if(!fImp) { Destroyed(); return return_value; }
1541    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
1542       
1543    try {
1544       return_value = rs->rowDeleted();
1545 
1546    } catch(odbc::SQLException& e) {
1547       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
1548                                 ODBCXX_STRING_CSTR(e.getSQLState()),
1549                                 e.getErrorCode()) );
1550       return_value = kFALSE;
1551    }
1552    return return_value;
1553 }
1554 
1555 //___________________________________________________________________
1556 void ODBCResultSet::UpdateNull( Int_t columnIndex )
1557 {
1558    // Give a nullable column a null value. The UpdateXXX methods
1559    // are used to update column values in the current row, 
1560    // or the insert row. The UpdateXXX methods do not update the
1561    // underlying database; instead the UpdateRow() or InsertRow() 
1562    // methods are called to update the database.
1563    //
1564    //  Parameters:
1565    //       columnIndex - the first column is 1, the second is 2, ...
1566    //  Throws:
1567    //       TSQLException - if a database access error occurs
1568    
1569    if(!fImp) { Destroyed(); return; }
1570    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
1571    
1572    try {      
1573       rs->updateNull(columnIndex);
1574 
1575    } catch(odbc::SQLException& e) {
1576       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
1577                                 ODBCXX_STRING_CSTR(e.getSQLState()),
1578                                 e.getErrorCode()) );
1579    }
1580 }
1581 
1582 //___________________________________________________________________
1583 void ODBCResultSet::UpdateBoolean( Int_t columnIndex,Bool_t x )
1584 {
1585    // Updates a column with a boolean value. The UpdateXXX
1586    // methods are used to update column values in the current row, 
1587    // or the insert row. The UpdateXXX methods do not update the
1588    // underlying database; instead the UpdateRow() or InsertRow() 
1589    // methods are called to update the database.
1590    // 
1591    //  Parameters:
1592    //       columnIndex - the first column is 1, the second is 2, ...
1593    //       x - the new column value
1594    //  Throws:
1595    //       TSQLException - if a database access error occurs
1596    
1597    if(!fImp) { Destroyed(); return; }
1598    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
1599    
1600    try {      
1601       rs->updateBoolean(columnIndex,x);
1602 
1603    } catch(odbc::SQLException& e) {
1604       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
1605                                 ODBCXX_STRING_CSTR(e.getSQLState()),
1606                                 e.getErrorCode()) );
1607    }
1608 }
1609 
1610 //___________________________________________________________________
1611 void ODBCResultSet::UpdateByte( Int_t columnIndex,Char_t x )
1612 {
1613    // Updates a column with a Char_t value. The UpdateXXX methods
1614    // are used to update column values in the current row, 
1615    // or the insert row. The UpdateXXX methods do not update the
1616    // underlying database; instead the UpdateRow() or InsertRow() 
1617    // methods are called to update the database.
1618    // 
1619    //  Parameters:
1620    //       columnIndex - the first column is 1, the second is 2, ...
1621    //       x - the new column value
1622    //  Throws:
1623    //       TSQLException - if a database access error occurs
1624    
1625    if(!fImp) { Destroyed(); return; }
1626    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
1627    
1628    try {      
1629       rs->updateByte(columnIndex,x);
1630 
1631    } catch(odbc::SQLException& e) {
1632       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
1633                                 ODBCXX_STRING_CSTR(e.getSQLState()),
1634                                 e.getErrorCode()) );
1635    }
1636 }
1637 
1638 //___________________________________________________________________
1639 void ODBCResultSet::UpdateShort( Int_t columnIndex,Short_t x )
1640 {
1641    // Updates a column with a Short_t value. The UpdateXXX methods
1642    // are used to update column values in the current row, 
1643    // or the insert row. The UpdateXXX methods do not update the
1644    // underlying database; instead the UpdateRow() or InsertRow() 
1645    // methods are called to update the database.
1646    // 
1647    //  Parameters:
1648    //       columnIndex - the first column is 1, the second is 2, ...
1649    //       x - the new column value
1650    //  Throws:
1651    //       TSQLException - if a database access error occurs
1652    
1653    if(!fImp) { Destroyed(); return; }
1654    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
1655    
1656    try {      
1657       rs->updateShort(columnIndex,x);
1658 
1659    } catch(odbc::SQLException& e) {
1660       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
1661                                 ODBCXX_STRING_CSTR(e.getSQLState()),
1662                                 e.getErrorCode()) );
1663    }
1664 }
1665 
1666 //___________________________________________________________________
1667 void ODBCResultSet::UpdateInt( Int_t columnIndex,Int_t x )
1668 {
1669    // Updates a column with an integer value. The UpdateXXX
1670    // methods are used to update column values in the current row, 
1671    // or the insert row. The UpdateXXX methods do not update the
1672    // underlying database; instead the UpdateRow() or InsertRow() 
1673    // methods are called to update the database.
1674    // 
1675    //  Parameters:
1676    //       columnIndex - the first column is 1, the second is 2, ...
1677    //       x - the new column value
1678    //  Throws:
1679    //       TSQLException - if a database access error occurs
1680    
1681    if(!fImp) { Destroyed(); return; }
1682    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
1683    
1684    try {
1685       rs->updateInt(columnIndex,x);
1686 
1687    } catch(odbc::SQLException& e) {
1688       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
1689                                 ODBCXX_STRING_CSTR(e.getSQLState()),
1690                                 e.getErrorCode()) );
1691    }
1692 }
1693 
1694 //___________________________________________________________________
1695 void ODBCResultSet::UpdateLong( Int_t columnIndex,Long_t x )
1696 {
1697    // Updates a column with a Long_t value. The UpdateXXX methods
1698    // are used to update column values in the current row, 
1699    // or the insert row. The UpdateXXX methods do not update the
1700    // underlying database; instead the UpdateRow() or InsertRow() 
1701    // methods are called to update the database.
1702    // 
1703    //  Parameters:
1704    //       columnIndex - the first column is 1, the second is 2, ...
1705    //       x - the new column value
1706    //  Throws:
1707    //       TSQLException - if a database access error occurs
1708    
1709    if(!fImp) { Destroyed(); return; }
1710    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
1711    
1712    try {
1713       rs->updateLong(columnIndex,x);
1714 
1715    } catch(odbc::SQLException& e) {
1716       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
1717                                 ODBCXX_STRING_CSTR(e.getSQLState()),
1718                                 e.getErrorCode()) );
1719    }
1720 }
1721 
1722 //___________________________________________________________________
1723 void ODBCResultSet::UpdateFloat( Int_t columnIndex,Float_t x )
1724 {
1725    // Updates a column with a Float_t value. The UpdateXXX methods
1726    // are used to update column values in the current row, 
1727    // or the insert row. The UpdateXXX methods do not update the
1728    // underlying database; instead the UpdateRow() or InsertRow() 
1729    // methods are called to update the database.
1730    // 
1731    //  Parameters:
1732    //       columnIndex - the first column is 1, the second is 2, ...
1733    //       x - the new column value
1734    //  Throws:
1735    //       TSQLException - if a database access error occurs
1736    
1737    if(!fImp) { Destroyed(); return; }
1738    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
1739    
1740    try {
1741       rs->updateFloat(columnIndex,x);
1742 
1743    } catch(odbc::SQLException& e) {
1744       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
1745                                 ODBCXX_STRING_CSTR(e.getSQLState()),
1746                                 e.getErrorCode()) );
1747    }
1748 }
1749 
1750 //___________________________________________________________________
1751 void ODBCResultSet::UpdateDouble( Int_t columnIndex,
1752                                   Double_t x )
1753 {
1754    // Updates a column with a Double value. The UpdateXXX
1755    // methods are used to update column values in the current row, 
1756    // or the insert row. The UpdateXXX methods do not update the
1757    // underlying database; instead the UpdateRow() or InsertRow() 
1758    // methods are called to update the database.
1759    // 
1760    //  Parameters:
1761    //       columnIndex - the first column is 1, the second is 2, ...
1762    //       x - the new column value
1763    //  Throws:
1764    //       TSQLException - if a database access error occurs
1765    
1766    if(!fImp) { Destroyed(); return; }
1767    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
1768    
1769    try {      
1770       rs->updateDouble(columnIndex,x);
1771 
1772    } catch(odbc::SQLException& e) {
1773       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
1774                                 ODBCXX_STRING_CSTR(e.getSQLState()),
1775                                 e.getErrorCode()) );
1776    }
1777 }
1778 
1779 //___________________________________________________________________
1780 void ODBCResultSet::UpdateString( Int_t columnIndex,
1781                                   const TString& x )
1782 {
1783    // Updates a column with a TString value. The UpdateXXX
1784    // methods are used to update column values in the current row, 
1785    // or the insert row. The UpdateXXX methods do not update the
1786    // underlying database; instead the UpdateRow() or InsertRow() 
1787    // methods are called to update the database.
1788    // 
1789    //  Parameters:
1790    //       columnIndex - the first column is 1, the second is 2, ...
1791    //       x - the new column value
1792    //  Throws:
1793    //       TSQLException - if a database access error occurs
1794    
1795    if(!fImp) { Destroyed(); return; }
1796    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
1797    
1798    try {       
1799       ODBCXX_STRING s = ODBCXX_STRING_C(x.Data()); 
1800       rs->updateString(columnIndex,s);
1801 
1802    } catch(odbc::SQLException& e) {
1803       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
1804                                 ODBCXX_STRING_CSTR(e.getSQLState()),
1805                                 e.getErrorCode()) );
1806    }
1807 }
1808 
1809 //___________________________________________________________________
1810 void ODBCResultSet::UpdateBytes( Int_t columnIndex,
1811                                  const TArrayC& x )
1812 {
1813    // Updates a column with a Char_t array value. The UpdateXXX
1814    // methods are used to update column values in the current row, 
1815    // or the insert row. The UpdateXXX methods do not update the
1816    // underlying database; instead the UpdateRow() or InsertRow() 
1817    // methods are called to update the database.
1818    // 
1819    //  Parameters:
1820    //       columnIndex - the first column is 1, the second is 2, ...
1821    //       x - the new column value
1822    //  Throws:
1823    //       TSQLException - if a database access error occurs
1824    
1825    if(!fImp) { Destroyed(); return; }
1826    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
1827    
1828    try {      
1829       ODBCXX_BYTES b = ODBCXX_BYTES_C(x.GetArray(),x.GetSize());
1830       rs->updateBytes(columnIndex,b);
1831 
1832    } catch(odbc::SQLException& e) {
1833       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
1834                                 ODBCXX_STRING_CSTR(e.getSQLState()),
1835                                 e.getErrorCode()) );
1836    }
1837 }
1838 
1839 //___________________________________________________________________
1840 void ODBCResultSet::UpdateDate( Int_t columnIndex,
1841                                 const TSQLDate& x )
1842 {
1843    // Updates a column with a TSQLDate value. The UpdateXXX methods
1844    // are used to update column values in the current row, 
1845    // or the insert row. The UpdateXXX methods do not update the
1846    // underlying database; instead the UpdateRow() or InsertRow() 
1847    // methods are called to update the database.
1848    // 
1849    //  Parameters:
1850    //       columnIndex - the first column is 1, the second is 2, ...
1851    //       x - the new column value
1852    //  Throws:
1853    //       TSQLException - if a database access error occurs
1854    
1855    if(!fImp) { Destroyed(); return; }
1856    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
1857    
1858    try {
1859       odbc::Date dt( x.GetYear(),
1860                      x.GetMonth(),
1861                      x.GetDay() );
1862     
1863       rs->updateDate(columnIndex,dt);
1864 
1865    } catch(odbc::SQLException& e) {
1866       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
1867                                 ODBCXX_STRING_CSTR(e.getSQLState()),
1868                                 e.getErrorCode()) );
1869    }
1870 }
1871 
1872 //___________________________________________________________________
1873 void ODBCResultSet::UpdateTime( Int_t columnIndex,
1874                                 const TSQLTime& x )
1875 {
1876    // Updates a column with a TSQLTime value. The UpdateXXX methods
1877    // are used to update column values in the current row, 
1878    // or the insert row. The UpdateXXX methods do not update the
1879    // underlying database; instead the UpdateRow() or InsertRow() 
1880    // methods are called to update the database.
1881    // 
1882    //  Parameters:
1883    //       columnIndex - the first column is 1, the second is 2, ...
1884    //       x - the new column value
1885    //  Throws:
1886    //       TSQLException - if a database access error occurs
1887    
1888    if(!fImp) { Destroyed(); return; }
1889    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
1890    
1891    try { 
1892       odbc::Time tm( x.GetHour(),
1893                      x.GetMinute(),
1894                      x.GetSecond() );
1895    
1896       rs->updateTime(columnIndex,tm);
1897 
1898    } catch(odbc::SQLException& e) {
1899       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
1900                                 ODBCXX_STRING_CSTR(e.getSQLState()),
1901                                 e.getErrorCode()) );
1902    }
1903 }
1904 
1905 //___________________________________________________________________
1906 void ODBCResultSet::UpdateTimestamp( Int_t columnIndex,
1907                                      const TSQLTimestamp& x )
1908 {
1909    // Updates a column with a TSQLTimestamp value. The UpdateXXX
1910    // methods are used to update column values in the current row, 
1911    // or the insert row. The UpdateXXX methods do not update the
1912    // underlying database; instead the UpdateRow() or InsertRow() 
1913    // methods are called to update the database.
1914    // 
1915    //  Parameters:
1916    //       columnIndex - the first column is 1, the second is 2, ...
1917    //       x - the new column value
1918    //  Throws:
1919    //       TSQLException - if a database access error occurs
1920    
1921    if(!fImp) { Destroyed(); return; }
1922    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
1923    
1924    try { 
1925       odbc::Timestamp tmstmp( x.GetYear(),
1926                               x.GetMonth(),
1927                               x.GetDay(),  
1928                               x.GetHour(),
1929                               x.GetMinute(),
1930                               x.GetSecond(),
1931                               x.GetNanos() );
1932    
1933       rs->updateTimestamp(columnIndex,tmstmp);
1934 
1935    } catch(odbc::SQLException& e) {
1936       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
1937                                 ODBCXX_STRING_CSTR(e.getSQLState()),
1938                                 e.getErrorCode()) );
1939    }
1940 }
1941 
1942 //___________________________________________________________________
1943 void ODBCResultSet::UpdateAsciiStream( Int_t columnIndex,
1944                                        TBuffer* x,
1945                                        Int_t length )
1946 {
1947    // Updates a column with an ascii stream value. The UpdateXXX
1948    // methods are used to update column values in the current row, 
1949    // or the insert row. The UpdateXXX methods do not update the
1950    // underlying database; instead the UpdateRow() or InsertRow() 
1951    // methods are called to update the database.
1952    // 
1953    //  Parameters:
1954    //       columnIndex - the first column is 1, the second is 2, ...
1955    //       x - the new column value
1956    //       length - length of stream
1957    //  Throws:
1958    //       TSQLException - if a database access error occurs  
1959 
1960    if(!fImp) { Destroyed(); return; }
1961    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
1962    
1963    try {         
1964       Int_t xl = (x->BufferSize()>length) && (length>0) ? length : x->BufferSize();
1965       std::istringstream* s = new std::istringstream(x->Buffer()); //
1966       rs->updateAsciiStream( columnIndex,(std::istream*)s,xl );
1967       
1968    } catch(odbc::SQLException& e) {
1969       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
1970                                 ODBCXX_STRING_CSTR(e.getSQLState()),
1971                                 e.getErrorCode()) );
1972    }
1973 }
1974 
1975 //___________________________________________________________________
1976 void ODBCResultSet::UpdateBinaryStream( Int_t columnIndex,
1977                                         TBuffer* x,
1978                                         Int_t length )
1979 {
1980    // Updates a column with a binary stream value. The UpdateXXX
1981    // methods are used to update column values in the current row, 
1982    // or the insert row. The UpdateXXX methods do not update the
1983    // underlying database; instead the UpdateRow() or InsertRow() 
1984    // methods are called to update the database.
1985    // 
1986    //  Parameters:
1987    //       columnIndex - the first column is 1, the second is 2, ...
1988    //       x - the new column value
1989    //       length - length of stream   
1990    //  Throws:
1991    //       TSQLException - if a database access error occurs
1992 
1993    if(!fImp) { Destroyed(); return; }
1994    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
1995    
1996    try {   
1997       Int_t xl = (x->BufferSize()>length) && (length>0) ? length : x->BufferSize();
1998       std::istringstream* s = new std::istringstream(x->Buffer());
1999       rs->updateBinaryStream( columnIndex,(std::istream*)s,xl );
2000       
2001    } catch(odbc::SQLException& e) {
2002       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
2003                                 ODBCXX_STRING_CSTR(e.getSQLState()),
2004                                 e.getErrorCode()) );
2005    }
2006 }
2007 
2008 //___________________________________________________________________
2009 void ODBCResultSet::UpdateObject( Int_t columnIndex,TObject* x )
2010 {
2011    // Updates a column with a ROOT object. The UpdateXXX
2012    // methods are used to update column values in the current row, 
2013    // or the insert row. The UpdateXXX methods do not update the
2014    // underlying database; instead the UpdateRow() or InsertRow() 
2015    // methods are called to update the database.
2016    // 
2017    //  Parameters:
2018    //       columnIndex - the first column is 1, the second is 2, ...
2019    //       x - the new column value
2020    //       length - length of stream   
2021    //  Throws:
2022    //       TSQLException - if a database access error occurs
2023  
2024 #if ROOT_VERSION_CODE >= ROOT_VERSION(5,15,0)
2025   TBuffer *b = new TBufferFile(TBuffer::kWrite);
2026 #else
2027   TBuffer *b = new TBuffer(TBuffer::kWrite);
2028 #endif
2029    b->WriteObject(x);
2030    UpdateBinaryStream(columnIndex,b,b->BufferSize());
2031    b->DetachBuffer();
2032    delete b; 
2033 }
2034 
2035 //___________________________________________________________________
2036 void ODBCResultSet::UpdateNull( const TString& columnName )
2037 {
2038    // Updates a column with a null value. The UpdateXXX methods
2039    // are used to update column values in the current row, 
2040    // or the insert row. The UpdateXXX methods do not update the
2041    // underlying database; instead the UpdateRow() or InsertRow() 
2042    // methods are called to update the database.
2043    // 
2044    //  Parameters:
2045    //       columnIndex - the first column is 1, the second is 2, ...
2046    //       x - the new column value
2047    //  Throws:
2048    //       TSQLException - if a database access error occurs
2049 
2050    UpdateNull(FindColumn(columnName));
2051 }
2052 
2053 //___________________________________________________________________
2054 void ODBCResultSet::UpdateBoolean( const TString& columnName,Bool_t x )
2055 {
2056    // Updates a column with a boolean value. The UpdateXXX methods
2057    // are used to update column values in the current row, 
2058    // or the insert row. The UpdateXXX methods do not update the
2059    // underlying database; instead the UpdateRow() or InsertRow() 
2060    // methods are called to update the database.
2061    // 
2062    //  Parameters:
2063    //       columnIndex - the first column is 1, the second is 2, ...
2064    //       x - the new column value
2065    //  Throws:
2066    //       TSQLException - if a database access error occurs
2067 
2068    UpdateBoolean(FindColumn(columnName),x);
2069 }
2070 
2071 //___________________________________________________________________
2072 void ODBCResultSet::UpdateByte( const TString& columnName,Char_t x )
2073 {
2074    // Updates a column with a Char_t value. The UpdateXXX methods
2075    // are used to update column values in the current row, 
2076    // or the insert row. The UpdateXXX methods do not update the
2077    // underlying database; instead the UpdateRow() or InsertRow() 
2078    // methods are called to update the database.
2079    // 
2080    //  Parameters:
2081    //       columnIndex - the first column is 1, the second is 2, ...
2082    //       x - the new column value
2083    //  Throws:
2084    //       TSQLException - if a database access error occurs
2085 
2086    UpdateByte(FindColumn(columnName),x);
2087 }
2088 
2089 //___________________________________________________________________
2090 void ODBCResultSet::UpdateShort( const TString& columnName,Short_t x )
2091 {
2092    // Updates a column with a short value. The UpdateXXX methods
2093    // are used to update column values in the current row, 
2094    // or the insert row. The UpdateXXX methods do not update the
2095    // underlying database; instead the UpdateRow() or InsertRow() 
2096    // methods are called to update the database.
2097    // 
2098    //  Parameters:
2099    //       columnIndex - the first column is 1, the second is 2, ...
2100    //       x - the new column value
2101    //  Throws:
2102    //       TSQLException - if a database access error occurs
2103 
2104    UpdateShort(FindColumn(columnName),x);
2105 }
2106 
2107 //___________________________________________________________________
2108 void ODBCResultSet::UpdateInt( const TString& columnName,Int_t x )
2109 {
2110    // Updates a column with an integer value. The UpdateXXX methods
2111    // are used to update column values in the current row, 
2112    // or the insert row. The UpdateXXX methods do not update the
2113    // underlying database; instead the UpdateRow() or InsertRow() 
2114    // methods are called to update the database.
2115    // 
2116    //  Parameters:
2117    //       columnIndex - the first column is 1, the second is 2, ...
2118    //       x - the new column value
2119    //  Throws:
2120    //       TSQLException - if a database access error occurs
2121 
2122    UpdateInt(FindColumn(columnName),x);
2123 }
2124 
2125 //___________________________________________________________________
2126 void ODBCResultSet::UpdateLong( const TString& columnName,Long_t x )
2127 {
2128    // Updates a column with a long value. The UpdateXXX methods
2129    // are used to update column values in the current row, 
2130    // or the insert row. The UpdateXXX methods do not update the
2131    // underlying database; instead the UpdateRow() or InsertRow() 
2132    // methods are called to update the database.
2133    // 
2134    //  Parameters:
2135    //       columnIndex - the first column is 1, the second is 2, ...
2136    //       x - the new column value
2137    //  Throws:
2138    //       TSQLException - if a database access error occurs
2139 
2140    UpdateLong(FindColumn(columnName),x);
2141 }
2142 
2143 //___________________________________________________________________
2144 void ODBCResultSet::UpdateFloat( const TString& columnName,Float_t x )
2145 {
2146    // Updates a column with a float value. The UpdateXXX methods
2147    // are used to update column values in the current row, 
2148    // or the insert row. The UpdateXXX methods do not update the
2149    // underlying database; instead the UpdateRow() or InsertRow() 
2150    // methods are called to update the database.
2151    // 
2152    //  Parameters:
2153    //       columnIndex - the first column is 1, the second is 2, ...
2154    //       x - the new column value
2155    //  Throws:
2156    //       TSQLException - if a database access error occurs 
2157 
2158    UpdateFloat(FindColumn(columnName),x);
2159 }
2160 
2161 //___________________________________________________________________
2162 void ODBCResultSet::UpdateDouble( const TString& columnName,Double_t x )
2163 {
2164    // Updates a column with a double value. The UpdateXXX methods
2165    // are used to update column values in the current row, 
2166    // or the insert row. The UpdateXXX methods do not update the
2167    // underlying database; instead the UpdateRow() or InsertRow() 
2168    // methods are called to update the database.
2169    // 
2170    //  Parameters:
2171    //       columnIndex - the first column is 1, the second is 2, ...
2172    //       x - the new column value
2173    //  Throws:
2174    //       TSQLException - if a database access error occurs
2175 
2176    UpdateDouble(FindColumn(columnName),x);
2177 }
2178 
2179 //___________________________________________________________________
2180 void ODBCResultSet::UpdateString( const TString& columnName,
2181                                   const TString& x )
2182 {
2183    // Updates a column with a TString value. The UpdateXXX methods
2184    // are used to update column values in the current row, 
2185    // or the insert row. The UpdateXXX methods do not update the
2186    // underlying database; instead the UpdateRow() or InsertRow() 
2187    // methods are called to update the database.
2188    // 
2189    //  Parameters:
2190    //       columnIndex - the first column is 1, the second is 2, ...
2191    //       x - the new column value
2192    //  Throws:
2193    //       TSQLException - if a database access error occurs
2194 
2195    UpdateString(FindColumn(columnName),x);
2196 }
2197 
2198 //___________________________________________________________________
2199 void ODBCResultSet::UpdateBytes( const TString& columnName,
2200                                  const TArrayC& x )
2201 {
2202    // Updates a column with a bytes array value. The update methods
2203    // are used to update column values in the current row, 
2204    // or the insert row. The UpdateXXX methods do not update the
2205    // underlying database; instead the UpdateRow() or InsertRow() 
2206    // methods are called to update the database.
2207    // 
2208    //  Parameters:
2209    //       columnIndex - the first column is 1, the second is 2, ...
2210    //       x - the new column value
2211    //  Throws:
2212    //       TSQLException - if a database access error occurs 
2213 
2214    UpdateBytes(FindColumn(columnName),x);
2215 }
2216 
2217 //___________________________________________________________________
2218 void ODBCResultSet::UpdateDate( const TString& columnName,
2219                                 const TSQLDate& x )
2220 {
2221    // Updates a column with a TSQLDate value. The UpdateXXX methods
2222    // are used to update column values in the current row, 
2223    // or the insert row. The UpdateXXX methods do not update the
2224    // underlying database; instead the UpdateRow() or InsertRow() 
2225    // methods are called to update the database.
2226    // 
2227    //  Parameters:
2228    //       columnIndex - the first column is 1, the second is 2, ...
2229    //       x - the new column value
2230    //  Throws:
2231    //       TSQLException - if a database access error occurs 
2232 
2233    UpdateDate(FindColumn(columnName),x);
2234 }
2235 
2236 //___________________________________________________________________
2237 void ODBCResultSet::UpdateTime( const TString& columnName,
2238                                 const TSQLTime& x )
2239 {
2240    // Updates a column with a TSQLTime value. The UpdateXXX methods
2241    // are used to update column values in the current row, 
2242    // or the insert row. The UpdateXXX methods do not update the
2243    // underlying database; instead the UpdateRow() or InsertRow() 
2244    // methods are called to update the database.
2245    // 
2246    //  Parameters:
2247    //       columnIndex - the first column is 1, the second is 2, ...
2248    //       x - the new column value
2249    //  Throws:
2250    //       TSQLException - if a database access error occurs 
2251    
2252    UpdateTime(FindColumn(columnName),x);
2253 }
2254 
2255 //___________________________________________________________________
2256 void ODBCResultSet::UpdateTimestamp( const TString& columnName,
2257                                      const TSQLTimestamp& x )
2258 {
2259    // Updates a column with a TSQLTimestamp value. The update methods
2260    // are used to update column values in the current row, 
2261    // or the insert row. The UpdateXXX methods do not update the
2262    // underlying database; instead the UpdateRow() or InsertRow() 
2263    // methods are called to update the database.
2264    // 
2265    //  Parameters:
2266    //       columnIndex - the first column is 1, the second is 2, ...
2267    //       x - the new column value
2268    //  Throws:
2269    //       TSQLException - if a database access error occurs
2270    
2271    UpdateTimestamp(FindColumn(columnName),x);
2272 }   
2273 
2274 //___________________________________________________________________
2275 void ODBCResultSet::UpdateAsciiStream( const TString& columnName,
2276                                        TBuffer* x,
2277                                        Int_t length )
2278 {
2279    // Updates a column with an ascii stream value. The update methods
2280    // are used to update column values in the current row, 
2281    // or the insert row. The UpdateXXX methods do not update the
2282    // underlying database; instead the UpdateRow() or InsertRow() 
2283    // methods are called to update the database.
2284    // 
2285    //  Parameters:
2286    //       columnIndex - the first column is 1, the second is 2, ...
2287    //       x - the new column value
2288    //       length - length of stream
2289    //  Throws:
2290    //       TSQLException - if a database access error occurs
2291 
2292    UpdateAsciiStream(FindColumn(columnName),x,length);
2293 }
2294 
2295 //___________________________________________________________________
2296 void ODBCResultSet::UpdateBinaryStream( const TString& columnName,
2297                                         TBuffer* x,
2298                                         Int_t length )
2299 {
2300    // Updates a column with a binary stream value. The update methods
2301    // are used to update column values in the current row, 
2302    // or the insert row. The UpdateXXX methods do not update the
2303    // underlying database; instead the UpdateRow() or InsertRow() 
2304    // methods are called to update the database.
2305    // 
2306    //  Parameters:
2307    //       columnIndex - the first column is 1, the second is 2, ...
2308    //       x - the new column value
2309    //       length - length of stream
2310    //  Throws:
2311    //       TSQLException - if a database access error occurs
2312    
2313    UpdateBinaryStream(FindColumn(columnName),x,length); 
2314 }
2315 
2316 //___________________________________________________________________
2317 void ODBCResultSet::UpdateObject(const TString& columnName,TObject* x)
2318 {
2319    // Updates a column with a ROOT object. The update methods
2320    // are used to update column values in the current row, 
2321    // or the insert row. The UpdateXXX methods do not update the
2322    // underlying database; instead the UpdateRow() or InsertRow() 
2323    // methods are called to update the database.
2324    // 
2325    //  Parameters:
2326    //       columnIndex - the first column is 1, the second is 2, ...
2327    //       x - the new column value
2328    //       length - length of stream
2329    //  Throws:
2330    //       TSQLException - if a database access error occurs
2331    
2332    UpdateObject(FindColumn(columnName),x); 
2333 }
2334 
2335 //___________________________________________________________________
2336 void ODBCResultSet::InsertRow()
2337 {
2338    // Inserts the contents of the insert row into the result set
2339    // and the database. Must be on the insert row when this method
2340    // is called.
2341    //
2342    //  Throws:
2343    //     TSQLException - if a database access error occurs, if 
2344    //     called when not on the insert row, or if not all of 
2345    //     non-nullable columns in the insert row have been given 
2346    //     a value.
2347 
2348    if(!fImp) { Destroyed(); return; }
2349    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
2350 
2351    try {
2352       rs->insertRow();
2353 
2354    } catch(odbc::SQLException& e) {
2355       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
2356                                 ODBCXX_STRING_CSTR(e.getSQLState()),
2357                                 e.getErrorCode()) );
2358    }
2359 }
2360 
2361 //___________________________________________________________________
2362 void ODBCResultSet::UpdateRow()
2363 {
2364    // Updates the underlying database with the new contents of
2365    // the current row. Cannot be called when on the insert row.
2366    //
2367    //  Throws:
2368    //       TSQLException - if a database access error occurs or if
2369    //       called when on the insert row
2370 
2371    if(!fImp) { Destroyed(); return; }
2372    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
2373    
2374    try {      
2375       rs->updateRow();
2376 
2377    } catch(odbc::SQLException& e) {
2378       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
2379                                 ODBCXX_STRING_CSTR(e.getSQLState()),
2380                                 e.getErrorCode()) );
2381    }
2382 }
2383 
2384 //___________________________________________________________________
2385 void ODBCResultSet::DeleteRow()
2386 {
2387    // Deletes the current row from the result set and the underlying 
2388    // database. Cannot be called when on the insert row.
2389    //
2390    //  Throws:
2391    //       TSQLException - if a database access error occurs or 
2392    //       if called when on the insert row.
2393    
2394    if(!fImp) { Destroyed(); return; }
2395    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
2396    
2397    try {      
2398       rs->deleteRow();
2399 
2400    } catch(odbc::SQLException& e) {
2401       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
2402                                 ODBCXX_STRING_CSTR(e.getSQLState()),
2403                                 e.getErrorCode()) );
2404    }
2405 }
2406 
2407 //___________________________________________________________________
2408 void ODBCResultSet::RefreshRow()
2409 {
2410    // Refreshes the current row with its most recent value in
2411    // the database. Cannot be called when on the insert row. 
2412    // The RefreshRow() method provides a way for an application to
2413    // explicitly tell the driver to refetch a row(s) from the
2414    // database. An application may want to call RefreshRow() when 
2415    // caching or prefetching is being done by the driver to
2416    // fetch the latest value of a row from the database. The 
2417    // driver may actually refresh multiple rows at once if the 
2418    // fetch size is greater than one. All values are refetched
2419    // subject to the transaction isolation level and cursor 
2420    // sensitivity. If RefreshRow() is called after calling UpdateXXX,
2421    // but before calling UpdateRow(), then the updates made to the 
2422    // row are lost. Calling the method RefreshRow() frequently will 
2423    // likely slow performance.
2424    //
2425    //  Throws:
2426    //       TSQLException - if a database access error occurs or 
2427    //       if called when on the insert row
2428    
2429    if(!fImp) { Destroyed(); return; }
2430    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
2431    
2432    try {      
2433       rs->refreshRow();
2434 
2435    } catch(odbc::SQLException& e) {
2436       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
2437                                 ODBCXX_STRING_CSTR(e.getSQLState()),
2438                                 e.getErrorCode()) );
2439    }
2440 }
2441 
2442 //___________________________________________________________________
2443 void ODBCResultSet::CancelRowUpdates()
2444 {
2445    // Cancels the updates made to a row. This method may be
2446    // called after calling an UpdateXXX method(s) and before 
2447    // calling UpdateRow() to rollback the updates made to a row. 
2448    // If no updates have been made or UpdateRow() has already been 
2449    // called then this method has no effect.
2450    //
2451    //   Throws:
2452    //        TSQLException - if a database access error occurs or if 
2453    //         called when on the insert row
2454   
2455    if(!fImp) { Destroyed(); return; }
2456    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
2457    
2458    try {      
2459       rs->cancelRowUpdates();
2460 
2461    } catch(odbc::SQLException& e) {
2462       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
2463                                 ODBCXX_STRING_CSTR(e.getSQLState()),
2464                                 e.getErrorCode()) );
2465    }
2466 }
2467 
2468 //___________________________________________________________________
2469 void ODBCResultSet::MoveToInsertRow()
2470 {
2471    //  Moves the cursor to the insert row. The current cursor
2472    //  position is remembered while the cursor is positioned on 
2473    //  the insert row. The insert row is a special row associated 
2474    //  with an updatable result set. It is essentially a buffer 
2475    //  where a new row may be constructed by calling the UpdateXXX 
2476    //  methods prior to inserting the row into the result set. 
2477    //  Only the UpdateXXX, GetXXX, and InsertRow() methods may be 
2478    //  called when the cursor is on the insert row.
2479    //  All of the columns in a result set must be given a value 
2480    //  each time this method is called before calling InsertRow(). 
2481    //  The method UpdateXXX must be called before a GetXXX method 
2482    //  can be called on a column value.
2483    //
2484    //  Throws:
2485    //       TSQLException - if a database access error occurs 
2486    //       or the result set is not updatable
2487    
2488    if(!fImp) { Destroyed(); return; }
2489    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
2490    
2491    try {
2492       rs->moveToInsertRow();
2493 
2494    } catch(odbc::SQLException& e) {
2495       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
2496                                 ODBCXX_STRING_CSTR(e.getSQLState()),
2497                                 e.getErrorCode()) );
2498    }
2499 }
2500 
2501 //___________________________________________________________________
2502 void ODBCResultSet::MoveToCurrentRow()
2503 {
2504    // Moves the cursor to the remembered cursor position,
2505    // usually the current row. This method has no effect if the 
2506    // cursor is not on the insert row.
2507    //
2508    //  Throws:
2509    //       TSQLException - if a database access error occurs or 
2510    //       the result set is not updatable
2511    
2512    if(!fImp) { Destroyed(); return; }
2513    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
2514    
2515    try {
2516       rs->moveToCurrentRow();
2517 
2518    } catch(odbc::SQLException& e) {
2519       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
2520                                 ODBCXX_STRING_CSTR(e.getSQLState()),
2521                                 e.getErrorCode()) );
2522    }
2523 }
2524 
2525 //___________________________________________________________________
2526 TSQLRow* ODBCResultSet::Next()
2527 {
2528    // Moves the cursor down one row from its current position. A
2529    // TSQLResultSet cursor is initially positioned before the first 
2530    // row; the first call to next makes the first row the current 
2531    // row; the second call makes the second row the current row, 
2532    // and so on.
2533    // 
2534    // If an input stream is open for the current row, a call to the
2535    // method next will implicitly close it. The TSQLResultSet's 
2536    // warning chain is cleared when a new row is read.
2537    //
2538    //  Returns:
2539    //       pointer to TSQLRow(kTRUE) if the new current row is valid; 
2540    //       null(kFALSE) if there are no more rows
2541    //  Throws:
2542    //       TSQLException - if a database access error occurs
2543 
2544    Bool_t return_value=kFALSE;
2545    
2546    if(!fImp) { Destroyed(); return 0; }
2547    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
2548    
2549    try {      
2550       return_value = rs->next();
2551 
2552    } catch(odbc::SQLException& e) {
2553       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
2554                                 ODBCXX_STRING_CSTR(e.getSQLState()),
2555                                 e.getErrorCode()) );
2556       return_value = 0;
2557    }
2558    return return_value ? fRow->Set(this) : 0;
2559 }
2560 
2561 //___________________________________________________________________
2562 TSQLRow* ODBCResultSet::First()
2563 {
2564    // Moves the cursor to the first row in the result set.
2565    //
2566    //  Returns:
2567    //       pointer to TSQLRow(kTRUE)  if the cursor is on a valid row; 
2568    //       null(kFALSE) if there are no rows in the result set
2569    //  Throws:
2570    //       TSQLException - if a database access error occurs or 
2571    //       the result set type is kTYPE_FORWARD_ONLY
2572 
2573 
2574    Bool_t return_value = kFALSE;
2575    
2576    if(!fImp) { Destroyed(); return 0; }
2577    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
2578    
2579    try {      
2580       return_value = rs->first();
2581 
2582    } catch(odbc::SQLException& e) {
2583       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
2584                                 ODBCXX_STRING_CSTR(e.getSQLState()),
2585                                 e.getErrorCode()) );
2586       return_value = 0;
2587    }
2588    return return_value  ? fRow->Set(this) : 0;
2589 }
2590 
2591 //___________________________________________________________________
2592 TSQLRow* ODBCResultSet::Absolute( Int_t row )
2593 {
2594    // Moves the cursor to the given row number in the result set. 
2595    // If the row number is positive, the cursor moves to the 
2596    // given row number with respect to the beginning of the 
2597    // result set. The first row is row 1, the second is row 2, 
2598    // and so on. 
2599    //
2600    //  If the given row number is negative, the cursor moves to an
2601    // absolute row position with respect to the end of the result 
2602    // set. For example, calling Absolute(-1) positions the cursor
2603    // on the last row, Absolute(-2) indicates the next-to-last row, 
2604    // and so on. 
2605    //
2606    //  An attempt to position the cursor beyond the first/last row 
2607    // in the result set leaves the cursor before/after the first/last
2608    // row, respectively. 
2609    //
2610    //  Note: calling Absolute(1) is the same as calling First(). 
2611    //        calling Absolute(-1) is the same as calling Last().
2612    //
2613    //  Returns:
2614    //       pointer to TSQLRow(kTRUE)  if the cursor is on the result set; 
2615    //       null(kFALSE) otherwise
2616    //  Throws:
2617    //       TSQLException - if a database access error occurs or
2618    //       row is 0, or result set type is kTYPE_FORWARD_ONLY
2619 
2620    Bool_t return_value = kFALSE;
2621    
2622    if(!fImp) { Destroyed(); return 0; }
2623    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
2624       
2625    try {     
2626       return_value = rs->absolute(row); 
2627    
2628    } catch(odbc::SQLException& e) {
2629       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
2630                                 ODBCXX_STRING_CSTR(e.getSQLState()),
2631                                 e.getErrorCode()) );
2632       return_value = 0;
2633    }
2634    return return_value  ? fRow->Set(this) : 0;
2635 }
2636 
2637 //___________________________________________________________________
2638 TSQLRow* ODBCResultSet::Relative(Int_t rows)
2639 {
2640    // Moves the cursor a relative number of rows, either positive or
2641    // negative. Attempting to move beyond the first/last row in 
2642    // the result set positions the cursor before/after the the
2643    // first/last row. Calling Relative(0) is valid, but does not 
2644    // change the cursor position. 
2645    //
2646    //  Note: Calling Relative(1) is different from calling Next() 
2647    //       because is makes sense to call Next() when there is 
2648    //       no current row, for example, when the cursor is 
2649    //       positioned before the first row or after the last row
2650    //       of the result set.
2651    //  Returns:
2652    //       pointer to TSQLRow(kTRUE)  if the cursor is on a row; 
2653    //       null(kFALSE) otherwise
2654    //  Throws:
2655    //       TSQLException - if a database access error occurs, 
2656    //       there is no current row, or the result set type 
2657    //       is kTYPE_FORWARD_ONLY
2658 
2659    Bool_t return_value = kFALSE;
2660    
2661    if(!fImp) { Destroyed(); return 0; }
2662    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
2663    
2664    try {
2665       return_value = rs->relative(rows);
2666 
2667    } catch(odbc::SQLException& e) {
2668       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
2669                                 ODBCXX_STRING_CSTR(e.getSQLState()),
2670                                 e.getErrorCode()) );
2671       return_value = 0;
2672    }
2673    return return_value  ? fRow->Set(this) : 0;
2674 }
2675 
2676 //___________________________________________________________________
2677 TSQLRow* ODBCResultSet::Previous()
2678 {
2679    // Moves the cursor to the previous row in the result set. 
2680    //
2681    //  Note: Previous() is not the same as Relative(-1)
2682    //       because it makes sense to call Previous()
2683    //       when there is no current row.
2684    //
2685    //  Returns:
2686    //       pointer to TSQLRow(kTRUE)  if the cursor is on a valid row; 
2687    //       null(kFALSE) if it is off the result set
2688    //  Throws:
2689    //       TSQLException - if a database access error occurs or 
2690    //       the result set type is kTYPE_FORWARD_ONLY
2691 
2692    Bool_t return_value = kFALSE;
2693    
2694    if(!fImp) { Destroyed(); return 0; }
2695    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
2696       
2697    try {
2698       return_value = rs->previous(); 
2699   
2700    } catch(odbc::SQLException& e) {
2701       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
2702                                 ODBCXX_STRING_CSTR(e.getSQLState()),
2703                                 e.getErrorCode()) );
2704       return_value = 0;
2705    }
2706    return return_value  ? fRow->Set(this) : 0;   
2707 }
2708 
2709 //___________________________________________________________________
2710 TSQLRow* ODBCResultSet::Last()
2711 {
2712    // Moves the cursor to the last row in the result set.
2713    //
2714    //  Returns:
2715    //       pointer to TSQLRow(kTRUE)  if the cursor is on a valid row; 
2716    //       null(kFALSE) if there are norows in the result set
2717    //
2718    //  Throws:
2719    //       TSQLException - if a database access error occurs or 
2720    //       the result set type is kTYPE_FORWARD_ONLY
2721 
2722    Bool_t return_value = kFALSE;
2723    
2724    if(!fImp) { Destroyed(); return 0; }
2725    odbc::ResultSet* rs = (odbc::ResultSet*)fImp;
2726       
2727    try {     
2728       return_value = rs->last();
2729 
2730    } catch(odbc::SQLException& e) {
2731       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
2732                                 ODBCXX_STRING_CSTR(e.getSQLState()),
2733                                 e.getErrorCode()) );
2734       return_value = 0;
2735    }
2736    return return_value  ? fRow->Set(this) : 0;
2737 }
2738 
2739 //___________________________________________________________________
2740 void ODBCResultSet::Close(Option_t * /* option */)
2741 {
2742    // Releases this TSQLResultSet object's database and resources
2743    // immediately instead of waiting for this to happen when it is 
2744    // automatically closed. 
2745    //
2746    // Note: A TSQLResultSet is automatically closed by the 
2747    // statement that generated it when that statement 
2748    // is closed, re-executed, or is used to retrieve the next
2749    // result from a sequence of multiple results. A TSQLResultSet 
2750    // is also automatically closed when it is garbage collected.
2751    //
2752    //  Throws:
2753    //       TSQLException - if a database access error occurs
2754   
2755    if(!fImp) { Destroyed(); return; }
2756 
2757    try {       
2758       if(fMetaData) delete ((ODBCResultSetMetaData*)fMetaData); 
2759       if(fRow) delete fRow; 
2760 
2761       if(fImp) {
2762          odbc::ResultSet* imp = (odbc::ResultSet*)fImp;  
2763          delete  imp;
2764       }
2765    } catch(odbc::SQLException& e) {
2766       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
2767                                 ODBCXX_STRING_CSTR(e.getSQLState()),
2768                                 e.getErrorCode()) );
2769    }
2770    
2771    fMetaData = 0;   
2772    fRow = 0;
2773    fImp = 0;
2774    Destroyed();
2775 }