Back to home page

sPhenix code displayed by LXR

 
 

    


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

0001 // $Id: TSQLConnection.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 //
0008 // A connection (session) with a specific database. Within the context 
0009 // of a TSQLConnection, SQL statements are executed and results are 
0010 // returned.  A TSQLConnection's database is able to provide information 
0011 // describing its tables, its supported SQL grammar, its stored procedures, 
0012 // the capabilities of this connection, and so on. This information is
0013 // obtained with the GetMetaData() method. 
0014 //
0015 // See also:
0016 //    TSQLDriverManager::GetConnection(TString)
0017 //    TSQLStatement TSQLPreparedStatement TSQLCallableStatement
0018 //    TSQLResultSet TSQLDatabaseMetaData
0019 //
0020 ///////////////////////////////////////////////////////////////////////
0021 // 
0022 // A transaction is a recoverable sequence of SQL operations grouped
0023 // as a single unit. The initiation and termination of transaction 
0024 // define the following points of data consistency within an 
0025 // application process; either all SQL operations within a transaction 
0026 // are applied to the data source (committed), or the effects of all
0027 // SQL operations within a transaction are completely "undone"
0028 // (rolled back). 
0029 //   RDBC provides the following modes of transaction processing 
0030 // that determine haw and when transactions are to be committed (or,
0031 // if possible rolled back):
0032 // 
0033 //    - Auto-commit mode
0034 //    - Manual-commit mode 
0035 //
0036 //  defined by TSQLConnection::SetAutoCommit( Bool_t autoCommit )
0037 //
0038 ///////////////////////////////////////////////////////////////////
0039 //
0040 // In multi-user database system, transactions can occur 
0041 // simultaneously, and each transaction has potential to interfere
0042 // with another one. When transactions are not isolated from each
0043 // other in multi-user enviroments, the following three types of
0044 // events can occur:
0045 //___________________________________________________________________
0046 //
0047 // Dirty Read: 
0048 //
0049 //    Transaction 1 changes a row. Transaction 2 reads
0050 // the changed row before Transacion 1 commits the change. If
0051 // Transaction 1 rolls back the change, Transacion 2 will have
0052 // read a row that is considered to have never existed
0053 //
0054 //___________________________________________________________________
0055 //
0056 // Nonrepeatable Read:
0057 //
0058 //    Transaction 1 reads a row. Transaction 2 updates or deletes
0059 // that row and commits the change. If Transaction 1 attempts
0060 // to reread the row, it will receive different row values or 
0061 //  discover that the row has been deleted.
0062 //
0063 //___________________________________________________________________
0064 //
0065 // Phantom: 
0066 //
0067 //    Transaction 1  reads a set of rows that satisfy some search
0068 // criteria. Transaction 2 generates one or more rows ( either 
0069 // through inserts or updates ) that match the search criteria
0070 // If transacion 1 re-executes the statement that reads the rows,
0071 // it receives a different set of rows.
0072 //
0073 //////////////////////////////////////////////////////////////////////
0074 //
0075 // ODBC defines four levels of transaction isolation that can,
0076 // prevent all, some, or none of these events from occurring. 
0077 // They are:
0078 //___________________________________________________________________
0079 //
0080 // kTRANSACTION_NONE
0081 //
0082 // Indicates that transactions are not supported.
0083 //
0084 //___________________________________________________________________
0085 //
0086 // kTRANSACTION_READ_UNCOMMITTED
0087 // 
0088 // Dirty reads, non-repeatable reads and phantom reads can occur.
0089 // This level allows a row changed by one transaction to be read 
0090 // by another transaction before any changes in that row have been 
0091 // committed (a "dirty read"). If any of the changes are rolled back,
0092 // the second transaction will have retrieved an invalid row.
0093 //
0094 //___________________________________________________________________
0095 //
0096 // kTRANSACTION_READ_COMMITTED
0097 //
0098 //
0099 // Dirty reads are prevented; non-repeatable reads and phantom reads
0100 // can occur. This level only prohibits a transaction from reading a 
0101 // row with uncommitted changes in it.
0102 //
0103 //___________________________________________________________________
0104 //
0105 // kTRANSACTION_REPEATABLE_READ
0106 //
0107 // Dirty reads and non-repeatable reads are prevented; phantom reads 
0108 // can occur. This level prohibits a transaction from reading a row 
0109 // with uncommitted changes in it, and it also prohibits the situation 
0110 // where one transaction reads a row, a second transaction alters the 
0111 // row, and the first transaction rereads the row, getting different 
0112 // values the second   time (a "non-repeatable read").
0113 //
0114 //___________________________________________________________________
0115 //
0116 // kTRANSACTION_SERIALIZABLE
0117 //
0118 // Dirty reads, non-repeatable reads and phantom reads are prevented.
0119 // This level includes the prohibitions in kTRANSACTION_REPEATABLE_READ
0120 // and further prohibits the situation where one transaction reads 
0121 // all rows that satisfy a WHERE condition, a second transaction 
0122 // inserts a row that satisfies that WHERE condition, and the first 
0123 // transaction rereads for the same condition, retrieving the 
0124 // additional "phantom" row in the second read.
0125 //
0126 //
0127 /////////////////////////////////////////////////////////////////////
0128 
0129 #include <RDBC/TSQLConnection.h>
0130 #include <RDBC/TSQLResultSet.h>
0131 #include <RDBC/TSQLDatabaseMetaData.h>
0132 #include <RDBC/TSQLDriverManager.h>
0133 #include <TList.h>
0134 
0135 ClassImpQ(TSQLConnection)
0136 
0137 ///////////////////////////////////////////////////////////////////// 
0138 //___________________________________________________________________
0139 TSQLConnection::TSQLConnection( const TString& /* connectString */ ):
0140 TObject(),TSQL(),TRefCnt()
0141 {
0142    // Attempts to establish a connection to the given database 
0143    // by specified connection string. This string is simply
0144    // a series of keyword/value pairs, searated by semicolons,
0145    // that contains information used to establish the connection.
0146    // The TSQLDriverManager attempts to select an appropriate driver
0147    // from the set of registered drivers.
0148    //
0149    // Parameters:
0150    //    connectString usually something like:
0151    //                   "dsn=minos;uid=scott;pwd=tiger"
0152    //
0153    // Throws:
0154    //    TSQLException - if a database access error occurs
0155 
0156    fImp = 0;
0157    fMetaData = 0;
0158    fListOfStatements = new TList();
0159    AddReference();
0160 }
0161 
0162 //___________________________________________________________________
0163 TSQLConnection::TSQLConnection( const TString& /* dsn */, 
0164                                 const TString& /* username */, 
0165                                 const TString& /* password */):
0166 TObject(),TSQL(),TRefCnt()
0167 {
0168    // Attempts to establish a connection to the given Data Source Name (DSN). 
0169    // The TSQLDriverManager attempts to select an appropriate driver  from  
0170    // the set of registered drivers.
0171    //
0172    // Parameters:
0173    //    dsn      - DataSourceName string
0174    //    username - the database user on whose behalf the TSQLConnection
0175    //                is being made
0176    //    password - the user's password
0177    //
0178    // Throws:
0179    //    TSQLException - if a database access error occurs
0180    //  
0181  
0182    fImp = 0;
0183    fMetaData = 0;
0184    fListOfStatements = new TList();
0185    AddReference();
0186 }
0187 
0188 //___________________________________________________________________
0189 TSQLConnection::~TSQLConnection()
0190 {  
0191    // dtor
0192 
0193    if(IsClosed()) return;
0194    TList* li = gSQLDriverManager->GetConnections();
0195    li->Remove(this);
0196 }
0197 
0198 //___________________________________________________________________
0199 void TSQLConnection::Close()
0200 {
0201    // Releases a TSQLConnection's database and resources immediately
0202    // instead of waiting for them to be automatically released. 
0203    //
0204    // Throws:
0205    //       TSQLException - if a database access error occurs
0206 
0207    if(IsClosed()) {
0208       Throw( new TSQLException( "Connection is closed","",0) );
0209       return;
0210    }
0211 
0212    if(RemoveReference()>0) return;
0213 
0214    TList* li = gSQLDriverManager->GetConnections();
0215    li->Remove(this);
0216 
0217    if(fListOfStatements) {    // deallocate all statements
0218       fListOfStatements->Delete();
0219       delete fListOfStatements;
0220    }
0221 
0222    fListOfStatements = 0;
0223    Destroyed();       
0224 }
0225 
0226 //___________________________________________________________________
0227 Bool_t TSQLConnection::IsClosed()
0228 {
0229    // Tests to see if a TSQLConnection is closed.
0230    // 
0231    // Returns:
0232    //       kTRUE if the connection is closed; 
0233    //       kFALSE if it's still open
0234    // Throws:
0235    //       TSQLException - if a database access error occurs
0236 
0237    return References()<=0;
0238 }
0239 
0240 //___________________________________________________________________
0241 void TSQLConnection::SetURL(const TString& url)
0242 {
0243    // sets URL string
0244 
0245    fMetaData->SetURL(url);
0246 }
0247 
0248 //////////// functions used to print out dbmetadata /////////////////
0249 //___________________________________________________________________
0250 const char* s(Bool_t b)
0251 {
0252    //
0253    
0254    return b?"Yes":"No";
0255 }
0256 
0257 //___________________________________________________________________
0258 TString maybeQuote(const TString& str, const TString& qc)
0259 {
0260    //
0261    
0262    TString res; 
0263    if(qc!=" ")  res = qc + str + qc;
0264    else  res = str;
0265    return res;
0266 }
0267 
0268 //___________________________________________________________________
0269 void rsInfo( TSQLDatabaseMetaData* md, 
0270              Int_t rsType, const char* name)
0271 {
0272    //  prints result set info    
0273   
0274    if(md->SupportsResultSetType(rsType)) {
0275       printf("%s\n",name);
0276 
0277       if(md->SupportsResultSetConcurrency(rsType,kCONCUR_READ_ONLY)) {
0278               printf("  + kCONCUR_READ_ONLY\n");
0279       }
0280 
0281       if(md->SupportsResultSetConcurrency(rsType,kCONCUR_UPDATABLE)) {
0282               printf("  + kCONCUR_UPDATABLE\n");
0283       }
0284 
0285       if(md->OwnInsertsAreVisible(rsType)) {
0286               printf("    Own inserts are visible\n");
0287       }
0288 
0289       if(md->OwnUpdatesAreVisible(rsType)) {
0290               printf("    Own updates are visible\n");
0291       }
0292       if(md->OwnDeletesAreVisible(rsType)) {
0293               printf("    Own deletes are visible\n");
0294       }
0295    }
0296 }
0297 
0298 //___________________________________________________________________
0299 struct {
0300    int id;
0301    const char* name;
0302    } levels[] = {
0303       { kTRANSACTION_READ_UNCOMMITTED, "kTRANSACTION_READ_UNCOMMITTED" },
0304       { kTRANSACTION_READ_COMMITTED, "kTRANSACTION_READ_COMMITTED" },
0305       { kTRANSACTION_REPEATABLE_READ, "kTRANSACTION_REPEATABLE_READ" },
0306       { kTRANSACTION_SERIALIZABLE, "kTRANSACTION_SERIALIZABLE" },
0307       { 0,NULL }
0308    };
0309    
0310 //___________________________________________________________________
0311 void transactionInfo(TSQLDatabaseMetaData* md)
0312 {
0313    //prints out transaction info
0314   
0315    TString str;
0316 
0317    str = s(md->SupportsTransactions());
0318    printf("Supports transactions           : %s\n",str.Data()); 
0319 
0320    printf("\nTransaction support \n");
0321    printf("---------------------------------------------------\n");
0322 
0323    if(!md->SupportsTransactions()) {
0324       printf("This datasource does not support transactions.\n\n");
0325       return;
0326    }
0327 
0328    int defIsolation=md->GetDefaultTransactionIsolation();
0329 
0330    for(int i=0; levels[i].name!=NULL; i++) {
0331       if(md->SupportsTransactionIsolationLevel(levels[i].id)) {
0332          str = " +";
0333          str += levels[i].name;
0334          str += (levels[i].id==defIsolation) ? " (default)" :"";
0335          printf("%s\n",str.Data());
0336       }
0337    }
0338 
0339    // the longest method name I've ever seen!
0340    if(md->SupportsDataDefinitionAndDataManipulationTransactions()) {
0341       printf("  Both DML and DDL can be used within a transaction\n");
0342    } else if(md->SupportsDataManipulationTransactionsOnly()) {
0343       printf("  Only DML can be used within a transaction\n");
0344    } else if(md->DataDefinitionCausesTransactionCommit()) {
0345       printf("  DDL causes commit\n");
0346    } else if(md->DataDefinitionIgnoredInTransactions()) {
0347       printf("  DDL is ignored in transactions\n");
0348    }
0349 }
0350 
0351 //___________________________________________________________________
0352 void catalogInfo(TSQLDatabaseMetaData* md)
0353 {
0354    //
0355 
0356    Bool_t cdml = md->SupportsCatalogsInDataManipulation();
0357    Bool_t cproc = md->SupportsCatalogsInProcedureCalls();
0358    Bool_t ctd = md->SupportsCatalogsInTableDefinitions();
0359    Bool_t cid = md->SupportsCatalogsInIndexDefinitions();
0360    Bool_t cpd = md->SupportsCatalogsInPrivilegeDefinitions();
0361    Bool_t hasCatalogs = cdml || cproc || ctd || cid || cpd;
0362   
0363    if(hasCatalogs) {
0364       printf("Supported catalog uses\n");
0365       printf("--------------------------------------------------- \n");
0366       printf("Data manipulation    : %s\n",s(cdml) );
0367       printf("Procedure calls      : %s\n",s(cproc) );
0368       printf("Table definitions    : %s\n",s(ctd) );
0369       printf("Index definitions    : %s\n",s(cid) );
0370       printf("Privilege definitions: %s\n",s(cpd) );
0371    } else {
0372       printf("This datasource does not support catalogs\n");
0373    }
0374    printf("\n");
0375  
0376    TString id = md->GetTableTerm();
0377    if(hasCatalogs) {
0378       TString catSep;
0379       TString catTerm;
0380       catSep  = md->GetCatalogSeparator();
0381       catTerm = md->GetCatalogTerm(); 
0382       if(md->IsCatalogAtStart()) {
0383          id =  catTerm + catSep + id;
0384       } else {
0385               id = id + catSep + catTerm;
0386       }
0387    }
0388    printf("Preferred table identifier format: %s\n",id.Data());
0389 }
0390 
0391 //___________________________________________________________________
0392 void schemaInfo(TSQLDatabaseMetaData* md)
0393 {
0394    //
0395 
0396    Bool_t sdml = md->SupportsSchemasInDataManipulation();
0397    Bool_t sproc = md->SupportsSchemasInProcedureCalls();
0398    Bool_t std = md->SupportsSchemasInTableDefinitions();
0399    Bool_t sid = md->SupportsSchemasInIndexDefinitions();
0400    Bool_t spd = md->SupportsSchemasInPrivilegeDefinitions();
0401    Bool_t hasSchemas=sdml || sproc || std || sid || spd;
0402 
0403    if(hasSchemas) {
0404       printf("Supported schema uses\n");
0405       printf("--------------------------------------------------- \n");
0406       printf("Data manipulation    : %s\n",s(sdml) );
0407       printf("Procedure calls      : %s\n",s(sproc) );
0408       printf("Table definitions    : %s\n",s(std) );
0409       printf("Index definitions    : %s\n",s(sid) );
0410       printf("Privilege definitions: %s\n",s(spd) );
0411    } else {
0412       printf("This datasource does not support schemas\n");
0413    }
0414    printf("\n");
0415   
0416    TString idq = md->GetIdentifierQuoteString();
0417    // space means no quoting supported
0418 
0419    TString id = md->GetTableTerm();
0420 }
0421 
0422 //___________________________________________________________________
0423 void productInfo(TSQLDatabaseMetaData* md)
0424 {
0425    //
0426 
0427    TString str;
0428 
0429    str = md->GetDatabaseProductName();
0430    printf("Product name                    : %s\n",str.Data()); 
0431    
0432    str = md->GetDatabaseProductVersion(); 
0433    printf("Product version                 : %s\n",str.Data()); 
0434 }
0435 
0436 //___________________________________________________________________
0437 void driverInfo(TSQLDatabaseMetaData* md)
0438 {
0439    //
0440 
0441    TString str;
0442 
0443    str = md->GetDriverName(); 
0444         printf("Driver name                     : %s\n",str.Data());
0445    
0446    str = md->GetDriverVersion();
0447         printf("Driver version                  : %s\n",str.Data()); 
0448 }
0449 
0450 //___________________________________________________________________
0451 void funcInfo(TSQLDatabaseMetaData* md)
0452 {
0453    //
0454 
0455    TString str;
0456 
0457    str =  md->GetSystemFunctions();
0458    printf("Supported system functions \n");
0459    printf("--------------------------------------------------- \n");
0460    printf("%s\n\n",str.Data());
0461    
0462    printf("Supported string functions\n");
0463    printf("--------------------------------------------------- \n");
0464    str = md->GetStringFunctions();
0465    printf("%s\n\n",str.Data());
0466    
0467    printf("Supported time/date functions\n");
0468    printf("--------------------------------------------------- \n");
0469    str = md->GetTimeDateFunctions();
0470    printf("%s\n\n",str.Data());
0471       
0472    printf("Supported numeric functions\n");
0473    printf("---------------------------------------------------\n");
0474    str = md->GetNumericFunctions();
0475    printf("%s\n\n",str.Data());
0476 }
0477 
0478 //___________________________________________________________________
0479 void keywordInfo(TSQLDatabaseMetaData* md)
0480 {
0481    //
0482 
0483    TString str;
0484 
0485    printf("Non-ODBC SQL keywords\n");
0486    printf("--------------------------------------------------- \n");
0487    str = md->GetSQLKeywords();
0488    printf("%s\n\n",str.Data());
0489 }
0490 
0491 //___________________________________________________________________
0492 void TSQLConnection::Print(Option_t *option) const
0493 {
0494    // Prints out information about this connection
0495    //
0496    // If option contains: 
0497    //
0498    //          'r' - prints result set info
0499    //          't' - prints out transaction info
0500    //          'p' - prints out product info
0501    //          'd' - prints out driver info
0502    //          'f' - prints out supported functions
0503    //          'k' - prints out Non-ODBC SQL keywords
0504    //          'c' - prints out catalog info
0505    //          's' - prints out shema info
0506    //          'a' - prints out everything
0507 
0508    TSQLConnection* con = (TSQLConnection*)this;
0509    if(con->IsClosed()) return;
0510 
0511    TString opt = option;
0512    opt.ToLower();
0513 
0514    printf("Connection to :\t%s\n",fMetaData->GetURL().Data());
0515    printf("=================================================== \n\n");
0516    
0517    if(opt.Contains("p") || opt.Contains("a")) {
0518       productInfo(fMetaData);
0519       printf("=================================================== \n\n");
0520    }
0521    if(opt.Contains("d") || opt.Contains("a")) {
0522       driverInfo(fMetaData);
0523       printf("=================================================== \n\n");
0524    }
0525    if(opt.Contains("t") || opt.Contains("a")) {
0526       transactionInfo(fMetaData);
0527       printf("=================================================== \n\n");
0528    }
0529    if(opt.Contains("f") || opt.Contains("a")) {
0530       funcInfo(fMetaData);
0531       printf("=================================================== \n\n");
0532    }
0533    if(opt.Contains("k") || opt.Contains("a")) {
0534       keywordInfo(fMetaData);
0535       printf("=================================================== \n\n");
0536    }
0537 
0538    if(opt.Contains("r") || opt.Contains("a")) {
0539       printf("Supported TSQLResultSet types\n");
0540       printf("--------------------------------------------------- \n");
0541       rsInfo(fMetaData,kTYPE_FORWARD_ONLY,"kTYPE_FORWARD_ONLY");
0542       rsInfo(fMetaData,kTYPE_SCROLL_INSENSITIVE,"kTYPE_SCROLL_INSENSITIVE");
0543       rsInfo(fMetaData,kTYPE_SCROLL_SENSITIVE,"kTYPE_SCROLL_SENSITIVE");
0544       printf("\n=================================================== \n");
0545    }
0546    if(opt.Contains("c") || opt.Contains("a")) {
0547       catalogInfo(fMetaData);
0548       printf("=================================================== \n\n");
0549    }
0550    if(opt.Contains("s") || opt.Contains("a")) {
0551       schemaInfo(fMetaData);
0552       printf("=================================================== \n\n");
0553    }
0554 }
0555 
0556 //___________________________________________________________________
0557 const char* TSQLConnection::GetName() const
0558 {
0559    // returns dsn/url
0560 
0561    TSQLConnection* con = (TSQLConnection*)this;
0562    if(con->IsClosed()) return 0;
0563 
0564    return fMetaData->GetURL().Data();
0565 }
0566 
0567 //___________________________________________________________________  
0568 const char* TSQLConnection::GetTitle() const
0569 {
0570    // returns nothing 
0571 
0572    TSQLConnection* con = (TSQLConnection*)this;
0573    if(con->IsClosed()) return 0;
0574    return "";
0575 }