/* ======================================================================== *\ ! ! * ! * This file is part of MARS, the MAGIC Analysis and Reconstruction ! * Software. It is distributed to you in the hope that it can be a useful ! * and timesaving tool in analysing Data of imaging Cerenkov telescopes. ! * It is distributed WITHOUT ANY WARRANTY. ! * ! * Permission to use, copy, modify and distribute this software and its ! * documentation for any purpose is hereby granted without fee, ! * provided that the above copyright notice appear in all copies and ! * that both that copyright notice and this permission notice appear ! * in supporting documentation. It is provided "as is" without express ! * or implied warranty. ! * ! ! ! Author(s): Thomas Bretz 2/2004 ! ! Copyright: MAGIC Software Development, 2000-2004 ! ! \* ======================================================================== */ //////////////////////////////////////////////////////////////////////// // // MSQLServer // // Using this instead of a TSQLServer gives the possibility to // browse a database server through the TBrowser and it will offer // many features usefull working with relational tables. // // Use it like TSQlServer: // new MSQLServer("mysql://localhost:3306", "hercules", "stdmagicpassword"); // // now start your TBrowser // new TBrowser; // //////////////////////////////////////////////////////////////////////// #include "MSQLServer.h" #include #include #include #include #include #include #include #include #include #include ClassImp(MSQLServer); using namespace std; // -------------------------------------------------------------------------- // // Used in virtual function TObject::Browse() to create the // void MSQLServer::BrowseColumn(TBrowser *b) /*FOLD00*/ { const TString query0(Form("EXPLAIN %s.%s %s", (const char*)fDataBase, (const char*)fTable, (const char*)fColumn)); const TString query1(Form("SELECT %s FROM %s.%s", (const char*)fColumn, (const char*)fDataBase, (const char*)fTable)); //cout << query0 << endl; TSQLResult *res = fServ->Query(query0); if (!res) { cout << "query - failed: " << query0 << endl; return; } TSQLRow *row=res->Next(); const TString desc((*row)[1]); delete res; const Bool_t isnum = !desc.Contains("char", TString::kIgnoreCase) && !desc.Contains("text", TString::kIgnoreCase); cout << query1 << endl; res = fServ->Query(query1); if (!res) { cout << "query - failed: " << query1 << endl; return; } TArrayD arr(2); Int_t num=0; Double_t max=0; Double_t min=0; Double_t sum=0; Double_t sqr=0; while ((row=res->Next())) { const TString row0((*row)[0]); if (!isnum) { cout << row0 << endl; continue; } if (num==arr.GetSize()) arr.Set(arr.GetSize()*2); arr[num] = atof(row0.Data()); if (num==0) min=max=arr[0]; if (arr[num]>max) max = arr[num]; if (arr[num]0) { /* cout << "Num: " << num << endl; cout << "Mean: " << sum/num << endl; cout << "Range: " << max-min << endl; cout << "RMS: " << TMath::Sqrt(sqr/num-sum*sum/num/num) << endl; */ num0 = (Int_t)((max-min)*40/TMath::Sqrt(sqr/num-sum*sum/num/num)); } const TString title(Form("#splitline{%s}{<%s>}", (const char*)query1, (const char*)desc)); TH1F *hist=new TH1F(fColumn, title, num0, min, max); for (int i=0; iFill(arr[i]); //cout << "Done." << endl; hist->Draw(); hist->SetBit(kCanDelete); } void MSQLServer::BrowseTable(TBrowser *b) /*FOLD00*/ { TSQLResult *res = fServ->GetColumns(fDataBase, fTable); if (!res) return; TSQLRow *row; while ((row=res->Next())) { TString row0((*row)[0]); MSQLServer *sql = (MSQLServer*)fList.FindObject(Form("%s/%s/%s", (const char*)fDataBase, (const char*)fTable, (const char*)row0)); if (!sql) { sql = new MSQLColumn(fServ, fDataBase, fTable, row0); fList.Add(sql); } b->Add(sql, row0); } } void MSQLServer::BrowseDataBase(TBrowser *b) /*FOLD00*/ { TSQLResult *res = fServ->GetTables(fDataBase); if (!res) return; TSQLRow *row; while ((row=res->Next())) { TString row0((*row)[0]); MSQLServer *sql = (MSQLServer*)fList.FindObject(Form("%s/%s", (const char*)fDataBase, (const char*)row0)); if (!sql) { sql = new MSQLServer(fServ, fDataBase, row0); fList.Add(sql); } b->Add(sql, row0); } } void MSQLServer::BrowseServer(TBrowser *b) /*FOLD00*/ { TSQLResult *res = fServ->GetDataBases(); if (!res) return; TSQLRow *row; while ((row=res->Next())) { const TString row0((*row)[0]); MSQLServer *sql = (MSQLServer*)fList.FindObject(row0); if (!sql) { sql = new MSQLServer(fServ, row0); fList.Add(sql); } b->Add(sql, row0); } } void MSQLServer::PrintLine(const TArrayI &max) /*FOLD00*/ { cout << "+" << setfill('-'); for (int i=0; iGetFieldLength(i)); rows.Add(row); } cout << endl; PrintLine(max); cout << "|" << setfill(' '); for (int i=0; iGetColumns(fDataBase, fTable); if (!res) return ""; TString fields; TSQLRow *row; TList rows; while ((row=res->Next())) rows.Add(row); TIter Next(&rows); while ((row=(TSQLRow*)Next())) { fields += (*row)[0]; if (row!=rows.Last()) fields += ", "; } return fields; } void MSQLServer::PrintQuery(const char *query) const /*FOLD00*/ { TSQLResult *res = fServ->Query(query); if (res) { PrintTable(*res); delete res; } else cout << "Query failed: " << query << endl; } void MSQLServer::Print(Option_t *o) const /*FOLD00*/ { switch (fType) { case kIsServer: PrintQuery("SHOW DATABASES"); break; case kIsDataBase: PrintQuery(Form("SHOW TABLES FROM %s", (const char*)fDataBase)); break; case kIsTable: PrintQuery(Form("SELECT * FROM %s.%s", (const char*)fDataBase, (const char*)fTable)); break; case kIsColumn: PrintQuery(Form("SELECT %s FROM %s.%s", (const char*)fColumn, (const char*)fDataBase, (const char*)fTable)); break; default: break; } } void MSQLServer::ShowColumns() const /*FOLD00*/ { switch (fType) { case kIsTable: PrintQuery(Form("SHOW FULl COLUMNS FROM %s.%s", (const char*)fDataBase, (const char*)fTable)); break; case kIsColumn: PrintQuery(Form("SHOW FULl COLUMNS FROM %s.%s LIKE %s", (const char*)fDataBase, (const char*)fTable, (const char*)fColumn)); break; default: //Print(); break; } } void MSQLServer::ShowStatus() const /*FOLD00*/ { switch (fType) { case kIsServer: PrintQuery("SHOW STATUS"); break; case kIsDataBase: PrintQuery(Form("SHOW TABLE STATUS FROM %s", (const char*)fDataBase)); break; case kIsTable: PrintQuery(Form("SHOW TABLE STATUS FROM %s LIKE %s", (const char*)fDataBase, (const char*)fTable)); break; default: break; } } void MSQLServer::ShowTableIndex() const /*FOLD00*/ { switch (fType) { case kIsTable: case kIsColumn: PrintQuery(Form("SHOW INDEX FROM %s.%s", (const char*)fDataBase, (const char*)fTable)); break; default: break; } } void MSQLServer::ShowTableCreate() const /*FOLD00*/ { switch (fType) { case kIsTable: case kIsColumn: PrintQuery(Form("SHOW CREATE TABLE %s.%s", (const char*)fDataBase, (const char*)fTable)); break; default: break; } } void MSQLServer::Close(Option_t *option) /*FOLD00*/ { if (fType==kIsServer) fServ->Close(option); } // -------------------------------------------------------------------------- // // Send a SQL query to the SQl server. // // If MSQLServer is no server (column, row, ...) NULL is returned and an // error message is send to stdout. // // If the query failed for some reason an error message is send to stdout // and NULL is returned. // // If everything works fine a TSQLResult is returned. Make sure that you // delete it! // TSQLResult *MSQLServer::Query(const char *sql) /*FOLD00*/ { if (fType!=kIsServer) { cout << "ERROR: MSQLServer::Query - this is not a server!" << endl; return NULL; } TSQLResult *res = fServ->Query(sql); if (!res) { cout << "ERROR: MSQLServer::Query - Query failed: " << sql << endl; return NULL; } return res; } Int_t MSQLServer::SelectDataBase(const char *dbname) /*FOLD00*/ { return fType==kIsServer ? fServ->SelectDataBase(dbname) : 0; } TSQLResult *MSQLServer::GetDataBases(const char *wild) /*FOLD00*/ { return fType==kIsServer ? fServ->GetDataBases(wild) : NULL; } TSQLResult *MSQLServer::GetTables(const char *dbname, const char *wild) /*FOLD00*/ { return fType==kIsServer ? fServ->GetTables(dbname, wild) : NULL; } TSQLResult *MSQLServer::GetColumns(const char *dbname, const char *table, const char *wild) /*FOLD00*/ { return fType==kIsServer ? fServ->GetColumns(dbname, table, wild) : NULL; } Int_t MSQLServer::CreateDataBase(const char *dbname) /*FOLD00*/ { return fType==kIsServer ? fServ->CreateDataBase(dbname) : 0; } Int_t MSQLServer::DropDataBase(const char *dbname) /*FOLD00*/ { return fType==kIsServer ? fServ->DropDataBase(dbname) : 0; } Int_t MSQLServer::Reload() /*FOLD00*/ { return fType==kIsServer ? fServ->Reload() : 0; } Int_t MSQLServer::Shutdown() /*FOLD00*/ { return fType==kIsServer ? fServ->Shutdown() : 0; } const char *MSQLServer::ServerInfo() /*FOLD00*/ { return fType==kIsServer ? fServ->ServerInfo() : ""; } Bool_t MSQLServer::IsConnected() const { return fType==kIsServer ? fServ->IsConnected() : kFALSE; } const char *MSQLServer::GetName() const { switch (fType) { case kIsServer: return Form("%s://%s:%d", fServ->GetDBMS(), fServ->GetHost(), fServ->GetPort()); case kIsDataBase: return GetNameDataBase(); case kIsTable: return GetNameTable(); case kIsColumn: return GetNameColumn(); default: return "n/a"; } } Bool_t MSQLServer::Split(TString &url, TString &user, TString &pasw) const { const Ssiz_t pos1 = url.First("://")+3; const Ssiz_t pos2 = url.Last(':') +1; const Ssiz_t pos3 = url.First('@'); if (pos1<0 || pos2<0 || pos3<0 || pos1>pos2 || pos2>pos3) return kFALSE; user = url(pos1, pos2-pos1-1); pasw = url(pos2, pos3-pos2); url.Remove(pos1, pos3+1-pos1); return kTRUE; } void MSQLServer::Init(const char *connection, const char *user, const char *password) /*FOLD00*/ { fType = kIsZombie; fServ = TSQLServer::Connect(connection, user, password); if (fServ) { gROOT->GetListOfBrowsables()->Add(this, connection); fType = kIsServer; } else SetBit(kZombie); fList.SetOwner(); } void MSQLServer::InitEnv(TEnv &env, const char *prefix) { TString url; TString user; TString pass; if (prefix) { url = env.GetValue(Form("%s.URL", prefix), ""); user = env.GetValue(Form("%s.User", prefix), ""); pass = env.GetValue(Form("%s.Password", prefix), ""); } if (url.IsNull()) url = env.GetValue("URL", ""); if (user.IsNull()) user = env.GetValue("User", ""); if (pass.IsNull()) pass = env.GetValue("Password", ""); if (user.IsNull() && pass.IsNull()) { if (!Split(url, user, pass)) { SetBit(kIsZombie); return; } } Init(url, user, pass); } MSQLServer::MSQLServer(const char *connection, const char *user, const char *password) /*FOLD00*/ { Init(connection, user, password); } MSQLServer::MSQLServer(const char *u) : fType(kIsZombie) /*FOLD00*/ { TString url(u); TString user, pasw; if (!Split(url, user, pasw)) { SetBit(kIsZombie); return; } Init(url, user, pasw); } MSQLServer::MSQLServer(TEnv &env, const char *prefix) { InitEnv(env, prefix); } MSQLServer::MSQLServer() { if (gEnv) InitEnv(*gEnv); } MSQLServer::~MSQLServer() /*FOLD00*/ { Close(); if (gDebug>0) cout << "Delete: " << GetName() << endl; } Bool_t MSQLServer::PrintError(const char *txt, const char *q) const /*FOLD00*/ { cout << "Fatal error acessing database: " << txt << endl; cout << "Query: " << q << endl; return kFALSE; } TString MSQLServer::GetEntry(const char *where, const char *col, const char *table) const /*FOLD00*/ { if (!fServ) return ""; if (table==0) table = Form("%s.%s", (const char *)fDataBase, (const char*)fTable); if (col==0) col = (const char *)fColumn; const TString query(Form("SELECT %s FROM %s WHERE %s", col, table, where)); TSQLResult *res = fServ->Query(query); if (!res) return (PrintError("GetEntry - TSQLResult==NULL", query), ""); if (res->GetFieldCount()!=1) { delete res; return (PrintError("GetEntry - Number of columns != 1", query), ""); } if (res->GetRowCount()>1) { delete res; return (PrintError("GetEntry - Number of rows > 1", query), ""); } if (res->GetRowCount()==0) { delete res; return ""; } const char *fld = res->Next()->GetField(0); if (!fld) { delete res; return (PrintError("GetEntry - Entry is empty", query), ""); } const TString rc(fld); delete res; return rc; }