Back to home page

sPhenix code displayed by LXR

 
 

    


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

0001 // $Id: ODBCStatement.cxx,v 1.1.1.1 2004/02/18 20:58:02 dave 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 // The object used for executing a static SQL statement and 
0031 // obtaining the results produced by it. 
0032 // 
0033 // Only one TSQLResultSet per ODBCStatement can be open at any point 
0034 // in time. Therefore, if the reading of one TSQLResultSet is
0035 // interleaved with the reading of another, each must have been 
0036 // generated by different ODBCStatements. All statement execute 
0037 // methods  implicitly close a statment's current TSQLResultSet if 
0038 // an open  one exists. 
0039 //
0040 // See also: 
0041 //    TSQLConnection::CreateStatement(), TSQLResultSet 
0042 //    TSQLCallableStatement TSQLPreparedStatement
0043 //Begin_Html
0044 /*
0045 <P>
0046    The <TT>ODBCStatement</TT> class encapsulates SQL queries to your database. 
0047 Using several methods, these calls return objects that contain the 
0048 results of your SQL query. When you execute an SQL query, the data 
0049 that is returned to you is commonly called the result set. You can 
0050 choose from several result sets, depending on your needs:
0051 <UL>
0052 <LI><TT>TSQLResultSet* ExecuteQuery( const TString& sqlStatement)<BR></TT>
0053 This method sends the SQL query contained in <TT>sqlStatement</TT>
0054 and returns a single set of results. This method is best used 
0055 in sending  <TT>SELECT</TT> statements. These statements typically 
0056 return a result set. This method implicitly deletes previous resultset.
0057 
0058 <LI><TT>Int_t ExecuteUpdate( const TString& sqlStatement )<BR></TT>
0059 This method sends the SQL query contained in <TT>sqlStatement</TT> 
0060 and returns an integer. This method is useful when you send SQL 
0061 <TT>INSERT</TT>s,  <TT>DELETE</TT>s, and <TT>UPDATE</TT>s.  These commands return 
0062 a count of rows  that were affected  by your query. This statement 
0063 should not be used for queries that  return result sets.
0064 
0065 <LI><TT>Bool_t Execute( const TString& sqlStatement )<BR></TT>
0066 This method sends the <TT>sqlStatement</TT> to the database and returns 
0067 <TT>kTRUE</TT> if the statement returns a result set or <TT>kFALSE</TT> if the 
0068 statement returns an integer. This method is best used when multiple 
0069 result sets can be returned.
0070 </UL>
0071 <P>
0072 Use the following methods to easily navigate the results a query returns:
0073 <UL>
0074 <LI><TT>Bool_t GetMoreResults()<BR> </TT>
0075 This moves to the next result set in the <TT>ODBCStatement</TT>. This, 
0076 like the <TT>Execute()</TT> method, returns <TT>kTRUE</TT> if the  next 
0077 result is a result set or <TT>kFALSE</TT> if it is an  integer.  
0078 If you have  already retrieved a <TT>TSQLResultSet</TT> from  the  
0079 <TT>ODBCStatement</TT>, this method will close it before returning.
0080 
0081 <LI><TT>TSQLResultSet* GetResultSet()<BR></TT>
0082 This method returns to you a result set in a <TT>TSQLResultSet</TT> 
0083 object. This result set is the current result set.
0084 
0085 <LI><TT>Int_t GetUpdateCount()<BR></TT>
0086 This method returns to you the integer result that an 
0087 <TT>Execute()</TT> method returned.
0088 </UL>
0089 <P>
0090 */
0091 //End_Html
0092 /////////////////////////////////////////////////////////////////////
0093 
0094 #include "ODBCStatement.h"
0095 #include "ODBCResultSet.h"
0096 #include <RDBC/TSQLConnection.h>
0097 #include <TList.h>
0098 #include <RDBC/odbc++/statement.h>
0099 #include <RDBC/odbc++/resultset.h>
0100 
0101 using namespace odbc;
0102 
0103 ClassImpQ(ODBCStatement)
0104 
0105 /////////////////////////////////////////////////////////////////////
0106 //___________________________________________________________________
0107 ODBCStatement::ODBCStatement( TSQLConnection* con, void* imp ):
0108       TSQLStatement(con,imp)
0109 {
0110    // ctor
0111 }
0112 
0113 //___________________________________________________________________
0114 ODBCStatement::~ODBCStatement( )
0115 {
0116    // Destructor.
0117    //
0118    //  Note: When a ODBCStatement is closed, its current 
0119    //       TSQLResultSet,  if one exists, is also closed.
0120    // 
0121  
0122    odbc::Statement* imp = (odbc::Statement*)fImp;
0123 
0124    try { 
0125       if(imp) delete imp;
0126    } catch(odbc::SQLException& e) {
0127       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0128                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0129                                 e.getErrorCode()) );
0130    }
0131 
0132    // implementation part of fCurrentResult is deleted with statement
0133    if(fCurrentResult) ((ODBCResultSet*)fCurrentResult)->fImp = 0;
0134    fImp = 0;
0135 }
0136 
0137 //___________________________________________________________________
0138 TSQLResultSet* ODBCStatement::ExecuteQuery( const TString& sql )
0139 {
0140    // Executes a SQL statement that returns a single TSQLResultSet
0141    //
0142    // This method also implicitly closes current TSQLResultSet 
0143    //
0144    // Returns:
0145    //       a TSLResultSet that contains the data produced by the query; 
0146    //       NULL - in case of error
0147    //
0148    //   Throws:
0149    //       TSQLException - if a database access error occurs
0150 
0151    if(!fImp) { Destroyed(); return 0; }
0152    odbc::Statement* stmt = (odbc::Statement*)fImp;
0153    odbc::ResultSet* rs = 0; 
0154    ClearWarnings();
0155 
0156    if(fCurrentResult)  { delete fCurrentResult; fCurrentResult = 0; }
0157 
0158    try {
0159       rs = stmt->executeQuery(ODBCXX_STRING_C(sql.Data()));
0160    } catch(odbc::SQLException& e) {
0161       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0162                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0163                                 e.getErrorCode()) );
0164       if(rs) delete rs;
0165       fCurrentResult = 0;
0166       return 0;
0167    }
0168    
0169    return fCurrentResult = new ODBCResultSet(this,(void*)rs);;
0170 }
0171 
0172 //___________________________________________________________________
0173 Bool_t ODBCStatement::Execute( const TString& sql )
0174 {
0175    // Executes a SQL statement that may return multiple results.
0176    // Under some (uncommon) situations a single SQL statement may 
0177    // return multiple result sets and/or update counts. Normally you 
0178    // can ignore this unless you are (1) executing a stored
0179    // procedure that you know may return multiple results or (2) you 
0180    // are dynamically executing an unknown SQL string. The methods 
0181    // execute, GetMoreResults(), GetResultSet(), and GetUpdateCount()
0182    // let you navigate through multiple results.
0183    //  The execute method executes a SQL statement and indicates the 
0184    // form of the first result. You can then use GetResultSet() or
0185    // GetUpdateCount() to retrieve the result, and GetMoreResults() 
0186    // to move to any subsequent result(s).
0187    //
0188    // Parameters:
0189    //          sql - any SQL statement
0190    // Returns:
0191    //          kTRUE if the next result is a TSQLResultSet; 
0192    //          kFALSE if it is an update count or there are no more
0193    //          results
0194    // Throws:
0195    //            TSQLException - if a database access error occurs
0196    // See Also: 
0197    //       GetResultSet(), GetUpdateCount(), GetMoreResults()
0198   
0199    if(!fImp) { Destroyed(); return kFALSE; }
0200 
0201    Bool_t return_value = kFALSE;
0202    ClearWarnings();
0203    odbc::Statement* stmt = (odbc::Statement*)fImp;
0204 
0205    if(fCurrentResult) { delete fCurrentResult; fCurrentResult = 0; }
0206  
0207    try {
0208       return_value = (Bool_t)stmt->execute(ODBCXX_STRING_C(sql.Data()));  
0209    } catch(odbc::SQLException& e) {
0210       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0211                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0212                                 e.getErrorCode()) );
0213       return_value = kFALSE;
0214    }
0215    return return_value;
0216 }
0217 
0218 //___________________________________________________________________
0219 Int_t ODBCStatement::ExecuteUpdate( const TString& sql )
0220 {
0221    // Executes an SQL INSERT, UPDATE or DELETE statement. 
0222    // In addition, SQL statements that return nothing, 
0223    // such as SQL DDL statements, can be executed.
0224    //
0225    //  Parameters:
0226    //      sql - a SQL INSERT, UPDATE or DELETE statement or 
0227    //            a SQL statement that  returns nothing
0228    //
0229    //  Returns:
0230    //      either the row count for INSERT, UPDATE or DELETE or 
0231    //      0 for SQL statements that return nothing
0232    //  Throws:
0233    //      TSQLException - if a database access error occurs
0234    
0235    if(!fImp) { Destroyed(); return 0; }
0236 
0237    Int_t return_value = 0;
0238    ClearWarnings();
0239    odbc::Statement* stmt = (odbc::Statement*)fImp;
0240 
0241    if(fCurrentResult)  { delete fCurrentResult; fCurrentResult = 0; }
0242 
0243    try {
0244       return_value = stmt->executeUpdate(ODBCXX_STRING_C(sql.Data()));      
0245    } catch(odbc::SQLException& e) {
0246       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0247                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0248                                 e.getErrorCode()) );
0249       return_value = 0;
0250    }
0251    return return_value;
0252 }
0253 
0254 //___________________________________________________________________
0255 TSQLResultSet* ODBCStatement::GetResultSet()
0256 {
0257    // Returns the current result as a TSQLResultSet object. 
0258    // This method should be called only once per result.
0259    //
0260    // This method also implicitly closes any current TSQLResultSet 
0261    //   
0262    // Returns:
0263    //       the current result as a TSQLResultSet; null if the result 
0264    //       is an update count or there are no more results
0265    // Throws:
0266    //       TSQLException - if a database access error occurs
0267    // See Also: 
0268    //       Execute(const TString&)
0269    
0270    if(!fImp) { Destroyed(); return 0; }
0271    odbc::ResultSet* rs = 0;
0272    odbc::Statement* stmt = (odbc::Statement*)fImp;
0273 
0274    if(fCurrentResult) { delete fCurrentResult; fCurrentResult = 0; }
0275 
0276    try {     
0277       rs = stmt->getResultSet(); 
0278    } catch(odbc::SQLException& e) {
0279       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0280                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0281                                 e.getErrorCode()) );
0282       if(rs) delete rs;
0283       fCurrentResult = 0;
0284       return 0;
0285    }
0286 
0287    return fCurrentResult = new ODBCResultSet(this,(void*)rs); 
0288 }   
0289 
0290 //___________________________________________________________________
0291 Int_t ODBCStatement::GetUpdateCount()
0292 {
0293    // Returns the current result as an update count; 
0294    // if there are no more results, -1 is returned.
0295    // This method should be called only once per result.
0296    //
0297    // Returns:
0298    //       the current result as an update count; -1 if it is a 
0299    //       TSQLResultSet or there are no more results
0300    // Throws:
0301    //       TSQLException - if a database access error occurs
0302    // See Also: 
0303    //       Execute(const TString&)
0304    
0305    if(!fImp) { Destroyed(); return 0; }
0306 
0307    Int_t return_value = 0;
0308    odbc::Statement* stmt = (odbc::Statement*)fImp;
0309       
0310    try {
0311       return_value = stmt->getUpdateCount();
0312    } catch(odbc::SQLException& e) {
0313       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0314                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0315                                 e.getErrorCode()) );
0316       return  0;
0317    }
0318    return return_value;
0319 }
0320 
0321 //___________________________________________________________________
0322 Bool_t ODBCStatement::GetMoreResults()
0323 {
0324    // Moves to a ODBCStatement's next result. It returns kTRUE if 
0325    // this result is a TSQLResultSet. 
0326    // 
0327    // There are no more results when 
0328    //       (!GetMoreResults() && (GetUpdateCount() == -1)
0329    //
0330    // Returns:
0331    //    kTRUE if the next result is a TSQLResultSet; 
0332    //    kFALSE if it is an update count or there are no more results
0333    //
0334    // Throws:
0335    //       TSQLException - if a database access error occurs
0336    // See Also: 
0337    //       Execute(const TString&)
0338 
0339    Bool_t return_value = kFALSE;
0340    
0341    if(!fImp) { Destroyed(); return return_value; }
0342    odbc::Statement* stmt = (odbc::Statement*)fImp;
0343       
0344    try {
0345       return_value = (Bool_t)stmt->getMoreResults();      
0346    } catch(odbc::SQLException& e) {
0347       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0348                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0349                                 e.getErrorCode()) );
0350       return  kFALSE;
0351    }
0352    return return_value;
0353 }
0354 
0355 //___________________________________________________________________
0356 Int_t ODBCStatement::GetMaxFieldSize()
0357 {
0358    // Returns the maximum number of bytes allowed for any column 
0359    // value. This limit is the maximum number of bytes that can be
0360    // returned for any column value. The limit applies only to 
0361    // kBINARY, kVARBINARY, kLONGVARBINARY, kCHAR, kVARCHAR, and 
0362    // kLONGVARCHAR columns (see TSQLTypes.h). If the limit is exceeded, 
0363    // the excess data  is silently discarded.
0364    //
0365    // Returns:
0366    //    the current max column size limit; zero means unlimited
0367    // Throws:
0368    //    TSQLException - if a database access error occurs
0369 
0370    if(!fImp) { Destroyed(); return 0; }
0371 
0372    Int_t return_value = 0;
0373    odbc::Statement* stmt = (odbc::Statement*)fImp;
0374    
0375    try {
0376       return_value = stmt->getMaxFieldSize();
0377    } catch(odbc::SQLException& e) {
0378       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0379                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0380                                 e.getErrorCode()) );
0381       return 0;
0382    }
0383    return return_value;
0384 }
0385 
0386 //___________________________________________________________________
0387 void ODBCStatement::SetMaxFieldSize( Int_t max )
0388 {
0389    // Sets the limit for the maximum number of bytes in a column to 
0390    // the given number of bytes. This is the maximum number of bytes 
0391    // that can be returned for any column value. This limit applies 
0392    // only to kBINARY, kVARBINARY, kLONGVARBINARY, kCHAR, kVARCHAR,
0393    // and kLONGVARCHAR fields (see TSQLTypes.h) . If the limit is exceeded, 
0394    // the excess  data is silently discarded. For maximum portability, 
0395    // use values greater than 256.
0396    //
0397    // Parameters:
0398    //       max - the new max column size limit; zero means unlimited
0399    // Throws:
0400    //       TSQLException - if a database access error occurs
0401    
0402    if(!fImp) { Destroyed(); return; }
0403    odbc::Statement* stmt = (odbc::Statement*)fImp;
0404    
0405    try {
0406       stmt->setMaxFieldSize(max);   
0407    } catch(odbc::SQLException& e) {
0408       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0409                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0410                                 e.getErrorCode()) );
0411    }
0412 }
0413 
0414 //___________________________________________________________________
0415 Int_t ODBCStatement::GetMaxRows()
0416 {
0417    // Retrieves the maximum number of rows that a TSQLResultSet can 
0418    // contain. If the limit is exceeded, the excess rows are silently 
0419    // dropped.
0420    //
0421    // Returns:
0422    //       the current max row limit; zero means unlimited
0423    // Throws:
0424    //       TSQLException - if a database access error occurs
0425 
0426    if(!fImp) { Destroyed(); return 0; }
0427 
0428    Int_t return_value = 0;
0429    odbc::Statement* stmt = (odbc::Statement*)fImp;
0430    
0431    try {
0432       return_value = stmt->getMaxRows();
0433    } catch(odbc::SQLException& e) {
0434       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0435                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0436                                 e.getErrorCode()) );
0437       return 0;
0438    }
0439    return return_value;
0440 }
0441 
0442 //___________________________________________________________________
0443 void ODBCStatement::SetMaxRows( Int_t max )
0444 {
0445    // Sets the limit for the maximum number of rows that any 
0446    // TSQLResultSet can contain to the given number. If the limit is 
0447    // exceeded, the excess rows are silently dropped.
0448    //
0449    // Parameters:
0450    //       max - the new max rows limit; zero means unlimited
0451    // Throws:
0452    //       TSQLException - if a database access error occurs
0453    
0454    if(!fImp) { Destroyed(); return; }
0455    odbc::Statement* stmt = (odbc::Statement*)fImp;
0456    
0457    try {
0458       stmt->setMaxRows(max);  
0459    } catch(odbc::SQLException& e) {
0460       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0461                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0462                                 e.getErrorCode()) );
0463    }
0464 }
0465 
0466 //___________________________________________________________________
0467 void ODBCStatement::SetEscapeProcessing( Bool_t enable )
0468 {
0469    // Sets escape processing on or off. If escape scanning is on 
0470    // (the default), the driver will do escape substitution before 
0471    // sending the SQL to the database.
0472    // 
0473    // Note:
0474    //    Since prepared statements have usually been parsed prior to 
0475    //    making this call, disabling escape processing for prepared 
0476    //    statements will have no effect.
0477    //
0478    // Parameters:
0479    //       enable - kTRUE to enable; kFALSE to disable
0480    // Throws:
0481    //       TSQLException - if a database access error occurs
0482    
0483    if(!fImp) { Destroyed(); return; }
0484    odbc::Statement* stmt = (odbc::Statement*)fImp;
0485    
0486    try {
0487       stmt->setEscapeProcessing(enable);
0488    } catch(odbc::SQLException& e) {
0489       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0490                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0491                                 e.getErrorCode()) );
0492    }
0493 }
0494 
0495 //___________________________________________________________________
0496 Bool_t ODBCStatement::GetEscapeProcessing()
0497 {
0498    //  Returns if escape processing is on or off. 
0499    // If escape scanning is on (the default), the driver will do escape 
0500    // substitution before  sending the SQL to the database.
0501    // 
0502    // Note:
0503    //    Since prepared statements have usually been parsed prior to 
0504    //    making this call, disabling escape processing for prepared 
0505    //    statements will have no effect.
0506    //
0507    // Parameters:
0508    //       enable - kTRUE to enable; kFALSE to disable
0509    // Throws:
0510    //       TSQLException - if a database access error occurs
0511 
0512    if(!fImp) { Destroyed(); return kFALSE; }   
0513 
0514    Bool_t return_value = kFALSE;
0515    odbc::Statement* stmt = (odbc::Statement*)fImp;
0516    
0517    try {
0518       return_value = stmt->getEscapeProcessing();
0519    } catch(odbc::SQLException& e) {
0520       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0521                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0522                                 e.getErrorCode()) );
0523       return kFALSE;
0524    }
0525    return return_value;
0526 }
0527 
0528 //___________________________________________________________________
0529 Int_t ODBCStatement::GetQueryTimeout()
0530 {
0531    // Retrieves the number of seconds the driver will wait for a
0532    // ODBCStatement to execute. If the limit is exceeded, a 
0533    // TSQLException is thrown.
0534    //
0535    // Returns:
0536    //    the current query timeout limit in seconds; zero means
0537    //    unlimited
0538    // Throws:
0539    //    TSQLException - if a database access error occurs
0540    
0541    Int_t return_value = 0;
0542    
0543    if(!fImp) { Destroyed(); return return_value; }
0544    odbc::Statement* stmt = (odbc::Statement*)fImp;
0545       
0546    try {
0547       return_value = stmt->getQueryTimeout();
0548    } catch(odbc::SQLException& e) {
0549       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0550                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0551                                 e.getErrorCode()) );
0552       return 0;
0553    }
0554    return return_value;
0555 }
0556 
0557 //___________________________________________________________________
0558 void ODBCStatement::SetQueryTimeout( Int_t seconds )
0559 {
0560    // Sets the number of seconds the driver will wait for a 
0561    // ODBCStatement to execute to the given number of seconds. 
0562    // If the limit is exceeded, a TSQLException is thrown.
0563    //
0564    // Parameters:
0565    //          seconds - the new query timeout limit in seconds; 
0566    //          zero means unlimited
0567    // Throws:
0568    //          TSQLException - if a database access error occurs
0569    
0570    if(!fImp) { Destroyed(); return; }
0571    odbc::Statement* stmt = (odbc::Statement*)fImp;
0572    
0573    try {
0574       stmt->setQueryTimeout(seconds);
0575    } catch(odbc::SQLException& e) {
0576       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0577                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0578                                 e.getErrorCode()) );
0579    }
0580 }
0581 
0582 //___________________________________________________________________
0583 void ODBCStatement::Cancel() 
0584 {
0585    // Cancels this statement object if both the DBMS and driver 
0586    // support aborting an SQL statement. This method can be used by 
0587    // one thread to cancel a statement that is being executed by 
0588    // another thread.
0589    //
0590    // Throws:
0591    //       TSQLException - if a database access error occurs
0592    
0593    if(!fImp) { Destroyed(); return; }
0594    odbc::Statement* stmt = (odbc::Statement*)fImp;
0595    
0596    try {
0597       stmt->cancel();
0598    } catch(odbc::SQLException& e) {
0599       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0600                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0601                                 e.getErrorCode()) );
0602    }
0603 }
0604 
0605 //___________________________________________________________________
0606 void ODBCStatement::Close()
0607 {
0608    // Avoid using this method. Use delete ODBCStatement instead.
0609    //
0610    //  Note: When a ODBCStatement is closed, its current 
0611    //       TSQLResultSet,  if one exists, is also closed.
0612    //
0613    //     Throws:
0614    //      TSQLException - if a database access error occurs
0615    
0616    if(!fImp) { Destroyed(); return; }
0617           
0618    try {    
0619       if(fCurrentResult)  { 
0620          delete fCurrentResult;
0621          fCurrentResult = 0;
0622       }
0623       ClearBatch();
0624       SafeDelete(fBatches);
0625 
0626       odbc::Statement* imp = (odbc::Statement*)fImp;
0627       if(imp) delete  imp;
0628    } catch(odbc::SQLException& e) {
0629       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0630                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0631                                 e.getErrorCode()) );
0632    }
0633    fImp = 0;
0634    Destroyed();
0635 }
0636 
0637 //___________________________________________________________________
0638 void ODBCStatement::SetCursorName( const TString& name )
0639 {
0640    // Defines the SQL cursor name that will be used by subsequent
0641    // ODBCStatement execute methods. This name can then be used in 
0642    // SQL positioned update/delete statements to identify the 
0643    // current row in the TSQLResultSet generated by this statement. 
0644    // If the database doesn't support positioned update/delete, 
0645    // this method is a noop. To insure that a cursor has the proper 
0646    // isolation level to support updates, the cursor's SELECT 
0647    // statement should be of the form 'SELECT FOR UPDATE ...'. If
0648    // the 'FOR UPDATE' phrase is omitted, positioned updates may 
0649    // fail. 
0650    //
0651    // Note: By definition, positioned update/delete execution must 
0652    //    be done by a different ODBCStatement than the one which 
0653    //    generated the TSQLResultSet being used for positioning.
0654    //    Also, cursor names must be unique within a connection.
0655    //
0656    // Parameters:
0657    //       name - the new cursor name, which must be unique within
0658    //       a connection
0659    // Throws:
0660    //       TSQLException - if a database access error occurs
0661    
0662    if(!fImp) { Destroyed(); return; }
0663    odbc::Statement* stmt = (odbc::Statement*)fImp;
0664    
0665    try {
0666       stmt->setCursorName(ODBCXX_STRING_C(name.Data()));
0667    } catch(odbc::SQLException& e) {
0668       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0669                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0670                                 e.getErrorCode()) );
0671    }
0672 }
0673 
0674 //___________________________________________________________________
0675 void ODBCStatement::SetFetchDirection( Int_t /* direction */ )
0676 {
0677    // Gives the driver a hint as to the direction in which the
0678    // rows in a result set will be processed. The hint applies only 
0679    // to result sets created using this statement object. 
0680    // The default value is TSQLResultSet::kTYPE_FORWARD_ONLY
0681    //
0682    // Note that this method sets the default fetch direction for 
0683    // result sets generated by this statement object.
0684    //
0685    // Parameters:
0686    //    direction - the initial direction for processing rows
0687    // Throws:
0688    //    TSQLException - if a database access error occurs or the 
0689    //                   given direction is not one of 
0690    // 
0691    
0692    if(!fImp) { Destroyed(); return; }
0693 }
0694 
0695 //___________________________________________________________________
0696 Int_t ODBCStatement::GetFetchDirection()
0697 {
0698    // Retrieves the direction for fetching rows from database
0699    // tables that is the default for result sets generated from this 
0700    // statement object. If this statement object has not set 
0701    // a fetch direction by calling the method SetFetchDirection(), 
0702    // the return value is implementation-specific.
0703    //
0704    // Returns:
0705    //       the default fetch direction for result sets generated 
0706    //       from this statement object
0707    // Throws:
0708    //       TSQLException - if a database access error occurs
0709 
0710    return 0;
0711 }
0712 
0713 //___________________________________________________________________
0714 void ODBCStatement::SetFetchSize( Int_t /* rows */ )
0715 {
0716    // Gives the driver a hint as to the number of rows that
0717    // should be fetched from the database when more rows are needed. 
0718    // The number of rows specified affects only result sets created 
0719    // using this statement. If the value specified is zero, then the
0720    // hint is ignored. The default value is zero.
0721    //
0722    // Parameters:
0723    //       rows - the number of rows to fetch
0724    // Throws:
0725    //       TSQLException - if a database access error occurs, or 
0726    //       the condition 0 <= rows <= GetMaxRows() is not satisfied.
0727    
0728    if(!fImp) { Destroyed(); return; }
0729 }
0730 
0731 //___________________________________________________________________
0732 Int_t ODBCStatement::GetFetchSize()
0733 {
0734    // Retrieves the number of result set rows that is the default 
0735    // fetch size for result sets generated from this ODBCStatement 
0736    // object. If this statement object has not set a fetch size
0737    // by calling the method SetFetchSize(), the return value is
0738    // implementation-specific.
0739    //
0740    // Returns:
0741    //       the default fetch size for result sets generated from 
0742    //       this statement object
0743    // Throws:
0744    //       TSQLException - if a database access error occurs
0745    
0746    Int_t return_value = 0;
0747    
0748    if(!fImp) { Destroyed(); return return_value; }
0749    odbc::Statement* stmt = (odbc::Statement*)fImp;
0750    
0751    try {
0752       return_value = stmt->getFetchSize();
0753    } catch(odbc::SQLException& e) {
0754       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0755                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0756                                 e.getErrorCode()) );
0757       return 0;
0758    }
0759    return return_value;
0760 }
0761 
0762 //___________________________________________________________________
0763 Int_t ODBCStatement::GetResultSetConcurrency()
0764 {
0765    // Retrieves the result set concurrency.
0766    //
0767    // enum EResultSetConcurrency{
0768    //       kCONCUR_READ_ONLY,
0769    //       kCONCUR_UPDATABLE
0770    //    };
0771 
0772    Int_t return_value = 0;
0773    
0774    if(!fImp) { Destroyed(); return return_value; }
0775    odbc::Statement* stmt = (odbc::Statement*)fImp;
0776    
0777    try {
0778       return_value = stmt->getResultSetConcurrency();
0779    } catch(odbc::SQLException& e) {
0780       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0781                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0782                                 e.getErrorCode()) );
0783       return 0;
0784    }   
0785    return return_value;
0786 }
0787 
0788 //___________________________________________________________________
0789 Int_t ODBCStatement::GetResultSetType()
0790 {
0791    // Determine the result set type.
0792    //
0793    // enum EResultSetType{
0794    //       kTYPE_FORWARD_ONLY,
0795    //       kTYPE_SCROLL_INSENSITIVE,
0796    //       kTYPE_SCROLL_SENSITIVE
0797    //       };
0798    //
0799      
0800    Int_t return_value = 0;
0801    
0802    if(!fImp) { Destroyed(); return return_value; }
0803    odbc::Statement* stmt = (odbc::Statement*)fImp;
0804    
0805    try {
0806       return_value = stmt->getResultSetType(); 
0807    } catch(odbc::SQLException& e) {
0808       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0809                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0810                                 e.getErrorCode()) );
0811       return 0;
0812    }
0813    return return_value;
0814 }
0815 
0816 //___________________________________________________________________
0817 void ODBCStatement::AddBatch( const TString& sql )
0818 {
0819    // Adds a SQL command to the current batch of commmands for
0820    // the statement. This method is optional.
0821    //
0822    // Parameters:
0823    //       sql - typically this is a static SQL INSERT or UPDATE 
0824    //       statement
0825    // Throws:
0826    //       TSQLException - if a database access error occurs, or 
0827    //       the  driver does not support batch statements
0828 
0829 }
0830 
0831 //___________________________________________________________________
0832 void ODBCStatement::ClearBatch()
0833 {
0834    // Makes the set of commands in the current batch empty. This
0835    // method is optional.
0836    //
0837    // Throws:
0838    //       TSQLException - if a database access error occurs or 
0839    //       the driver does not support batch statements
0840 
0841 }
0842 
0843 //___________________________________________________________________
0844 Int_t* ODBCStatement::ExecuteBatch()
0845 {
0846    // Submits a batch of commands to the database for execution.
0847    // This method is optional.
0848    //
0849    // Returns:
0850    //       an array of update counts containing one element for 
0851    //       each command in the batch. The array is ordered 
0852    //       according  to the order in which commands were inserted 
0853    //       into the  batch.
0854    //
0855    // Throws:
0856    //       TSQLException - if a database access error occurs or 
0857    //       the driver  does not support batch statements
0858 
0859    return 0;
0860 }