Back to home page

sPhenix code displayed by LXR

 
 

    


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

0001 // $Id: TSQLUrl.cxx,v 1.2 2009/10/09 12:28:48 pinkenbu Exp $
0002 //*-- Author : Valeriy Onuchin 14/02/2000
0003 //
0004 
0005 ////////////////////////////////////////////////////////////////////
0006 //
0007 // The connection string can be specified by DSN or URL.
0008 // The default format of URL string is:
0009 //
0010 // protocol:[subprotocol:][driver:]//host[:port]/[database][?options]
0011 //
0012 // where:
0013 //    protocol - DBMS type , e.g. mysql,oracle, etc.
0014 //    subprotocol - driver type , currently: "odbc"
0015 //    driver - driver name ( it could be alias name defined in /etc/odbcinst ) 
0016 //             or path to the driver lib, e.g. myodbc - /usr/local/lib/libmyodbc.so
0017 //
0018 //             If absolute pathname is not specified, driver manager will try to
0019 //             find "lib[driver].so" in the following directories"
0020 //                /usr/lib,
0021 //                /usr/local/lib,
0022 //                $ROOTSYS/lib, 
0023 //
0024 //    host - host name or IP address of database server
0025 //    port - port number
0026 //    database - name of database
0027 //    options - string key=value's separated by ';' or '&'     
0028 //
0029 //  Example: "mysql:odbc:myodbc://myhost:3306/test?Trace=Yes;TraceFile=qq.log"
0030 //
0031 //  You can do the same via "mysql://myhost/test?Trace=Yes;TraceFile=qq.log"
0032 //  The missing parts of connect string are set to default values.
0033 // 
0034 //    For MySQL these values are:
0035 //
0036 //    subprotcol = odbc
0037 //    driver = /usr/local/lib/libmyodbc.so 
0038 //    port = 3306
0039 //    database = test
0040 //    options = "Trace=;TraceFile="  
0041 //
0042 //
0043 // See also: 
0044 //     TSQLConnection TSQLDriverManager 
0045 //
0046 /////////////////////////////////////////////////////////////////////
0047 
0048 #include <RDBC/TSQLUrl.h>
0049 #include <RDBC/TSQLDriverManager.h>
0050 #include <RDBC/TSQLDriverInfo.h>
0051 #include <iostream>
0052 #include <TString.h>
0053 #include <TList.h>
0054 #include <TSystem.h>
0055 #include <TNamed.h>
0056 #include <TRefCnt.h>
0057 #include <cstdlib>
0058 
0059 ClassImpQ(TSQLUrl)
0060 
0061 /////////////////////////////////////////////////////////////////////
0062 //
0063 //  TSQLUrlParser - auxilary class used for parsing of URL string
0064 //     It has several subclasses, i.e. OracleParser,MySQLParser etc.
0065 //     which handle database specific cases.  
0066 //
0067 //
0068 /////////////////////////////////////////////////////////////////////
0069 class TSQLUrlParser: public TQObject, public TRefCnt
0070 {
0071 friend class TSQLUrl;
0072 
0073 protected:
0074 
0075    enum EErrorBits {
0076       kErrProtocol   = BIT(0),   // wrong protocol 
0077       kErrSubProtocol= BIT(1),   // wrong subprotocol 
0078       kErrDriver     = BIT(2),   // wrong or not existent driver
0079       kErrHost       = BIT(3),   // wrong host
0080       kErrPort       = BIT(4),   // wrong port
0081       kErrFile       = BIT(5),   // wrong file/database 
0082       kErrDatabase   = BIT(5),   // wrong file/database 
0083       kErrAnchor     = BIT(6),   // wrong anchor 
0084       kErrOption     = BIT(7)    // wrong option
0085    };
0086 
0087    TString  fDriver;    // driver name  
0088    TString  fFullUrl;   // full url string 
0089    TString  fDSN;       // DataSourceName 
0090    TString  fProtocol;  // protocol: oracle, mysql, etc
0091    TString  fSubProtocol;  // sub-protocol:odbc, thin, etc
0092    TString  fHost;      // remote host
0093    TString  fFile;      // remote object
0094    TString  fAnchor;    // anchor in object
0095    TString  fOptions;   // options (after ?)
0096    TString  fDescription; // description
0097    TString  fPort;      // port through which to contact remote server  
0098    Int_t    fStatus;    // O if url is valid , non-zero otherwise
0099    Bool_t   fDynamicDSN;   // kTRUE if DSN is created at dynamically
0100          
0101 protected:
0102    virtual TString DefaultProtocol() { return "odbc"; }
0103    virtual TString DefaultSubProtocol() { return "odbc"; }
0104    virtual TString DefaultDriver() { return ""; }
0105    virtual TString DefaultHost() { return "localhost"; }
0106    virtual TString DefaultDatabase() { return ""; }
0107    virtual TString DefaultPort() { return ""; }
0108    virtual TString DefaultOptions() { return ""; }
0109    virtual TString DefaultAnchor() { return ""; }
0110    virtual TString DefaultDescription() { return ""; }
0111    virtual TString DefaultDriverPath() { return ""; }
0112 
0113    virtual Bool_t  ValidProtocol(const TString&);
0114    virtual Bool_t  ValidSubProtocol(const TString&);
0115    virtual Bool_t  ValidDriver(const TString&);
0116    virtual Bool_t  ValidHost(const TString&);
0117    virtual Bool_t  ValidDatabase(const TString&);
0118    virtual Bool_t  ValidPort(const TString&);
0119    virtual Bool_t  ValidOption(const TString&);
0120    virtual Bool_t  ValidAnchor(const TString&);
0121    virtual void    Validate();
0122    virtual void    SetDefaults();
0123    virtual void    SetFullUrl();
0124 public:
0125    TSQLUrlParser():TQObject(),TRefCnt() { }
0126    TSQLUrlParser(const TString& url);
0127    TSQLUrlParser& operator=(const TSQLUrlParser& url);
0128    void Throw( TSQLException* e ) { Emit("Throw(TSQLException*)",(long)e); } //*SIGNAL*
0129    virtual Bool_t IsValid() { return fStatus==0; }
0130 };
0131 
0132 /////////////////////////////////////////////////////////////////////
0133 class Tokenizer 
0134 {
0135 private:
0136    TString fString;     // string to tokenize
0137    TString fDelim;      // delimter
0138    Ssiz_t  fDL;         // delim length 
0139    
0140 public:
0141    ~Tokenizer() {}
0142 
0143    Tokenizer(const TString& str,const TString& delim) 
0144    { 
0145       SetString(str);
0146       SetDelim(delim); 
0147    } 
0148 
0149    Tokenizer(const TString& str) 
0150    { 
0151       SetString(str);
0152    } 
0153 
0154    TString GetString() const { return fString; }
0155    void SetString(const TString& str) 
0156    { 
0157       // force new TString w/ separate reference counting
0158       // so internal Tokenizer actions (effective modification of fData)
0159       // by Forw/Back don't disturb const TString& passed in to ctor
0160       const char* strCopy = str.Data();
0161       fString = TString(strCopy);
0162    }
0163 
0164    void SetDelim(const TString& delim)
0165    {
0166       fDelim = delim;
0167       fDL = fDelim.Length();
0168    }
0169 
0170    TString Skip(Int_t n)
0171    {
0172       fString = fString(n,fString.Length()-n);
0173       return fString;
0174    }
0175 
0176    TString Before()
0177    {
0178       // Returns string before delim
0179 
0180       Int_t idx = fString.First(fDelim.Data());
0181 
0182       if(idx!=kNPOS) {
0183          return fString(0,idx);
0184       } else {
0185          return fString;
0186       }
0187    }
0188 
0189    TString After()
0190    {
0191       // Returns string after delim
0192 
0193       Int_t idx = fString.First(fDelim.Data());
0194 
0195       if(idx!=kNPOS) {
0196          return fString(idx+fDL,fString.Length());
0197       } else {
0198          return fString;
0199       }
0200    }
0201    
0202    TString Forw(char term=0)
0203    {
0204       //  - Looks for fDelim string which is before "term char"
0205       // - Returns string before fDelim. 
0206       // - Cuts fString after fDelim.
0207 
0208       TString str;
0209 
0210       Int_t idx1 = fString.First(term);
0211 
0212       if(idx1!=kNPOS) {
0213          str = fString(0,idx1);
0214       } else {
0215          str = fString;
0216          idx1 = 0;
0217       }
0218       
0219       Int_t idx = str.Index(fDelim.Data());
0220 
0221       if(idx!=kNPOS) {
0222          fString = fString(idx+fDL,fString.Length());
0223          return str(0,idx);
0224       } else {
0225          return fString;
0226       }
0227    }   
0228 
0229    TString Back(char term=0)
0230    {
0231       // - Looks for fDelim string which is after "term char"
0232       // - Returns string after fDelim. 
0233       // - Cuts fString before fDelim.
0234 
0235       TString str;
0236 
0237       Int_t idx1 = fString.Last(term);
0238 
0239       if(idx1!=kNPOS && idx1<fString.Length()) {
0240          str = fString(idx1,fString.Length());
0241       } else {
0242          str = fString;
0243          idx1 = 0;
0244       }
0245 
0246       Int_t idx = str.Index(fDelim.Data());
0247 
0248       if(idx!=kNPOS) {
0249          fString = fString(0,idx+idx1);
0250          return str(idx+fDL,str.Length());
0251       } else {
0252          return "";
0253       }
0254    }
0255 };
0256 
0257 /////////////////////////////////////////////////////////////////////
0258 //___________________________________________________________________
0259 TSQLUrlParser::TSQLUrlParser(const TString& url):TQObject(),TRefCnt()
0260 {
0261    //
0262 
0263    TString str;
0264    fDynamicDSN = kTRUE;
0265    fStatus = 0;
0266 
0267    Tokenizer parser(url);
0268 
0269    // protocol
0270    parser.SetDelim(":");
0271    fProtocol = parser.Forw('/');
0272 
0273    if(fProtocol.IsNull()) {   // dsn-like  
0274       fFullUrl = url;
0275       fDSN = url;
0276       fProtocol = DefaultProtocol();
0277       fDynamicDSN = kFALSE;
0278       return;
0279    }
0280 
0281    fProtocol.ToLower();
0282 
0283    // subprotocol
0284    parser.SetDelim(":");       // 
0285    fSubProtocol = parser.Forw('/');   // 
0286    fSubProtocol.ToLower();
0287 
0288    parser.SetDelim("://");
0289    fDriver= parser.Forw('@');
0290 
0291    if(fDriver.BeginsWith("//")) {  
0292       fDriver="";
0293       parser.Skip(2);
0294    }
0295 
0296    parser.SetDelim("?");
0297    fOptions = parser.Back(':');
0298 
0299    parser.SetDelim("#");
0300    fAnchor = parser.Back(':');   //
0301 
0302    if(fAnchor.IsNull()) fAnchor = DefaultAnchor(); 
0303 
0304    // host + port + file
0305    parser.SetDelim("/");
0306    fFile = parser.Back(':');
0307 
0308    if(parser.GetString().Contains(":")) {
0309       parser.SetDelim(":"); 
0310       fPort = parser.After();
0311       fHost = parser.Before();
0312    } else {
0313       fHost = parser.GetString();
0314    }
0315 
0316    if(fProtocol=="file") { // small fix
0317       if( fHost != "localhost") {
0318       // See if "host" is actually an environmental variable
0319         const char* host  = 0;
0320         if ( fHost.BeginsWith("$") ) host = getenv(fHost.Data()+1);
0321         if ( host ) { 
0322           fFile.Prepend("/");
0323           fFile.Prepend(host);
0324         }
0325         else        fFile = "/" + fHost + fFile;
0326         fHost = "localhost";
0327       }
0328    }
0329 }
0330 
0331 //___________________________________________________________________
0332 void TSQLUrlParser::SetFullUrl()
0333 {
0334    //
0335 
0336    if(fDynamicDSN) { //
0337       fFullUrl = fProtocol + ":" + fSubProtocol + ":";
0338       fFullUrl += fDriver + "://";
0339       if(!(fHost=="localhost" && fPort.IsNull())) fFullUrl += fHost; 
0340       fFullUrl += fPort.IsNull() ? "" : ":"; 
0341       fFullUrl += fPort;
0342       if((fHost=="localhost"&& fPort.IsNull())) fFullUrl +=  "/";
0343       fFullUrl += fFile; 
0344       fFullUrl += fOptions.IsNull() ? "" : "?";
0345       fFullUrl += fOptions;
0346    }
0347 }
0348 
0349 //___________________________________________________________________
0350 void TSQLUrlParser::SetDefaults()
0351 {
0352    // default settings
0353 
0354    if(fSubProtocol.IsNull()) fSubProtocol = DefaultSubProtocol();
0355    if(fDriver.IsNull()) fDriver = DefaultDriver();
0356    if(fOptions.IsNull()) fOptions = DefaultOptions();
0357    if(fDescription.IsNull()) fDescription = DefaultDescription();
0358    if(fFile.IsNull()) fFile = DefaultDatabase();
0359    if(fPort.IsNull()) fPort = DefaultPort();
0360    if(fHost.IsNull()) fHost = DefaultHost();
0361 }
0362 
0363 //___________________________________________________________________
0364 void TSQLUrlParser::Validate()
0365 {
0366    //
0367 
0368    TString str;
0369 
0370    if(!ValidProtocol(fProtocol)) {
0371       str = "Wrong format of protocol: ";
0372       str += fProtocol;
0373       fProtocol="none";
0374       Throw(new TSQLException(str,""));
0375       fStatus = fStatus | kErrProtocol;
0376    }
0377 
0378    if(!ValidSubProtocol(fSubProtocol)) {
0379       str = "Wrong format of sub-protocol: ";
0380       str += fSubProtocol;
0381       fSubProtocol="none";
0382       Throw(new TSQLException(str,""));
0383       fStatus = fStatus | kErrSubProtocol;
0384    }
0385 
0386    if(!ValidDriver(fDriver)) {
0387       str = "Wrong Driver : ";
0388       str += fDriver;
0389       fDriver="none";
0390       Throw(new TSQLException(str,""));
0391       fStatus = fStatus | kErrDriver;
0392    }
0393  
0394    if(!ValidHost(fHost)) {
0395       str = "Wrong format of host: ";
0396       str += fHost;
0397       fHost="none";
0398       Throw(new TSQLException(str,""));
0399       fStatus = fStatus | kErrHost;
0400    } 
0401 
0402    if(!ValidDatabase(fFile)) {
0403       str = "Wrong format of file/database: ";
0404       str += fFile;
0405       fFile="none";
0406       Throw(new TSQLException(str,""));
0407       fStatus = fStatus | kErrFile;
0408    }
0409 
0410    if(!ValidPort(fPort)) {
0411       str = "Wrong port: ";
0412       str += fPort;
0413       fPort="none";
0414       Throw(new TSQLException(str,""));
0415       fStatus = fStatus | kErrPort;
0416    }
0417 
0418    if(!ValidOption(fOptions)) {
0419       str = "Wrong format of option: ";
0420       str += fOptions;
0421       fOptions="none";
0422       Throw(new TSQLException(str,""));
0423       fStatus = fStatus | kErrOption;
0424    }
0425 
0426    if(fDSN.IsNull()) { // 
0427 //    unixODBC imposes a 32 char limit on this (SQL_MAX_DSN_LENGTH)
0428 //    make each name distinct to avoid ODBCINI caching issues
0429       static Int_t nConnect = 0;
0430       fDSN = fProtocol + Form("%d-%d",gSystem->GetPid(),++nConnect);
0431    }
0432 }
0433 
0434 //___________________________________________________________________
0435 TSQLUrlParser& TSQLUrlParser::operator=(const TSQLUrlParser& url)
0436 {
0437    //
0438  
0439    if (this != &url) {
0440       fDriver = url.fDriver; 
0441       fFullUrl = url.fFullUrl;
0442       fDSN = url.fDSN;
0443       fProtocol = url.fProtocol;
0444       fSubProtocol = url.fSubProtocol;
0445       fHost = url.fHost;
0446       fFile = url.fFile;
0447       fAnchor = url.fAnchor;
0448       fOptions = url.fOptions;
0449       fDescription = url.fDescription;
0450       fPort = url.fPort;
0451       fStatus = url.fStatus;
0452       fDynamicDSN = url.fDynamicDSN;
0453    }
0454    return *this;
0455 }     
0456 
0457 //___________________________________________________________________
0458 Bool_t TSQLUrlParser::ValidProtocol(const TString& prot) 
0459 { 
0460    //
0461 
0462    const char* str = prot.Data();
0463  
0464    for (Ssiz_t i = 0; i < prot.Length(); i++) {
0465       if( !isalnum(str[i]) && str[i]!='-' ) return kFALSE;
0466    }
0467    return kTRUE; 
0468 }
0469 
0470 //___________________________________________________________________
0471 Bool_t TSQLUrlParser::ValidSubProtocol(const TString& prot) 
0472 { 
0473    //
0474    const char* str = prot.Data();
0475  
0476    for (Ssiz_t i = 0; i < prot.Length(); i++) {
0477       if( !isalnum(str[i]) && str[i]!='-' ) return kFALSE;
0478    }
0479    return kTRUE; 
0480 }
0481 
0482 //___________________________________________________________________
0483 Bool_t TSQLUrlParser::ValidDriver(const TString& drvname) 
0484 { 
0485    //
0486 
0487    Char_t* chrStr =0;
0488    TList* li = TSQLDriverManager::GetDrivers();
0489    TSQLDriverInfo* drv;
0490    TString str;
0491    TNamed* obj;
0492    TString key;
0493    TString value;
0494    TString so = "."; so += gSystem->GetSoExt();
0495    TString str2;
0496    TString name = chrStr = gSystem->ExpandPathName(drvname.Data());
0497    delete [] chrStr;
0498 
0499    if(li) {
0500       TIter next(li);
0501 
0502       while((drv=(TSQLDriverInfo*)next())) {
0503          str = drv->GetDescription();
0504          if(str==name) return kTRUE;
0505          li=drv->GetAttributes();
0506          TIter nexta(li);
0507       
0508          while((obj=(TNamed*)nexta())) {
0509             str=obj->GetName();
0510             str.ReplaceAll(" ","");
0511             str.ReplaceAll("\t","");
0512             Int_t i = str.Index("=");
0513             key = str(0,i);
0514             value = str(i+1,str.Length()-i-1);
0515             key.ToLower();
0516             if(key=="driver" && value==name) return kTRUE;
0517          }
0518       } 
0519    }
0520 
0521    Bool_t af = gSystem->IsAbsoluteFileName(name.Data());
0522 
0523    if(!af) {
0524       if(!name.BeginsWith("lib")) name = "lib" + name;
0525       if(!name.EndsWith(so.Data())) name += so;
0526 
0527       str2 = chrStr = gSystem->ConcatFileName(DefaultDriverPath().Data(),name.Data());
0528       delete [] chrStr;
0529       if(!gSystem->AccessPathName(str2.Data()))  { fDriver = str2; return kTRUE; }
0530 
0531       str2 = chrStr = gSystem->ConcatFileName("/usr/lib",name.Data());
0532       delete [] chrStr;
0533       if(!gSystem->AccessPathName(str2.Data()))  { fDriver = str2; return kTRUE; }
0534 
0535       str2 = chrStr = gSystem->ConcatFileName("/usr/local/lib",name.Data());
0536       delete [] chrStr;
0537       if(!gSystem->AccessPathName(str2.Data()))   { fDriver = str2; return kTRUE; }
0538 
0539       TString rootsys = chrStr = gSystem->ExpandPathName("$ROOTSYS/lib");
0540       delete [] chrStr;
0541 
0542       str2 = chrStr = gSystem->ConcatFileName(rootsys.Data(),name.Data());
0543       delete [] chrStr;
0544       if(!gSystem->AccessPathName(str2.Data()))   { fDriver = str2; return kTRUE; }
0545 
0546       // check driver at $LD_LIBRARY_PATH
0547       TString ldlib = gSystem->Getenv("LD_LIBRARY_PATH");
0548 
0549       if(!ldlib.IsNull()) {
0550          Int_t sep = 0;
0551          Int_t prev = 0;
0552          TString sublib;
0553 
0554          while(1) {
0555             sep = ldlib.Index(":",prev);
0556             if(sep==kNPOS) break;
0557             sublib = ldlib(prev,sep-prev);
0558 
0559 
0560             if( (sublib=="/usr/lib") ||
0561                 (sublib=="/usr/local/lib") ||
0562                 (sublib==rootsys) ) {
0563                prev += sublib.Length()+1;  
0564                continue;
0565             }
0566             prev = sep+1;
0567 
0568             str2 = chrStr = gSystem->ConcatFileName(sublib.Data(),name.Data());
0569             delete [] chrStr;
0570             if(!gSystem->AccessPathName(str2.Data()))   { fDriver = str2; return kTRUE; }
0571          }
0572          sublib = ldlib(prev,ldlib.Length()-prev);
0573          str2 = chrStr = gSystem->ConcatFileName(sublib.Data(),name.Data());
0574          delete [] chrStr;
0575          if(!gSystem->AccessPathName(str2.Data()))   { fDriver = str2; return kTRUE; }        
0576       }
0577 
0578       return kFALSE;
0579    } else {
0580       if(!gSystem->AccessPathName(name.Data())) { 
0581          fDriver = name; 
0582          return kTRUE; 
0583       } else {
0584          fDriver = name;
0585          return kFALSE;  
0586       }
0587    }
0588    return kFALSE; 
0589 }
0590 
0591 //___________________________________________________________________
0592 Bool_t TSQLUrlParser::ValidHost(const TString& host) 
0593 { 
0594    //
0595    const char* str = host.Data();
0596    char prevch;
0597 
0598    for (Ssiz_t i = 0; i < host.Length(); i++) {
0599       if( (!isalnum(str[i]) && str[i]!='.' && str[i]!='-') || 
0600          (str[i]=='.' && prevch=='.') ) return kFALSE;
0601       prevch=str[i];
0602    }
0603    return kTRUE; 
0604 }
0605 
0606 //___________________________________________________________________
0607 Bool_t TSQLUrlParser::ValidDatabase(const TString& db) 
0608 { 
0609    //
0610   
0611    const char* str = db.Data();
0612 
0613    for (Ssiz_t i = 0; i < db.Length(); i++) {
0614       if( !isascii(str[i]) ) return kFALSE;
0615    }
0616    return kTRUE; 
0617 }
0618 
0619 //___________________________________________________________________
0620 Bool_t TSQLUrlParser::ValidPort(const TString& port) 
0621 { 
0622    //
0623 
0624    const char* str = port.Data();
0625    return atoi(str)!=0; 
0626 }
0627 
0628 //___________________________________________________________________
0629 Bool_t TSQLUrlParser::ValidOption(const TString& /* opt */) 
0630 { 
0631    //
0632    return kTRUE; 
0633 }
0634 
0635 //___________________________________________________________________
0636 Bool_t TSQLUrlParser::ValidAnchor(const TString&) 
0637 { 
0638    //
0639    return kTRUE;
0640 }
0641 
0642 /////////////////////////////////////////////////////////////////////
0643 class OracleParser: public TSQLUrlParser
0644 {
0645 protected:
0646    TString fTNS;  // TNS name 
0647 
0648    virtual TString DefaultProtocol() { return "oracle"; }
0649    virtual TString DefaultSubProtocol() { return "odbc"; }
0650    virtual TString DefaultDriver();
0651    virtual TString DefaultHost() { return "localhost"; }
0652    virtual TString DefaultDatabase() { return "ORCL"; }
0653    virtual TString DefaultPort() { return "1521"; }
0654    virtual TString DefaultOptions();
0655    virtual TString DefaultDescription() { return "Connection via OpenLink ODBC driver to Oracle database"; }
0656 public:
0657    OracleParser(const TString& url);
0658 };
0659 
0660 //___________________________________________________________________
0661 OracleParser::OracleParser(const TString& url):TSQLUrlParser(url) 
0662 {
0663    //
0664 
0665    if(fHost.IsNull()) {
0666       if(fFile.BeginsWith("@")) {
0667          Tokenizer parser(fFile);
0668          fFile = parser.Skip(1);
0669          if(fFile.Contains(":")) {
0670             parser.SetDelim(":");
0671             fTNS = "";
0672             fHost = parser.Forw(0);
0673             fPort = parser.Forw(0);
0674             fFile = parser.GetString();            
0675          } else {
0676             fTNS = parser.GetString();
0677             fHost = "localhost";
0678             fFile = fTNS;
0679          } 
0680       }
0681    }
0682 }
0683 
0684 //___________________________________________________________________
0685 TString OracleParser::DefaultDriver()
0686 {
0687    //
0688 
0689    if(fSubProtocol=="odbc") {
0690       return "oplodbc";
0691    } else {
0692       return "";
0693    }
0694 }
0695 
0696 //___________________________________________________________________
0697 TString OracleParser::DefaultOptions()
0698 {
0699    //
0700 
0701    if(fSubProtocol=="odbc") {
0702       return "ServerType=Oracle 8;"
0703              "Protocol=TCP/IP;"
0704              "ReadOnly=Yes;"
0705              "FetchBufferSize=100;"
0706              "UserName=scott;"
0707              "Password=tiger;";
0708    } else {
0709       return "";
0710    }
0711 }
0712 
0713 /////////////////////////////////////////////////////////////////////
0714 class MySQLParser: public TSQLUrlParser
0715 {
0716 protected:
0717    virtual TString DefaultProtocol() { return "mysql"; }
0718    virtual TString DefaultSubProtocol() { return "odbc"; }
0719    virtual TString DefaultDriver();
0720    virtual TString DefaultHost() { return "localhost"; }
0721    virtual TString DefaultDatabase() { return "test"; }
0722    virtual TString DefaultPort() { return "3306"; }
0723    virtual TString DefaultOptions() { return "Trace=No;TraceFile=;"; }
0724    virtual TString DefaultDescription() { return "Connection via MyODBC driver to MySQL database"; }
0725 //   virtual TString DefaultDriverPath() { return ""; }
0726 
0727 public:
0728    MySQLParser(const TString& url):TSQLUrlParser(url) { }
0729 };
0730 
0731 //___________________________________________________________________
0732 TString MySQLParser::DefaultDriver()
0733 {
0734    //
0735 
0736    if(fSubProtocol=="odbc") {
0737       return "myodbc";
0738    } else {
0739       return "";
0740    }
0741 }
0742 
0743 /////////////////////////////////////////////////////////////////////
0744 class PostgreSQLParser: public TSQLUrlParser
0745 {
0746 protected:
0747    virtual TString DefaultProtocol() { return "postgresql"; }
0748    virtual TString DefaultSubProtocol() { return "odbc"; }
0749    virtual TString DefaultDriver();
0750    virtual TString DefaultHost() { return "localhost"; }
0751    virtual TString DefaultDatabase() { return "test"; }
0752    virtual TString DefaultPort() { return "5432"; }
0753    virtual TString DefaultOptions() { return ""; }
0754    virtual TString DefaultDescription() { return "Connection via psqlodbc driver to PostgreSQL database"; }
0755 
0756 public:
0757    PostgreSQLParser(const TString& url);
0758 };
0759 
0760 //___________________________________________________________________
0761 PostgreSQLParser::PostgreSQLParser(const TString& url):TSQLUrlParser(url)  
0762 {
0763 }
0764 
0765 //___________________________________________________________________
0766 TString PostgreSQLParser::DefaultDriver()
0767 {
0768   return "psqlodbc";
0769 }
0770 
0771 /////////////////////////////////////////////////////////////////////
0772 class ConnectStringParser: public TSQLUrlParser
0773 {
0774 public:
0775    ConnectStringParser(const TString& fullurl) {
0776       Int_t i1 = fullurl.Index("=");
0777       Int_t i2 = fullurl.Index(";",i1);
0778       fFullUrl = fullurl;
0779       if(i2<0) {
0780          Destroyed();
0781          return;
0782       }
0783       fDSN = fullurl(i1+1,i2-i1-1); 
0784       fOptions = fullurl(i2+1,fullurl.Length()-i2-1);
0785       fDynamicDSN = kFALSE;
0786    }
0787 };
0788 
0789 /////////////////////////////////////////////////////////////////////
0790 //___________________________________________________________________
0791 TSQLUrl::TSQLUrl( const TString& url ):TObject(),TQObject()
0792 {
0793    //
0794 
0795    TString fullurl(url.Data());
0796    fullurl.ReplaceAll(" ","");    // remove blanks 
0797 
0798    if (fullurl.BeginsWith("oracle:",TString::kIgnoreCase))  { fParser = new OracleParser(fullurl); goto exit; }
0799    if (fullurl.BeginsWith("mysql:",TString::kIgnoreCase))   { fParser = new MySQLParser(fullurl);  goto exit; }
0800    if (fullurl.BeginsWith("postgresql:",TString::kIgnoreCase)) { fParser = new PostgreSQLParser(fullurl); goto exit; }
0801 //if (fullurl.BeginsWith("msql:",TString::kIgnoreCase))     { fParser = new mSQLParser(fullurl); goto exit; }
0802 //if (fullurl.BeginsWith("informix:",TString::kIgnoreCase)) { fParser = new InformixParser(fullurl); goto exit; }
0803    if (fullurl.BeginsWith("dsn=",TString::kIgnoreCase))     { fParser = new ConnectStringParser(fullurl);  goto exit; }
0804    if(fullurl.BeginsWith("/")) fullurl = "file:" + fullurl;
0805 
0806 // default:
0807    fParser = new TSQLUrlParser(fullurl);
0808 
0809 exit:
0810    if(fParser->fDynamicDSN) {
0811       fParser->SetDefaults();
0812       fParser->Validate();
0813       fParser->SetFullUrl();
0814 
0815       if(!fParser->IsValid()) {
0816          //Throw(TSQLException*);
0817 //      delete fParser;
0818    
0819       } else fParser->AddReference(); //update counter of references
0820    }
0821 }
0822 
0823 //___________________________________________________________________
0824 TSQLUrl::TSQLUrl( const TString& dsn, const TString& description):
0825    TObject(),TQObject()
0826 {
0827    // ctor.
0828    
0829    fParser = new TSQLUrlParser(dsn);
0830    fParser->fDescription = description;
0831    fParser->AddReference(); //update counter of references
0832 }
0833    
0834 //___________________________________________________________________
0835 TSQLUrl::~TSQLUrl()
0836 {
0837    // dtor.
0838 
0839    fParser->RemoveReference();  // decrease references
0840    if( fParser->References()<=0 ) delete fParser;
0841 }
0842 
0843 //___________________________________________________________________
0844 TSQLUrl::TSQLUrl(const TSQLUrl& url) : TObject(), TQObject()
0845 {
0846    //
0847 
0848    fParser = url.fParser; 
0849    fParser->AddReference(); //update counter of references 
0850 }
0851 
0852 //___________________________________________________________________
0853 TSQLUrl& TSQLUrl::operator=(const TSQLUrl& url)
0854 {
0855    //
0856 
0857    if(this != &url) {
0858       url.fParser->AddReference();
0859       fParser = url.fParser;
0860    }
0861    return *this;  
0862 }
0863 //___________________________________________________________________
0864 TString TSQLUrl::GetDSN() const
0865 {
0866    // Return DataSourceName
0867 
0868    return fParser->fDSN;  //
0869 }
0870 
0871 //___________________________________________________________________
0872 TString TSQLUrl::GetUrl() const  
0873 {
0874    // Return full URL string. 
0875 
0876    return fParser->fFullUrl;  //
0877 }
0878 //___________________________________________________________________
0879 TString TSQLUrl::GetProtocol() const 
0880 {
0881    // protocol: oracle, mysql, postgresql
0882 
0883    return fParser->fProtocol;
0884 }
0885 
0886 //___________________________________________________________________
0887 TString TSQLUrl::GetSubProtocol() const 
0888 {
0889    // subprotocol (driver type) : odbc, oci8, thin etc 
0890 
0891    return fParser->fSubProtocol;
0892 }
0893 
0894 //___________________________________________________________________
0895 TString TSQLUrl::GetDriver() const
0896 {
0897    // driver library name: myodbc, oplodbc, odbcpsql  or full path to driver
0898    //                /usr/lib/libmyodbc.so.1   
0899 
0900    return fParser->fDriver;
0901 }
0902 
0903 //___________________________________________________________________
0904 TString TSQLUrl::GetHost() const
0905 {
0906    // remote host
0907 
0908    return fParser->fHost;
0909 }
0910 
0911 //___________________________________________________________________
0912 TString TSQLUrl::GetFile() const
0913 {
0914    // remote object: file or database
0915 
0916    return fParser->fFile;
0917 }
0918 
0919 //___________________________________________________________________
0920 TString TSQLUrl::GetAnchor() const
0921 {
0922    // anchor in object
0923 
0924    return fParser->fAnchor;
0925 }
0926 
0927 //___________________________________________________________________
0928 TString TSQLUrl::GetOptions() const
0929 {
0930    // options (after ?) 
0931 
0932    return fParser->fOptions;
0933 }
0934 
0935 //___________________________________________________________________
0936 TString TSQLUrl::GetDescription() const
0937 {
0938    // return description string
0939 
0940    return fParser->fDescription;
0941 }
0942 
0943 //___________________________________________________________________
0944 Int_t TSQLUrl::GetPort() const
0945 {
0946    //  port through which to contact remote server
0947 
0948    const char* str = (const char*)fParser->fPort;
0949    return atoi(str);
0950 }
0951 
0952 //___________________________________________________________________
0953 Bool_t TSQLUrl::IsValid() const
0954 {
0955    // 
0956 
0957    return fParser->fStatus == 0;
0958 }
0959 
0960 //___________________________________________________________________
0961 Bool_t TSQLUrl::IsDynamicDSN() const
0962 {
0963    // 
0964 
0965    return fParser->fDynamicDSN;
0966 }
0967 
0968 //___________________________________________________________________
0969 void TSQLUrl::AddOption(const TString& opt)
0970 {
0971    // 
0972 
0973    int l = fParser->fOptions.Length();
0974 
0975    if(l) fParser->fFullUrl += "?";
0976 
0977    if(!l || ( l && !fParser->fOptions.Last(';'))) fParser->fOptions += ";";
0978    fParser->fOptions += opt + ";";
0979    fParser->fFullUrl += opt + ";";
0980 }
0981 
0982 //___________________________________________________________________
0983 const char *TSQLUrl::GetName() const
0984 {
0985    //  
0986 
0987    return GetDSN().Data();
0988 }
0989 
0990 //___________________________________________________________________
0991 const char *TSQLUrl::GetTitle() const
0992 {
0993    // 
0994 
0995    return GetDescription().Data();
0996 }
0997 
0998 //___________________________________________________________________
0999 void TSQLUrl::ls(Option_t *option) const
1000 {
1001    // pritnts url
1002 
1003    Print(option);
1004 }
1005 
1006 //___________________________________________________________________
1007 void TSQLUrl::Print(Option_t *option) const
1008 {
1009    // pritnts url to stdout or to file with name=option
1010 
1011    FILE* fd;
1012    if(!option || !strlen(option) || !IsDynamicDSN()) fd = stdout;
1013    else fd = fopen(option,"w"); 
1014 
1015    if(!fd) {
1016 //      Throw( new TSQLException(Form("TSQLUrl:: Failed to open file: %s",option)) );
1017       return;
1018    }
1019 
1020    if(!fParser->fDSN.IsNull()) fprintf(fd,"[%s]\n", fParser->fDSN.Data()); 
1021    if(!fParser->fDescription.IsNull()) fprintf(fd,"Description\t\t= %s\n", fParser->fDescription.Data());
1022    if(!fParser->fProtocol.IsNull() && (fd == stdout) ) fprintf(fd,"RDBC Protocol\t\t= %s\n", fParser->fProtocol.Data()); 
1023    if(!fParser->fSubProtocol.IsNull() && (fd == stdout) ) fprintf(fd,"RDBC SubProtocol\t\t= %s\n", fParser->fSubProtocol.Data()); 
1024    if(!fParser->fDriver.IsNull()) fprintf(fd,"Driver\t\t= %s\n", fParser->fDriver.Data()); 
1025    if(!fParser->fHost.IsNull()) fprintf(fd,"Server\t\t= %s\n", fParser->fHost.Data()); 
1026    if(!fParser->fPort.IsNull()) fprintf(fd,"Port\t\t= %s\n", fParser->fPort.Data());  
1027    if(!fParser->fFile.IsNull()) fprintf(fd,"Database\t\t= %s\n", fParser->fFile.Data()); 
1028    if(!fParser->fAnchor.IsNull() && (fd == stdout) ) fprintf(fd,"Anchor\t\t= %s\n", fParser->fAnchor.Data()); 
1029    if(!fParser->fOptions.IsNull()) { 
1030       TString str(fParser->fOptions.Data());
1031       str.ReplaceAll(";","\n");
1032       str.ReplaceAll("&","\n");
1033       str.ReplaceAll("=","\t\t= ");
1034       fprintf(fd,"%s",str.Data());
1035    }
1036    fprintf( fd,"\n" );
1037    if(fd != stdout) fclose(fd);
1038 }
1039