// @(#)root/net:$Id: TSQLServer.cxx 23091 2008-04-09 15:04:27Z rdm $ // Author: Fons Rademakers 25/11/99 /************************************************************************* * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * * All rights reserved. * * * * For the licensing terms see $ROOTSYS/LICENSE. * * For the list of contributors see $ROOTSYS/README/CREDITS. * *************************************************************************/ ////////////////////////////////////////////////////////////////////////// // // // TSQLServer // // // // Abstract base class defining interface to a SQL server. // // // // To open a connection to a server use the static method Connect(). // // The db argument of Connect() is of the form: // // <dbms>://<host>[:<port>][/<database>], e.g. // // mysql://pcroot.cern.ch:3456/test, oracle://srv1.cern.ch/main, ... // // Depending on the <dbms> specified an appropriate plugin library // // will be loaded which will provide the real interface. // // // // Related classes are TSQLResult and TSQLRow. // // // ////////////////////////////////////////////////////////////////////////// #include "TSQLServer.h" #include "TSQLResult.h" #include "TSQLRow.h" #include "TSQLTableInfo.h" #include "TSQLColumnInfo.h" #include "TROOT.h" #include "TList.h" #include "TObjString.h" #include "TPluginManager.h" #include "TVirtualMutex.h" ClassImp(TSQLServer) //______________________________________________________________________________ TSQLServer *TSQLServer::Connect(const char *db, const char *uid, const char *pw) { // The db should be of the form: <dbms>://<host>[:<port>][/<database>], // e.g.: mysql://pcroot.cern.ch:3456/test, oracle://srv1.cern.ch/main, // pgsql://... or sapdb://... // The uid is the username and pw the password that should be used for // the connection. Depending on the <dbms> the shared library (plugin) // for the selected system will be loaded. When the connection could not // be opened 0 is returned. TPluginHandler *h; TSQLServer *serv = 0; if ((h = gROOT->GetPluginManager()->FindHandler("TSQLServer", db))) { if (h->LoadPlugin() == -1) return 0; serv = (TSQLServer *) h->ExecPlugin(3, db, uid, pw); } if (serv && serv->IsZombie()) { delete serv; serv = 0; } return serv; } //______________________________________________________________________________ Bool_t TSQLServer::Exec(const char* sql) { // Execute sql query. // Usefull for commands like DROP TABLE or INSERT, where result set // is not interested. Return kTRUE if no error TSQLResult* res = Query(sql); if (res==0) return kFALSE; delete res; return !IsError(); } //______________________________________________________________________________ Int_t TSQLServer::GetErrorCode() const { // returns error code of last operation // if res==0, no error // Each specific implementation of TSQLServer provides its own error coding return fErrorCode; } //______________________________________________________________________________ const char* TSQLServer::GetErrorMsg() const { // returns error message of last operation // if no errors, return 0 // Each specific implementation of TSQLServer provides its own error messages return GetErrorCode()==0 ? 0 : fErrorMsg.Data(); } //______________________________________________________________________________ void TSQLServer::ClearError() { // reset error fields fErrorCode = 0; fErrorMsg = ""; } //______________________________________________________________________________ void TSQLServer::SetError(Int_t code, const char* msg, const char* method) { // set new values for error fields // if method is specified, displays error message fErrorCode = code; fErrorMsg = msg; if ((method!=0) && fErrorOut) Error(method,"Code: %d Msg: %s", code, (msg ? msg : "No message")); } //______________________________________________________________________________ Bool_t TSQLServer::StartTransaction() { // submit "START TRANSACTION" query to database // return kTRUE, if succesfull return Exec("START TRANSACTION"); } //______________________________________________________________________________ Bool_t TSQLServer::Commit() { // submit "COMMIT" query to database // return kTRUE, if succesfull return Exec("COMMIT"); } //______________________________________________________________________________ Bool_t TSQLServer::Rollback() { // submit "ROLLBACK" query to database // return kTRUE, if succesfull return Exec("ROLLBACK"); } //______________________________________________________________________________ TList* TSQLServer::GetTablesList(const char* wild) { // Return list of user tables // Parameter wild specifies wildcard for table names. // It either contains exact table name to verify that table is exists or // wildcard with "%" (any number of symbols) and "_" (exactly one symbol). // Example of vaild wildcards: "%", "%name","___user__". // If wild=="", list of all available tables will be produced. // List contain just tables names in the TObjString. // List must be deleted by the user. // Example code of method usage: // // TList* lst = serv->GetTablesList(); // TIter next(lst); // TObject* obj; // while (obj = next()) // cout << "Table: " << obj->GetName() << endl; // delete lst; TSQLResult* res = GetTables(fDB.Data(), wild); if (res==0) return 0; TList* lst = 0; TSQLRow* row = 0; while ((row = res->Next())!=0) { const char* tablename = row->GetField(0); if (lst==0) { lst = new TList; lst->SetOwner(kTRUE); } lst->Add(new TObjString(tablename)); delete row; } delete res; return lst; } //______________________________________________________________________________ Bool_t TSQLServer::HasTable(const char* tablename) { // Tests if table of that name exists in database // Return kTRUE, if table exists if ((tablename==0) || (strlen(tablename)==0)) return kFALSE; TList* lst = GetTablesList(tablename); if (lst==0) return kFALSE; Bool_t res = kFALSE; TObject* obj = 0; TIter iter(lst); // Can be, that tablename contains "_" or "%" symbols, which are wildcards in SQL, // therefore more than one table can be returned as result. // One should check that exactly same name is appears while ((obj = iter()) != 0) if (strcmp(tablename, obj->GetName())==0) res = kTRUE; delete lst; return res; } //______________________________________________________________________________ TSQLTableInfo* TSQLServer::GetTableInfo(const char* tablename) { // Producec TSQLTableInfo object, which contain info about // table itself and each table column // Object must be deleted by user. if ((tablename==0) || (*tablename==0)) return 0; TSQLResult* res = GetColumns(fDB.Data(), tablename); if (res==0) return 0; TList* lst = 0; TSQLRow* row = 0; while ((row = res->Next())!=0) { const char* columnname = row->GetField(0); if (lst==0) lst = new TList; lst->Add(new TSQLColumnInfo(columnname)); delete row; } delete res; return new TSQLTableInfo(tablename, lst); }