Back to home page

sPhenix code displayed by LXR

 
 

    


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

0001 // $Id: ODBCConnection.cxx,v 1.2 2010/09/17 14:55:49 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 connection (session) with a specific database. Within the context 
0032 // of a TSQLConnection, SQL statements are executed and results are 
0033 // returned.  A TSQLConnection's database is able to provide information 
0034 // describing its tables, its supported SQL grammar, its stored procedures, 
0035 // the capabilities of this connection, and so on. This information is
0036 // obtained with the GetMetaData() method. 
0037 //
0038 // See also:
0039 //    TSQLDriverManager::GetConnection(TString)
0040 //    TSQLStatement TSQLPreparedStatement TSQLCallableStatement
0041 //    TSQLResultSet TSQLDatabaseMetaData
0042 //
0043 ///////////////////////////////////////////////////////////////////////
0044 // 
0045 // A transaction is a recoverable sequence of SQL operations grouped
0046 // as a single unit. The initiation and termination of transaction 
0047 // define the following points of data consistency within an 
0048 // application process; either all SQL operations within a transaction 
0049 // are applied to the data source (committed), or the effects of all
0050 // SQL operations within a transaction are completely "undone"
0051 // (rolled back). 
0052 //   RDBC provides the following modes of transaction processing 
0053 // that determine haw and when transactions are to be committed (or,
0054 // if possible rolled back):
0055 // 
0056 //    - Auto-commit mode
0057 //    - Manual-commit mode 
0058 //
0059 //  defined by TSQLConnection::SetAutoCommit( Bool_t autoCommit )
0060 //
0061 ///////////////////////////////////////////////////////////////////
0062 //
0063 // In multi-user database system, transactions can occur 
0064 // simultaneously, and each transaction has potential to interfere
0065 // with another one. When transactions are not isolated from each
0066 // other in multi-user enviroments, the following three types of
0067 // events can occur:
0068 //___________________________________________________________________
0069 //
0070 // Dirty Read: 
0071 //
0072 //    Transaction 1 changes a row. Transaction 2 reads
0073 // the changed row before Transacion 1 commits the change. If
0074 // Transaction 1 rolls back the change, Transacion 2 will have
0075 // read a row that is considered to have never existed
0076 //
0077 //___________________________________________________________________
0078 //
0079 // Nonrepeatable Read:
0080 //
0081 //    Transaction 1 reads a row. Transaction 2 updates or deletes
0082 // that row and commits the change. If Transaction 1 attempts
0083 // to reread the row, it will receive different row values or 
0084 //  discover that the row has been deleted.
0085 //
0086 //___________________________________________________________________
0087 //
0088 // Phantom: 
0089 //
0090 //    Transaction 1  reads a set of rows that satisfy some search
0091 // criteria. Transaction 2 generates one or more rows ( either 
0092 // through inserts or updates ) that match the search criteria
0093 // If transacion 1 re-executes the statement that reads the rows,
0094 // it receives a different set of rows.
0095 //
0096 //////////////////////////////////////////////////////////////////////
0097 //
0098 // ODBC defines four levels of transaction isolation that can,
0099 // prevent all, some, or none of these events from occurring. 
0100 // They are:
0101 //___________________________________________________________________
0102 //
0103 // kTRANSACTION_NONE
0104 //
0105 // Indicates that transactions are not supported.
0106 //
0107 //___________________________________________________________________
0108 //
0109 // kTRANSACTION_READ_UNCOMMITTED
0110 // 
0111 // Dirty reads, non-repeatable reads and phantom reads can occur.
0112 // This level allows a row changed by one transaction to be read 
0113 // by another transaction before any changes in that row have been 
0114 // committed (a "dirty read"). If any of the changes are rolled back,
0115 // the second transaction will have retrieved an invalid row.
0116 //
0117 //___________________________________________________________________
0118 //
0119 // kTRANSACTION_READ_COMMITTED
0120 //
0121 //
0122 // Dirty reads are prevented; non-repeatable reads and phantom reads
0123 // can occur. This level only prohibits a transaction from reading a 
0124 // row with uncommitted changes in it.
0125 //
0126 //___________________________________________________________________
0127 //
0128 // kTRANSACTION_REPEATABLE_READ
0129 //
0130 // Dirty reads and non-repeatable reads are prevented; phantom reads 
0131 // can occur. This level prohibits a transaction from reading a row 
0132 // with uncommitted changes in it, and it also prohibits the situation 
0133 // where one transaction reads a row, a second transaction alters the 
0134 // row, and the first transaction rereads the row, getting different 
0135 // values the second   time (a "non-repeatable read").
0136 //
0137 //___________________________________________________________________
0138 //
0139 // kTRANSACTION_SERIALIZABLE
0140 //
0141 // Dirty reads, non-repeatable reads and phantom reads are prevented.
0142 // This level includes the prohibitions in kTRANSACTION_REPEATABLE_READ
0143 // and further prohibits the situation where one transaction reads 
0144 // all rows that satisfy a WHERE condition, a second transaction 
0145 // inserts a row that satisfies that WHERE condition, and the first 
0146 // transaction rereads for the same condition, retrieving the 
0147 // additional "phantom" row in the second read.
0148 //
0149 //
0150 /////////////////////////////////////////////////////////////////////
0151 
0152 #include "ODBCConnection.h"
0153 #include "ODBCStatement.h"
0154 #include "ODBCPreparedStatement.h"
0155 #include "ODBCCallableStatement.h"
0156 #include "ODBCDatabaseMetaData.h"
0157 #include "ODBCResultSet.h"
0158 #include <RDBC/TSQLDriverManager.h>
0159 #include <RDBC/TSQLUrl.h>
0160 #include <RDBC/TSQLDriverInfo.h>
0161 #include <TList.h>
0162 #include <TNamed.h>
0163 #include <RDBC/odbc++/connection.h>
0164 #include <RDBC/odbc++/statement.h>
0165 #include <RDBC/odbc++/resultset.h>
0166 #include <RDBC/odbc++/preparedstatement.h>
0167 #include <RDBC/odbc++/callablestatement.h>
0168 #include <RDBC/odbc++/drivermanager.h>
0169 
0170 using namespace odbc;
0171 using namespace std;
0172 
0173 ClassImpQ(ODBCConnection)
0174 
0175 ///////////////////////////////////////////////////////////////////// 
0176 //___________________________________________________________________
0177 ODBCConnection::ODBCConnection( const TString&  connectString ):
0178                TSQLConnection(connectString)
0179 {
0180    // Attempts to establish a connection to the given database 
0181    // by specified connection string. This string is simply
0182    // a series of keyword/value pairs, searated by semicolons,
0183    // that contains information used to establish the connection.
0184    // The TSQLDriverManager attempts to select an appropriate driver
0185    // from the set of registered drivers.
0186    //
0187    // Parameters:
0188    //    connectString usually something like:
0189    //                   "dsn=minos;uid=scott;pwd=tiger"
0190    //
0191    // Throws:
0192    //    TSQLException - if a database access error occurs
0193 
0194    odbc::Connection* imp = 0;
0195    odbc::DatabaseMetaData* md = 0; 
0196 
0197    try {
0198       imp = odbc::DriverManager::getConnection( 
0199                                    ODBCXX_STRING_C(connectString) );
0200       fImp = imp;
0201       if(imp) md = imp->getMetaData();
0202     } catch(odbc::SQLException& e) {
0203       gSQLDriverManager->Throw( new TSQLException( 
0204                                     ODBCXX_STRING_CSTR(e.getMessage()),
0205                                     ODBCXX_STRING_CSTR(e.getSQLState()),
0206                                     e.getErrorCode()) );
0207    // failed to connect => clean all
0208       if(imp) delete imp;
0209       fImp = 0;
0210       return;
0211    }
0212 
0213    if(!fMetaData) fMetaData = new ODBCDatabaseMetaData(this,md);
0214 }
0215 
0216 //___________________________________________________________________
0217 ODBCConnection::ODBCConnection( const TString& dsn, 
0218                                 const TString& username, 
0219                                 const TString& password ): 
0220                                 TSQLConnection(dsn,username,password)
0221 {
0222    // Attempts to establish a connection to the given Data Source Name (DSN). 
0223    // The TSQLDriverManager attempts to select an appropriate driver  from  
0224    // the set of registered drivers.
0225    //
0226    // Parameters:
0227    //    dsn      - DataSourceName string
0228    //    username - the database user on whose behalf the TSQLConnection
0229    //                is being made
0230    //    password - the user's password
0231    //
0232    // Throws:
0233    //    TSQLException - if a database access error occurs
0234    //  
0235    
0236    odbc::Connection* imp = 0;
0237    odbc::DatabaseMetaData* md = 0; 
0238 
0239    try {
0240       imp = odbc::DriverManager::getConnection( 
0241                                    ODBCXX_STRING_C(dsn),
0242                                    ODBCXX_STRING_C(username),
0243                                    ODBCXX_STRING_C(password) );
0244       fImp = imp;
0245       if(imp) md = imp->getMetaData();
0246     } catch(odbc::SQLException& e) {
0247       gSQLDriverManager->Throw( new TSQLException( 
0248                                     ODBCXX_STRING_CSTR(e.getMessage()),
0249                                     ODBCXX_STRING_CSTR(e.getSQLState()),
0250                                     e.getErrorCode()) );
0251    // failed to connect => clean all
0252       if(imp) delete imp;
0253       fImp = 0;
0254       return;
0255    }
0256    if(!fMetaData) fMetaData = new ODBCDatabaseMetaData(this,md);
0257 }
0258 
0259 //___________________________________________________________________
0260 ODBCConnection::~ODBCConnection()
0261 {
0262    // Destructor:
0263    //
0264    // - deallocate all statements produced by this connection
0265    // - disconnect this connection 
0266 
0267    if(IsClosed()) return;
0268 
0269    odbc::Connection* con = (odbc::Connection*)fImp;  
0270 
0271    if(fListOfStatements) {    // deallocate all statements
0272       fListOfStatements->Delete();
0273       delete fListOfStatements;
0274    }
0275 
0276    fListOfStatements = 0;
0277 
0278    try {
0279       if(con) delete con;
0280    } catch(odbc::SQLException& e) {
0281       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0282                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0283                                 e.getErrorCode()) );
0284    }
0285   
0286    if(fMetaData) delete ((ODBCDatabaseMetaData*)fMetaData);
0287 
0288    fImp = 0;
0289    fMetaData = 0;
0290 }
0291 
0292 //___________________________________________________________________
0293 TSQLStatement* ODBCConnection::CreateStatement()
0294 { 
0295    // Creates a TSQLStatement object for sending SQL statements 
0296    // to the database. SQL statements without parameters are 
0297    // normally executed using TSQLStatement objects. If the
0298    // same SQL statement is executed many times, it is more 
0299    // efficient to use a TSQLPreparedStatement. TSQLResultSet s 
0300    // created using the returned TSQLStatement will have 
0301    // forward-only type, and read-only concurrency, by default.
0302    //
0303    // Returns:
0304    //      a new ODBCStatement object
0305    //      zero - in case of  error  
0306    // Throws:
0307    //       TSQLException - if a database access error occurs     
0308 
0309    if(IsClosed()) {
0310       Throw( new TSQLException( "Connection is closed","",0) );
0311       return 0;
0312    }
0313 
0314    ClearWarnings();
0315 
0316    TSQLStatement* stmt = 0;
0317    odbc::Connection* con = (odbc::Connection*)fImp;
0318    odbc::Statement* imp = 0;
0319 
0320    try {      
0321       imp = con->createStatement();
0322    } catch(odbc::SQLException& e) {
0323       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0324                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0325                                 e.getErrorCode()) );
0326       if(imp) delete imp;
0327       return 0;
0328    }
0329    stmt = new ODBCStatement(this,imp);
0330    fListOfStatements->Add(stmt);
0331    return stmt; 
0332 }
0333 
0334 //___________________________________________________________________
0335 TSQLStatement* ODBCConnection::CreateStatement( Int_t resultSetType,
0336                                           Int_t resultSetConcurrency )
0337 { 
0338    // Creates a TSQLStatement object that will generate TSQLResultSet
0339    // objects with the given type and concurrency. This method is the 
0340    // same as the CreateStatement() method above, but it allows the 
0341    // default result set type and result set concurrency type to be 
0342    // overridden.
0343    //
0344    // Parameters:
0345    //       resultSetType - a result set type; 
0346    //                       see TSQLResultSet::kTYPE_XXX
0347    //       resultSetConcurrency - a concurrency type; 
0348    //                       see TSQLResultSet::kCONCUR_XXX
0349    // Returns:
0350    //       a new ODBCStatement object
0351    // Throws:
0352    //       TSQLException - if a database access error occurs
0353 
0354    if(IsClosed()) {
0355       Throw( new TSQLException( "Connection is closed","",0) );
0356       return 0;
0357    }
0358    ClearWarnings();
0359 
0360    TSQLStatement* stmt = 0;  
0361    odbc::Connection* con = (odbc::Connection*)fImp;
0362    odbc::Statement* imp = 0;
0363 
0364    try {      
0365       imp = con->createStatement( resultSetType,resultSetConcurrency );
0366    } catch(odbc::SQLException& e) {
0367       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0368                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0369                                 e.getErrorCode()) );
0370       if(imp) delete imp;
0371       return 0;
0372    }
0373    stmt = new ODBCStatement(this,imp);
0374    fListOfStatements->Add(stmt);
0375    return stmt; 
0376 }
0377 
0378 //___________________________________________________________________
0379 TSQLPreparedStatement* ODBCConnection::PrepareStatement( const TString& sql )
0380 {
0381    // Creates a TSQLPreparedStatement object for sending 
0382    // parameterized SQL statements to the database. A SQL statement 
0383    // with or without IN parameters can be pre-compiled and stored 
0384    // in a TSQLPreparedStatement object. This object can then be 
0385    // used to efficiently execute this statement multiple times. 
0386    //
0387    // Note: This method is optimized for handling parametric SQL
0388    //       statements that benefit from precompilation.
0389    //       If the driver supports precompilation, the method 
0390    //       PrepareStatement() will send the statement to the database 
0391    //       for precompilation. Some drivers may not support precompilation. 
0392    //       In this case, the statement may not be sent to the database 
0393    //       until the TSQLPreparedStatement is executed. This has no direct
0394    //       effect on users; however, it does affect which method throws 
0395    //       certain TSQLException s. Result sets created using the returned 
0396    //       TSQLPreparedStatement will have forward-only type and read-only
0397    //       concurrency, by default.
0398    //
0399    // Parameters:
0400    //       sql - a SQL statement that may contain one or more '?' 
0401    //       IN parameter placeholders
0402    // Returns:
0403    //       a new ODBCPreparedStatement object containing the 
0404    //       pre-compiled statement
0405    // Throws:
0406    //       TSQLException - if a database access error occurs
0407 
0408    if(IsClosed()) {
0409       Throw( new TSQLException( "Connection is closed","",0) );
0410       return 0;
0411    }
0412 
0413    ClearWarnings();
0414 
0415    ODBCPreparedStatement* stmt = 0;
0416    odbc::Connection* con = (odbc::Connection*)fImp;
0417    odbc::PreparedStatement* imp = 0;
0418 
0419    try {      
0420       imp = con->prepareStatement( ODBCXX_STRING_C(sql.Data()) );
0421    } catch(odbc::SQLException& e) {
0422       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0423                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0424                                 e.getErrorCode()) );
0425       if(imp) delete imp;
0426       return 0; 
0427    }
0428    stmt = new ODBCPreparedStatement(this,imp); 
0429    fListOfStatements->Add(stmt);
0430    return stmt;
0431 }
0432 
0433 //___________________________________________________________________
0434 TSQLCallableStatement* ODBCConnection::PrepareCall( const TString& sql )
0435 {  
0436    // Creates a TSQLCallableStatement object for calling database 
0437    // stored procedures. The TSQLCallableStatement provides methods 
0438    // for setting up its IN and OUT parameters, and methods for 
0439    // executing the call to a stored procedure. 
0440    //
0441    // Note: This method is optimized for handling stored procedure 
0442    //       call statements. Some drivers may send the call statement 
0443    //       to the database when the method PrepareCall() is done; 
0444    //       others may wait until the TSQLCallableStatement is 
0445    //       executed. This has no direct effect on users; however, 
0446    //       it does affect which method throws certain SQLExceptions. 
0447    //       Result sets created using the returned 
0448    //       TSQLCallableStatement will have forward-only type and 
0449    //       read-only concurrency, by default.
0450    // Parameters:
0451    //       sql - a SQL statement that may contain one or more '?'
0452    //             parameter placeholders. Typically this statement is
0453    //             a function call escape string.
0454    // Returns:
0455    //       a new ODBCCallableStatement object containing the 
0456    //       pre-compiled SQL statement
0457    // Throws:
0458    //       TSQLException - if a database access error occurs
0459 
0460    if(IsClosed()) {
0461       Throw( new TSQLException( "Connection is closed","",0) );
0462       return 0;
0463    }
0464 
0465    ClearWarnings();
0466 
0467    ODBCCallableStatement* stmt = 0;
0468    odbc::Connection* con = (odbc::Connection*)fImp;
0469    odbc::CallableStatement* imp = 0;
0470 
0471    try {      
0472       imp = con->prepareCall( ODBCXX_STRING_C(sql.Data()) );      
0473    } catch(odbc::SQLException& e) {
0474       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0475                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0476                                 e.getErrorCode()) );
0477       if(imp) delete imp;
0478       return 0;
0479    }
0480    stmt = new ODBCCallableStatement(this,imp);
0481    fListOfStatements->Add(stmt);
0482    return stmt;
0483 }
0484 
0485 //___________________________________________________________________
0486 TSQLPreparedStatement* ODBCConnection::PrepareStatement( const TString& sql,
0487                                                          Int_t resultSetType, 
0488                                                          Int_t resultSetConcurrency )
0489 {
0490    // Creates a TSQLPreparedStatement object that will generate
0491    // TSQLResultSet objects with the given type and concurrency. 
0492    // This method is the same as the PrepareStatement() method above,
0493    // but it allows the default result set type and result set 
0494    // concurrency type to be overridden.
0495    //   
0496    // Parameters:
0497    //       resultSetType - a result set type; 
0498    //                       see TSQLResultSet::kTYPE_XXX
0499    //       resultSetConcurrency - a concurrency type; 
0500    //                              see TSQLResultSet::kCONCUR_XXX
0501    // Returns:
0502    //       a new ODBCPreparedStatement object containing the 
0503    //       pre-compiled SQL statement
0504    // Throws:
0505    //       TSQLException - if a database access error occurs
0506 
0507    if(IsClosed()) {
0508       Throw( new TSQLException( "Connection is closed","",0) );
0509       return 0;
0510    }
0511 
0512    ClearWarnings();
0513 
0514    ODBCPreparedStatement* stmt = 0; 
0515    odbc::Connection* con = (odbc::Connection*)fImp;
0516    odbc::PreparedStatement* imp =0;
0517 
0518    try {      
0519       imp = con->prepareStatement( ODBCXX_STRING_C(sql.Data()),
0520                                    resultSetType,
0521                                    resultSetConcurrency );
0522    } catch(odbc::SQLException& e) {
0523       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0524                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0525                                 e.getErrorCode()) );
0526       if(imp) delete imp;
0527       return 0;
0528    }
0529    stmt =  new ODBCPreparedStatement(this,imp);
0530    fListOfStatements->Add(stmt);
0531    return stmt;
0532 }
0533 
0534 //___________________________________________________________________
0535 TSQLCallableStatement* ODBCConnection::PrepareCall( const TString& sql, 
0536                                                     Int_t resultSetType, 
0537                                                     Int_t resultSetConcurrency )
0538 {
0539    // Creates a TSQLCallableStatement object that will generate
0540    // TSQLResultSet objects with the given type and concurrency. 
0541    // This method is the same as the PrepareCall() method above,
0542    // but it allows the default result set type and result set 
0543    // concurrency type to be overridden.
0544    //
0545    // Parameters:
0546    //       resultSetType - a result set type; 
0547    //                         see TSQLResultSet::kTYPE_XXX
0548    //       resultSetConcurrency - a concurrency type;
0549    //                         see TSQLResultSet::kCONCUR_XXX
0550    //
0551    // Returns:
0552    //       a new ODBCCallableStatement object containing the 
0553    //       pre-compiled SQL statement
0554    // Throws:
0555    //       TSQLException - if a database access error occurs
0556 
0557    if(IsClosed()) {
0558       Throw( new TSQLException( "Connection is closed","",0) );
0559       return 0;
0560    }
0561 
0562    ClearWarnings();
0563 
0564    ODBCCallableStatement* stmt = 0;
0565    odbc::Connection* con = (odbc::Connection*)fImp;
0566    odbc::CallableStatement* imp = 0; 
0567 
0568    try {      
0569       imp= con->prepareCall( ODBCXX_STRING_C(sql.Data()),
0570                              resultSetType,
0571                              resultSetConcurrency );
0572    } catch(odbc::SQLException& e) {
0573       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0574                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0575                                 e.getErrorCode()) );
0576       if(imp) delete imp;
0577       return 0;
0578    }
0579    stmt =  new ODBCCallableStatement(this,imp);
0580    fListOfStatements->Add(stmt);
0581    return stmt;
0582 }
0583 
0584 //___________________________________________________________________
0585 TString ODBCConnection::NativeSQL( const TString& sql )
0586 {
0587    // Converts the given SQL statement into the system's native SQL
0588    // grammar. A driver may convert the sql grammar into its system's
0589    // native SQL grammar prior to sending it; this method returns 
0590    // the native form of the statement that the driver would have 
0591    // sent.
0592    //
0593    // Parameters:
0594    //       sql - a SQL statement that may contain one or more '?'
0595    //             parameter placeholders
0596    // Returns:
0597    //       the native form of this statement
0598    // Throws:
0599    //       TSQLException - if a database access error occurs
0600 
0601    if(IsClosed()) {
0602       Throw( new TSQLException( "Connection is closed","",0) );
0603       return "0";
0604    }
0605 
0606    ClearWarnings();
0607 
0608    TString str;
0609    odbc::Connection* con = (odbc::Connection*)fImp;
0610 
0611    try {
0612       ODBCXX_STRING s = con->nativeSQL( ODBCXX_STRING_C(sql.Data()) );
0613       str = ODBCXX_STRING_CSTR(s);         
0614    } catch(odbc::SQLException& e) {
0615       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0616                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0617                                 e.getErrorCode()) );
0618       return "";
0619    }     
0620    return str;
0621 }
0622 
0623 //___________________________________________________________________
0624 void ODBCConnection::SetAutoCommit( Bool_t autoCommit )
0625 {
0626    // Sets this connection's auto-commit mode. If a connection is in
0627    // auto-commit mode, then all its SQL statements will be executed 
0628    // and committed as individual transactions. Otherwise, its SQL 
0629    // statements are grouped into transactions that are terminated 
0630    // by a call to either the method commit or the method rollback. 
0631    // By default, new connections are in auto-commit mode. The commit
0632    // occurs when the statement completes or the next execute occurs,
0633    // whichever comes first. In the case of statements returning a 
0634    // TSQLResultSet, the statement completes when the last row
0635    // of the TSQLResultSet has been retrieved or the TSQLResultSet 
0636    // has been closed. In advanced cases, a single statement may 
0637    // return multiple results as well as output parameter values. 
0638    // In these cases the commit occurs when all results and output 
0639    // parameter values have been retrieved.
0640    //
0641    // Parameters:
0642    //       autoCommit - kTRUE enables auto-commit; 
0643    //                    kFALSE disables auto-commit.
0644    // Throws:
0645    //       TSQLException - if a database access error occurs
0646 
0647    if(IsClosed()) {
0648       Throw( new TSQLException( "Connection is closed","",0) );
0649       return;
0650    }
0651    odbc::Connection* con = (odbc::Connection*)fImp;
0652 
0653    try {      
0654       con->setAutoCommit(autoCommit);
0655    } catch(odbc::SQLException& e) {
0656       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0657                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0658                                 e.getErrorCode()) );
0659    }
0660 }
0661 
0662 //___________________________________________________________________
0663 Bool_t ODBCConnection::GetAutoCommit()
0664 { 
0665    // Gets the current auto-commit state.
0666    //   
0667    // Returns:
0668    //       the current state of auto-commit mode
0669    // Throws:
0670    //       TSQLException - if a database access error occurs
0671    // See Also: 
0672    //       SetAutoCommit(Bool_t)
0673 
0674    if(IsClosed()) {
0675       Throw( new TSQLException( "Connection is closed","",0) );
0676       return 0;
0677    }
0678 
0679    Bool_t return_value = kFALSE;    
0680    odbc::Connection* con = (odbc::Connection*)fImp;
0681 
0682    try {      
0683       return_value = con->getAutoCommit();
0684    } catch(odbc::SQLException& e) {
0685       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0686                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0687                                 e.getErrorCode()) );
0688       return kFALSE;
0689    }
0690    return return_value;
0691 }
0692 
0693 //___________________________________________________________________
0694 void ODBCConnection::Commit()
0695 {
0696    // Makes all changes made since the previous commit/rollback
0697    // permanent and releases any database locks currently held by 
0698    // the TSQLConnection. This method should be used only when 
0699    // auto-commit mode has been disabled.
0700    //
0701    // Throws:
0702    //       TSQLException - if a database access error occurs
0703    // See Also: 
0704    //       SetAutoCommit(Bool_t)
0705 
0706    if(IsClosed()) {
0707       Throw( new TSQLException( "Connection is closed","",0) );
0708       return;
0709    }
0710   
0711    odbc::Connection* con = (odbc::Connection*)fImp;
0712 
0713    try {      
0714       con->commit();
0715    } catch(odbc::SQLException& e) {
0716       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0717                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0718                                 e.getErrorCode()) );
0719    }
0720 }
0721 
0722 //___________________________________________________________________
0723 void ODBCConnection::Rollback()
0724 { 
0725    // Drops all changes made since the previous commit/rollback and
0726    // releases any database locks currently held by this TSQLConnection. 
0727    // This method should be used only when auto-commit has been disabled.
0728    //
0729    // Throws:
0730    //       TSQLException - if a database access error occurs
0731    // See Also: 
0732    //       SetAutoCommit(Bool_t)
0733 
0734    if(IsClosed()) {
0735       Throw( new TSQLException( "Connection is closed","",0) );
0736       return;
0737    }
0738 
0739    odbc::Connection* con = (odbc::Connection*)fImp;
0740 
0741    try {      
0742       con->rollback();
0743    } catch(odbc::SQLException& e) {
0744       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0745                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0746                                 e.getErrorCode()) );
0747    }
0748 }
0749 
0750 //___________________________________________________________________
0751 void ODBCConnection::Close()
0752 {
0753    // Releases a TSQLConnection's database and resources immediately
0754    // instead of waiting for them to be automatically released. 
0755    //
0756    // Throws:
0757    //       TSQLException - if a database access error occurs
0758 
0759    TSQLConnection::Close();
0760    if(!IsClosed()) return;    // connection is in use
0761 
0762    odbc::Connection* con = (odbc::Connection*)fImp;
0763 
0764    try {
0765       if(con) delete con;  // !!!!
0766    } catch(odbc::SQLException& e) {
0767       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0768                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0769                                 e.getErrorCode()) );
0770    }  
0771 
0772    if(fMetaData) delete ((ODBCDatabaseMetaData*)fMetaData);
0773    fMetaData = 0;
0774    fImp = 0;
0775 }
0776 
0777 //___________________________________________________________________
0778 TSQLDatabaseMetaData* ODBCConnection::GetMetaData()
0779 {
0780    // Gets the metadata regarding this connection's database. 
0781    // A TSQLConnection's database is able to provide information 
0782    // describing its tables, its supported SQL grammar, its
0783    // stored procedures, the capabilities of this connection,
0784    // and so on. This information is made available through a 
0785    // TSQLDatabaseMetaData object.
0786    //
0787    // Returns:
0788    //       a TSQLDatabaseMetaData object for this TSQLConnection
0789    // Throws:
0790    //       TSQLException - if a database access error occurs
0791 
0792    if(IsClosed()) {
0793       Throw( new TSQLException( "Connection is closed","",0) );
0794       return 0;
0795    }
0796 
0797    odbc::DatabaseMetaData* md = 0; 
0798    odbc::Connection* con = (odbc::Connection*)fImp;
0799 
0800    try {      
0801       md = con->getMetaData();
0802    } catch(odbc::SQLException& e) {
0803       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0804                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0805                                 e.getErrorCode()) ); 
0806       return 0;
0807    }   
0808    if(fMetaData) ((ODBCDatabaseMetaData*)fMetaData)->Set(this,md);
0809    return fMetaData;
0810 }
0811 
0812 //___________________________________________________________________
0813 void ODBCConnection::SetReadOnly( Bool_t readOnly )
0814 {
0815    // Puts this connection in read-only mode as a hint to enable
0816    // database optimizations. 
0817    //
0818    // Note: This method cannot be called while in the middle of a
0819    // transaction.
0820    //
0821    // Parameters:
0822    //       readOnly - kTRUE enables read-only mode; 
0823    //                  kFALSE disables read-only mode.
0824    // Throws:
0825    //       TSQLException - if a database access error occurs
0826 
0827    if(IsClosed()) {
0828       Throw( new TSQLException( "Connection is closed","",0) );
0829       return;
0830    } 
0831    odbc::Connection* con = (odbc::Connection*)fImp;
0832 
0833    try {
0834       con->setReadOnly(readOnly);
0835    } catch(odbc::SQLException& e) {
0836       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0837                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0838                                 e.getErrorCode()) );
0839    }
0840 }
0841 
0842 //___________________________________________________________________
0843 Bool_t ODBCConnection::IsReadOnly()
0844 {
0845    // Tests to see if the connection is in read-only mode.
0846    //   
0847    // Returns:
0848    //       kTRUE if connection is read-only and kFALSE otherwise
0849    // Throws:
0850    //       TSQLException - if a database access error occurs
0851 
0852    if(IsClosed()) {
0853       Throw( new TSQLException( "Connection is closed","",0) );
0854       return kTRUE;
0855    }
0856 
0857    Bool_t return_value = kTRUE;   
0858    odbc::Connection* con = (odbc::Connection*)fImp;
0859 
0860    try {      
0861         return_value = con->isReadOnly();
0862    } catch(odbc::SQLException& e) {
0863       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0864                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0865                                 e.getErrorCode()) );
0866       return kTRUE;
0867    }
0868     return return_value;
0869 }
0870 
0871 //___________________________________________________________________
0872 void ODBCConnection::SetCatalog( const TString& catalog )
0873 { 
0874    // Sets a catalog name in order to select a subspace of this
0875    // TSQLConnection's database in which to work. If the driver 
0876    // does not support catalogs, it will silently ignore this 
0877    // request.
0878    //
0879    // Throws:
0880    //       TSQLException - if a database access error occurs
0881 
0882    if(IsClosed()) {
0883       Throw( new TSQLException( "Connection is closed","",0) );
0884       return;
0885    }
0886 
0887    odbc::Connection* con = (odbc::Connection*)fImp;
0888 
0889    try {      
0890       con->setCatalog( ODBCXX_STRING_C(catalog.Data()) );
0891    } catch(odbc::SQLException& e) {
0892       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0893                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0894                                 e.getErrorCode()) );
0895    }
0896 }
0897 
0898 //___________________________________________________________________
0899 TString ODBCConnection::GetCatalog()
0900 {
0901    // Returns the TSQLConnection's current catalog name.
0902    //
0903    // Returns:
0904    //       the current catalog name or null string
0905    // Throws:
0906    //       TSQLException - if a database access error occurs
0907 
0908    if(IsClosed()) {
0909       Throw( new TSQLException( "Connection is closed","",0) );
0910       return "0";
0911    }
0912 
0913    TString str;
0914    odbc::Connection* con = (odbc::Connection*)fImp;
0915 
0916    try {       
0917       str = ODBCXX_STRING_CSTR( con->getCatalog() );
0918    } catch(odbc::SQLException& e) {
0919       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0920                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0921                                 e.getErrorCode()) );
0922       return "";
0923    }
0924    return str;
0925 }
0926 
0927 //___________________________________________________________________
0928 void ODBCConnection::SetTransactionIsolation( Int_t level )
0929 {
0930    // Attempts to change the transaction isolation level to the one
0931    // given. The constants defined in the interface TSQLConnection 
0932    // are the possible transaction isolation levels. 
0933    //
0934    // Note: This method cannot be called while in the middle of a
0935    //       transaction.
0936    //
0937    // Parameters:
0938    //       level - one of the kTRANSACTION_XXX isolation values with 
0939    //               the exception of kTRANSACTION_NONE; 
0940    //               some databases may not support other values
0941    // Throws:
0942    //        TSQLException - if a database access error occurs
0943    // 
0944    // See Also: 
0945    // TSQLDatabaseMetaData::SupportsTransactionIsolationLevel(Int_t)
0946 
0947    if(IsClosed()) {
0948       Throw( new TSQLException( "Connection is closed","",0) );
0949       return;
0950    }
0951 
0952    try {      
0953       // con->setTransactionIsolation(level);
0954    } catch(odbc::SQLException& e) {
0955       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0956                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0957                                 e.getErrorCode()) );
0958    }
0959 }
0960 
0961 //___________________________________________________________________
0962 Int_t ODBCConnection::GetTransactionIsolation()
0963 { 
0964    // Gets this TSQLConnection's current transaction isolation level.
0965    //
0966    // Returns:
0967    //       the current kTRANSACTION_XXX mode value
0968    // Throws:
0969    //       TSQLException - if a database access error occurs
0970 
0971    if(IsClosed()) {
0972       Throw( new TSQLException( "Connection is closed","",0) );
0973       return 0;
0974    }
0975    
0976    Int_t return_value = 0; 
0977    odbc::Connection* con = (odbc::Connection*)fImp;
0978 
0979    try {      
0980       return_value = con->getTransactionIsolation(); 
0981 
0982    } catch(odbc::SQLException& e) {
0983       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
0984                                 ODBCXX_STRING_CSTR(e.getSQLState()),
0985                                 e.getErrorCode()) );
0986       return 0;
0987    }
0988    return return_value;
0989 }
0990 
0991 //___________________________________________________________________
0992 Bool_t ODBCConnection::GetTrace()
0993 {
0994    // Returns kTRUE if tracing is enabled on this connection 
0995 
0996    if(IsClosed()) {
0997       Throw( new TSQLException( "Connection is closed","",0) );
0998       return kFALSE;
0999    }
1000 
1001    Bool_t return_value = kFALSE;
1002    odbc::Connection* con = (odbc::Connection*)fImp;
1003 
1004    try {      
1005       return_value = con->getTrace();
1006    } catch(odbc::SQLException& e) {
1007       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
1008                                 ODBCXX_STRING_CSTR(e.getSQLState()),
1009                                 e.getErrorCode()) );
1010       return kFALSE;
1011    }
1012    return return_value;
1013 }
1014 
1015 //___________________________________________________________________
1016 void ODBCConnection::SetTrace( Bool_t on )
1017 {
1018    // Sets tracing on or off
1019    
1020    if(IsClosed()) {
1021       Throw( new TSQLException( "Connection is closed","",0) );
1022       return;
1023    }
1024 
1025    odbc::Connection* con = (odbc::Connection*)fImp;
1026 
1027    try {      
1028       con->setTrace(on);
1029    } catch(odbc::SQLException& e) {
1030       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
1031                                 ODBCXX_STRING_CSTR(e.getSQLState()),
1032                                 e.getErrorCode()) );
1033    }
1034 }
1035 
1036 //___________________________________________________________________
1037 TString ODBCConnection::GetTraceFile()
1038 {
1039    // Returns the file tracing is currently written to  
1040    
1041    TString str;
1042 
1043    if(IsClosed()) {
1044       Throw( new TSQLException( "Connection is closed","",0) );
1045       return str;
1046    }
1047    
1048    if(!fImp) { Destroyed();   return str; }       
1049    odbc::Connection* con = (odbc::Connection*)fImp;
1050 
1051    try {      
1052       str = ODBCXX_STRING_CSTR( con->getTraceFile() );
1053    } catch(odbc::SQLException& e) {
1054       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
1055                                 ODBCXX_STRING_CSTR(e.getSQLState()),
1056                                 e.getErrorCode()) );
1057       return "";
1058    }
1059    return str;
1060 }
1061 
1062 //___________________________________________________________________
1063 void ODBCConnection::SetTraceFile( const TString& fn )
1064 {
1065    // Sets the file racing is written to    
1066 
1067    if(IsClosed()) {
1068       Throw( new TSQLException( "Connection is closed","",0) );
1069       return;
1070    }
1071 
1072    odbc::Connection* con = (odbc::Connection*)fImp;
1073 
1074    try {      
1075       con->setTraceFile( ODBCXX_STRING_C(fn.Data()) );
1076    } catch(odbc::SQLException& e) {
1077       Throw( new TSQLException( ODBCXX_STRING_CSTR(e.getMessage()),
1078                                 ODBCXX_STRING_CSTR(e.getSQLState()),
1079                                 e.getErrorCode()) );
1080    }
1081 }
1082 
1083 //___________________________________________________________________
1084 Bool_t ODBCConnection::HasBatchSupport()
1085 {
1086    // Returns kTRUE if batch are supported
1087    //
1088    // Throws:
1089    //       TSQLException - if a database access error occurs
1090   
1091    return kFALSE; 
1092 }
1093 
1094 /////////// private methods used by TSQLDriverManager ///////////////
1095 
1096 //___________________________________________________________________
1097 void ODBCConnection::SetLoginTimeout( Int_t seconds )
1098 {
1099    // Sets the maximum time in seconds that a driver will wait while
1100    // attempting to connect to a database. Set to 0 to disable. 
1101    //
1102    // Parameters:
1103    //       seconds - the login time limit in seconds
1104 
1105    odbc::DriverManager::setLoginTimeout( seconds );
1106 }
1107 
1108 //___________________________________________________________________
1109 Int_t ODBCConnection::GetLoginTimeout()
1110 {
1111    // Gets the maximum time in seconds that a driver can wait when
1112    // attempting to log in to a database. 
1113    //
1114    // Returns:
1115    //       the driver login time limit in seconds, or 0 if disabled.
1116 
1117    return odbc::DriverManager::getLoginTimeout();
1118 }
1119 
1120 //___________________________________________________________________
1121 void ODBCConnection::Shutdown()
1122 {
1123    // Should be called before an application is to exit
1124 
1125    try {
1126       odbc::DriverManager::shutdown();
1127    } catch(odbc::SQLException& e) {
1128       gSQLDriverManager->Throw( new TSQLException( 
1129                                     ODBCXX_STRING_CSTR(e.getMessage()),
1130                                     ODBCXX_STRING_CSTR(e.getSQLState()),
1131                                     e.getErrorCode()) );
1132    }  
1133 }
1134 
1135 //___________________________________________________________________
1136 TList* ODBCConnection::RefreshDrivers(TList* gDrivers)
1137 {
1138    // Fetch a list of all of currently loaded drivers
1139    // to which the current caller has access. 
1140    
1141    if(!gDrivers) return 0;
1142 
1143    gDrivers->Delete();
1144 
1145    TSQLDriverInfo* driver; 
1146    TNamed* attribute;
1147    TList* attributeList;
1148    
1149    try {
1150       odbc::DriverList* list = odbc::DriverManager::getDrivers();
1151       
1152       for( odbc::DriverList::iterator i=list->begin();
1153            i != list->end(); i++) {
1154 
1155          TString description = ODBCXX_STRING_CSTR((*i)->getDescription());
1156          const vector<ODBCXX_STRING>& attrs=(*i)->getAttributes();
1157          
1158          attributeList = new TList();
1159             
1160          for( vector<ODBCXX_STRING>::const_iterator x=attrs.begin(); 
1161                x!=attrs.end(); x++) {
1162            
1163             attribute = new TNamed( ODBCXX_STRING_CSTR((*x)), "attribute" );
1164             attributeList->Add(attribute);
1165          }
1166          driver = new TSQLDriverInfo(description,attributeList);
1167          gDrivers->Add(driver);   
1168       }   
1169    } catch(odbc::SQLException& e) {
1170       gSQLDriverManager->Throw( new TSQLException( 
1171                               ODBCXX_STRING_CSTR(e.getMessage()),
1172                               ODBCXX_STRING_CSTR(e.getSQLState()),
1173                               e.getErrorCode()) );
1174    }
1175    return  gDrivers;   
1176 }
1177 
1178 //___________________________________________________________________
1179 TList* ODBCConnection::RefreshDataSources(TList* gDataSources)
1180 {
1181    // Fetch a list of of all available data sources ( TSQLUrl objects)
1182  
1183    if(!gDataSources) return 0;
1184 
1185    gDataSources->Delete(); // remove all 
1186    TSQLUrl* url;
1187          
1188    try {
1189       odbc::DataSourceList* list = 
1190             odbc::DriverManager::getDataSources();
1191    
1192       for( odbc::DataSourceList::iterator i=list->begin();
1193          i != list->end(); i++) {
1194 
1195          odbc::DataSource* ds = (*i);
1196          url = new TSQLUrl(ODBCXX_STRING_CSTR(ds->getName()),
1197                            ODBCXX_STRING_CSTR(ds->getDescription()));
1198          gDataSources->Add(url);   
1199       }   
1200    } catch(odbc::SQLException& e) {
1201       gSQLDriverManager->Throw( new TSQLException( 
1202                               ODBCXX_STRING_CSTR(e.getMessage()),
1203                               ODBCXX_STRING_CSTR(e.getSQLState()),
1204                               e.getErrorCode()) );
1205    }
1206    return  gDataSources;
1207 }