From d5969c21321e00cee45a1c08a6fa05bc7b2a7ac3 Mon Sep 17 00:00:00 2001
From: Fons Rademakers <Fons.Rademakers@cern.ch>
Date: Fri, 16 Feb 2007 12:15:41 +0000
Subject: [PATCH] Add extensive description how to setup the Oracle
 instantclient libraries and how to use the Oracle plugin.

git-svn-id: http://root.cern.ch/svn/root/trunk@17987 27541ba8-7e3a-0410-8455-c3a389f83636
---
 oracle/src/TOracleServer.cxx | 157 ++++++++++++++++++++++-------------
 1 file changed, 99 insertions(+), 58 deletions(-)

diff --git a/oracle/src/TOracleServer.cxx b/oracle/src/TOracleServer.cxx
index 7ed2451c32c..9324ef8288a 100644
--- a/oracle/src/TOracleServer.cxx
+++ b/oracle/src/TOracleServer.cxx
@@ -1,4 +1,4 @@
-// @(#)root/oracle:$Name:  $:$Id: TOracleServer.cxx,v 1.16 2006/09/29 13:58:34 brun Exp $
+// @(#)root/oracle:$Name:  $:$Id: TOracleServer.cxx,v 1.17 2006/12/12 11:29:45 rdm Exp $
 // Author: Yan Liu and Shaowen Wang   23/11/04
 
 /*************************************************************************
@@ -9,6 +9,47 @@
  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
  *************************************************************************/
 
+//////////////////////////////////////////////////////////////////////////
+//                                                                      //
+// TOracleServer                                                        //
+//                                                                      //
+// This class implements an OCCI interface to Oracle data bases.        //
+// It uses the instantclient10 software available from Oracle.          //
+// To install this client software do:                                  //
+// 1) Download Instant Client Packages (4 files) from:                  //
+//     http://www.oracle.com/technology/software/tech/oci/instantclient/index.html
+// 2) Unzip the files into instantclient10_1 (Mac OS X example here):   //
+//     unzip instantclient-basic-macosx-10.1.0.3.zip                    //
+//     unzip instantclient-sqlplus-macosx-10.1.0.3.zip                  //
+//     unzip instantclient-sdk-macosx-10.1.0.3.zip                      //
+//     unzip instantclient-jdbc-macosx-10.1.0.3.zip                     //
+// 3) Create two symbolic links for the files that have the version     //
+//    appended:                                                         //
+//      ln -s libclntsh.dylib.10.1 libclntsh.dylib                      //
+//      ln -s libocci.dylib.10.1 libocci.dylib                          //
+// 4) Add instantclient10_1 directory to your (DY)LD_LIBRARY_PATH       //
+//    in your .profile:                                                 //
+//      export DYLD_LIBRARY_PATH="<pathto>/instantclient10_1"           //
+//    Use DY only on Mac OS X.                                          //
+// 5) If you also want to use the sqlplus command line app add also     //
+//      export SQLPATH="<pathto>/instantclient10_1"                     //
+// 6) If you want to connect to a remote db server you will also need   //
+//    to create a tnsname.ora file which describes the local_name for   //
+//    the remote db servers (at CERN most public machines have this     //
+//    file in /etc). If it is not in /etc create TNS_ADMIN:             //
+//      export TNS_ADMIN="<path-to-dir-containing-tnsname.ora>"         //
+// 7) Test it our with the sqlplus command line app:                    //
+//      sqlplus [username][/password]@<local_name>                      //
+//    or                                                                //
+//      sqlplus [username][/password]@//[hostname][:port][/database]    //
+//                                                                      //
+// ATTENTION: This plugin will not work on Mac OS X / Intel as Oracle   //
+// has no intention to release a universal binary of the instantclient  //
+// libraries.                                                           //
+//                                                                      //
+//////////////////////////////////////////////////////////////////////////
+
+
 #include "TOracleServer.h"
 #include "TOracleResult.h"
 #include "TOracleStatement.h"
@@ -26,19 +67,19 @@ ClassImp(TOracleServer)
       if (!IsConnected()) {                             \
          SetError(-1,"Oracle database is not connected",method); \
          return res;                                    \
-      }                                                 
+      }
 
 // catch Oracle exception after try block
 #define CatchError(method)                           \
    catch (SQLException &oraex) {                     \
       SetError(oraex.getErrorCode(), oraex.getMessage().c_str(), method); \
-   }                                                 
+   }
 
 //______________________________________________________________________________
 TOracleServer::TOracleServer(const char *db, const char *uid, const char *pw)
 {
    // Open a connection to a Oracle DB server. The db arguments should be
-   // of the form "oracle://connection_identifier][/<database>]", e.g.:
+   // of the form "oracle://connection_identifier[/<database>]", e.g.:
    // "oracle://cmscald.fnal.gov/test". The uid is the username and pw
    // the password that should be used for the connection.
 
@@ -75,7 +116,7 @@ TOracleServer::TOracleServer(const char *db, const char *uid, const char *pw)
       fPort = url.GetPort();
       fPort = (fPort>0) ? fPort : 1521;
       return;
-      
+
    } CatchError("TOracleServer")
 
    MakeZombie();
@@ -107,7 +148,7 @@ void TOracleServer::Close(Option_t *)
 
    fPort = -1;
 }
-  
+
 //______________________________________________________________________________
 TSQLStatement *TOracleServer::Statement(const char *sql, Int_t niter)
 {
@@ -120,9 +161,9 @@ TSQLStatement *TOracleServer::Statement(const char *sql, Int_t niter)
 
    try {
       oracle::occi::Statement *stmt = fConn->createStatement(sql);
-      
+
       Blob parblob(fConn);
-      
+
       return new TOracleStatement(fEnv, fConn, stmt, niter, fErrorOut);
 
    } CatchError("Statement")
@@ -146,12 +187,12 @@ TSQLResult *TOracleServer::Query(const char *sql)
    try {
       oracle::occi::Statement *stmt = fConn->createStatement();
 
-      // NOTE: before special COUNT query was executed to define number of 
+      // NOTE: before special COUNT query was executed to define number of
       // rows in result set. Now it is not requried, while TOracleResult class
-      // will automatically fetch all rows from resultset when 
-      // GetRowCount() will be called first time. 
+      // will automatically fetch all rows from resultset when
+      // GetRowCount() will be called first time.
       // It is better do not use GetRowCount() to avoid unnecessary memory usage.
-      
+
       stmt->setSQL(sql);
       stmt->setPrefetchRowCount(1000);
       stmt->setPrefetchMemorySize(1000000);
@@ -171,14 +212,14 @@ Bool_t TOracleServer::Exec(const char* sql)
    // Return kTRUE if succesfull
 
    CheckConnect("Exec", kFALSE);
-   
+
    if (!sql || !*sql) {
       SetError(-1, "no query string specified","Exec");
       return kFALSE;
    }
 
    oracle::occi::Statement *stmt = 0;
-   
+
    Bool_t res = kFALSE;
 
    try {
@@ -186,11 +227,11 @@ Bool_t TOracleServer::Exec(const char* sql)
       stmt->execute();
       res = kTRUE;
    } CatchError("Exec")
- 
+
    try {
       fConn->terminateStatement(stmt);
    } CatchError("Exec")
-  
+
    return res;
 }
 
@@ -222,31 +263,31 @@ TSQLResult *TOracleServer::GetTables(const char *dbname, const char * /*wild*/)
 TList* TOracleServer::GetTablesList(const char* wild)
 {
    CheckConnect("GetTablesList",0);
-   
+
    TString cmd("SELECT table_name FROM user_tables");
-   if ((wild!=0) && (*wild!=0)) 
+   if ((wild!=0) && (*wild!=0))
       cmd+=Form(" WHERE table_name LIKE '%s'", wild);
 
    TSQLStatement* stmt = Statement(cmd);
    if (stmt==0) return 0;
-   
+
    TList* lst = 0;
-   
+
    if (stmt->Process()) {
       stmt->StoreResult();
       while (stmt->NextResultRow()) {
-         const char* tablename = stmt->GetString(0); 
+         const char* tablename = stmt->GetString(0);
          if (tablename==0) continue;
          if (lst==0) {
             lst = new TList;
-            lst->SetOwner(kTRUE);   
+            lst->SetOwner(kTRUE);
          }
          lst->Add(new TObjString(tablename));
       }
    }
-   
+
    delete stmt;
-   
+
    return lst;
 }
 
@@ -262,10 +303,10 @@ TSQLTableInfo *TOracleServer::GetTableInfo(const char* tablename)
 
    TString sql;
    sql.Form("SELECT COLUMN_NAME, DATA_TYPE, DATA_LENGTH, DATA_PRECISION, DATA_SCALE, NULLABLE, CHAR_COL_DECL_LENGTH FROM user_tab_columns WHERE table_name = '%s' ORDER BY COLUMN_ID", tablename);
-   
+
    TSQLStatement* stmt = Statement(sql.Data(), 10);
    if (stmt==0) return 0;
-   
+
    if (!stmt->Process()) {
       delete stmt;
       return 0;
@@ -273,20 +314,20 @@ TSQLTableInfo *TOracleServer::GetTableInfo(const char* tablename)
 
    TList* lst = 0;
 
-   stmt->StoreResult();  
-   
+   stmt->StoreResult();
+
    while (stmt->NextResultRow()) {
       const char* columnname = stmt->GetString(0);
       TString data_type = stmt->GetString(1);
       Int_t data_length = stmt->GetInt(2);      // this is size in bytes
-      Int_t data_precision = stmt->GetInt(3);    
+      Int_t data_precision = stmt->GetInt(3);
       Int_t data_scale = stmt->GetInt(4);
       const char* nstr = stmt->GetString(5);
       Int_t char_col_decl_length = stmt->GetInt(6);
       Int_t data_sign = -1; // no info about sign
-      
+
       Int_t sqltype = kSQL_NONE;
-      
+
       if (data_type=="NUMBER") {
          sqltype = kSQL_NUMERIC;
          if (data_precision<=0) {
@@ -296,40 +337,40 @@ TSQLTableInfo *TOracleServer::GetTableInfo(const char* tablename)
          if (data_scale<=0)
             data_scale = -1;
          data_sign = 1;
-      } else 
-      
+      } else
+
       if (data_type=="CHAR") {
          sqltype = kSQL_CHAR;
          data_precision = char_col_decl_length;
          data_scale = -1;
-      } else 
-      
+      } else
+
       if ((data_type=="VARCHAR") || (data_type=="VARCHAR2")) {
          sqltype = kSQL_VARCHAR;
          data_precision = char_col_decl_length;
          data_scale = -1;
       } else
-      
+
       if (data_type=="FLOAT") {
          sqltype = kSQL_FLOAT;
          data_scale = -1;
          if (data_precision==126) data_precision = -1;
          data_sign = 1;
-      } else 
+      } else
 
       if (data_type=="BINARY_FLOAT") {
          sqltype = kSQL_FLOAT;
          data_scale = -1;
          data_precision = -1;
          data_sign = 1;
-      } else 
+      } else
 
       if (data_type=="BINARY_DOUBLE") {
          sqltype = kSQL_DOUBLE;
          data_scale = -1;
          data_precision = -1;
          data_sign = 1;
-      } else 
+      } else
 
       if (data_type=="LONG") {
          sqltype = kSQL_VARCHAR;
@@ -337,32 +378,32 @@ TSQLTableInfo *TOracleServer::GetTableInfo(const char* tablename)
          data_precision = -1;
          data_scale = -1;
       } else
-      
+
       if (data_type.Contains("TIMESTAMP")) {
          sqltype = kSQL_TIMESTAMP;
          data_precision = -1;
       }
-      
+
       Bool_t IsNullable = kFALSE;
       if (nstr!=0)
          IsNullable = (*nstr=='Y') || (*nstr=='y');
-      
-      TSQLColumnInfo* info = 
-         new TSQLColumnInfo(columnname, 
-                            data_type, 
+
+      TSQLColumnInfo* info =
+         new TSQLColumnInfo(columnname,
+                            data_type,
                             IsNullable,
                             sqltype,
                             data_length,
                             data_precision,
                             data_scale,
                             data_sign);
-                            
+
       if (lst==0) lst = new TList;
       lst->Add(info);
    }
-   
+
    delete stmt;
-   
+
    return new TSQLTableInfo(tablename, lst);
 }
 
@@ -376,7 +417,7 @@ TSQLResult *TOracleServer::GetColumns(const char * /*dbname*/, const char *table
    // The result object must be deleted by the user.
 
    CheckConnect("GetColumns",0);
-   
+
 //  make no sense, while method is not implemented
 //   if (SelectDataBase(dbname) != 0) {
 //      SetError(-1, "Database is not connected","GetColumns");
@@ -393,7 +434,7 @@ Int_t TOracleServer::SelectDataBase(const char * /*dbname*/)
    // NOT IMPLEMENTED.
 
    CheckConnect("SelectDataBase", -1);
-   
+
    // do nothing and return success code
    return 0;
 }
@@ -408,7 +449,7 @@ TSQLResult *TOracleServer::GetDataBases(const char * /*wild*/)
    // NOT IMPLEMENTED.
 
    CheckConnect("GetDataBases",0);
-   
+
    return 0;
 }
 
@@ -419,7 +460,7 @@ Int_t TOracleServer::CreateDataBase(const char * /*dbname*/)
    // NOT IMPLEMENTED.
 
    CheckConnect("CreateDataBase",-1);
-      
+
    return -1;
 }
 
@@ -463,15 +504,15 @@ Int_t TOracleServer::Shutdown()
 const char *TOracleServer::ServerInfo()
 {
    // Return Oracle server version info.
-   
+
    CheckConnect("ServerInfo", 0);
 
    fInfo = "Oracle";
    TSQLStatement* stmt = Statement("select * from v$version");
    if (stmt!=0) {
-       stmt->EnableErrorOutput(kFALSE); 
+       stmt->EnableErrorOutput(kFALSE);
        if (stmt->Process()) {
-          fInfo = ""; 
+          fInfo = "";
           stmt->StoreResult();
           while (stmt->NextResultRow()) {
              if (fInfo.Length()>0) fInfo += "\n";
@@ -489,7 +530,7 @@ Bool_t TOracleServer::StartTransaction()
 {
    // Call Commit() to submit all chanes, done before.
    // Commit() ot Rollback() must be used to complete submitted actions or cancel them
-   
+
    return Commit();
 }
 
@@ -498,7 +539,7 @@ Bool_t TOracleServer::Commit()
 {
    // Commits all changes made since the previous Commit() or Rollback()
    // Return kTRUE if OK
-   
+
    CheckConnect("Commit", kFALSE);
 
    try {
@@ -521,6 +562,6 @@ Bool_t TOracleServer::Rollback()
       fConn->rollback();
       return kTRUE;
    } CatchError("Rollback")
-   
+
    return kFALSE;
 }
-- 
GitLab