source: trunk/MagicSoft/Mars/msql/MSQLServer.cc@ 4743

Last change on this file since 4743 was 4694, checked in by tbretz, 20 years ago
*** empty log message ***
File size: 14.0 KB
Line 
1/* ======================================================================== *\
2!
3! *
4! * This file is part of MARS, the MAGIC Analysis and Reconstruction
5! * Software. It is distributed to you in the hope that it can be a useful
6! * and timesaving tool in analysing Data of imaging Cerenkov telescopes.
7! * It is distributed WITHOUT ANY WARRANTY.
8! *
9! * Permission to use, copy, modify and distribute this software and its
10! * documentation for any purpose is hereby granted without fee,
11! * provided that the above copyright notice appear in all copies and
12! * that both that copyright notice and this permission notice appear
13! * in supporting documentation. It is provided "as is" without express
14! * or implied warranty.
15! *
16!
17!
18! Author(s): Thomas Bretz 2/2004 <mailto:tbretz@astro.uni-wuerzburg.de>
19!
20! Copyright: MAGIC Software Development, 2000-2004
21!
22!
23\* ======================================================================== */
24
25////////////////////////////////////////////////////////////////////////
26//
27// MSQLServer
28//
29// Using this instead of a TSQLServer gives the possibility to
30// browse a database server through the TBrowser and it will offer
31// many features usefull working with relational tables.
32//
33// Use it like TSQlServer:
34// new MSQLServer("mysql://localhost:3306", "hercules", "stdmagicpassword");
35// // now start your TBrowser
36// new TBrowser;
37//
38////////////////////////////////////////////////////////////////////////
39#include "MSQLServer.h"
40
41#include <iostream>
42#include <iomanip>
43#include <stdlib.h>
44
45#include <TROOT.h>
46
47#include <TH1.h>
48
49#include <TSQLResult.h>
50#include <TSQLServer.h>
51#include <TSQLRow.h>
52
53#include <TBrowser.h>
54
55ClassImp(MSQLServer);
56
57using namespace std;
58
59// --------------------------------------------------------------------------
60//
61// Used in virtual function TObject::Browse() to create the
62//
63void MSQLServer::BrowseColumn(TBrowser *b) /*FOLD00*/
64{
65 const TString query0(Form("EXPLAIN %s.%s %s", (const char*)fDataBase, (const char*)fTable, (const char*)fColumn));
66 const TString query1(Form("SELECT %s FROM %s.%s", (const char*)fColumn, (const char*)fDataBase, (const char*)fTable));
67
68 //cout << query0 << endl;
69 TSQLResult *res = fServ->Query(query0);
70 if (!res)
71 {
72 cout << "query - failed: " << query0 << endl;
73 return;
74 }
75
76 TSQLRow *row=res->Next();
77 const TString desc((*row)[1]);
78
79 delete res;
80
81 const Bool_t isnum =
82 !desc.Contains("char", TString::kIgnoreCase) &&
83 !desc.Contains("text", TString::kIgnoreCase);
84
85 cout << query1 << endl;
86 res = fServ->Query(query1);
87 if (!res)
88 {
89 cout << "query - failed: " << query1 << endl;
90 return;
91 }
92
93 TArrayD arr(2);
94 Int_t num=0;
95 Double_t max=0;
96 Double_t min=0;
97 Double_t sum=0;
98 Double_t sqr=0;
99
100 while ((row=res->Next()))
101 {
102 const TString row0((*row)[0]);
103
104 if (!isnum)
105 {
106 cout << row0 << endl;
107 continue;
108 }
109
110 if (num==arr.GetSize())
111 arr.Set(arr.GetSize()*2);
112
113 arr[num] = atof(row0.Data());
114
115 if (num==0)
116 min=max=arr[0];
117
118 if (arr[num]>max) max = arr[num];
119 if (arr[num]<min) min = arr[num];
120
121 sum += arr[num];
122 sqr += arr[num]*arr[num];
123
124 num++;
125 }
126
127 delete res;
128
129 if (!isnum)
130 return;
131
132 if (max==min) max += 1;
133
134 Int_t num0 = 1;
135
136 if (num>0)
137 {
138 /*
139 cout << "Num: " << num << endl;
140 cout << "Mean: " << sum/num << endl;
141 cout << "Range: " << max-min << endl;
142 cout << "RMS: " << TMath::Sqrt(sqr/num-sum*sum/num/num) << endl;
143 */
144
145 num0 = (Int_t)((max-min)*40/TMath::Sqrt(sqr/num-sum*sum/num/num));
146 }
147
148 const TString title(Form("#splitline{%s}{<%s>}", (const char*)query1, (const char*)desc));
149
150 TH1F *hist=new TH1F(fColumn, title, num0, min, max);
151 for (int i=0; i<num; i++)
152 hist->Fill(arr[i]);
153
154 //cout << "Done." << endl;
155
156 hist->Draw();
157 hist->SetBit(kCanDelete);
158}
159
160void MSQLServer::BrowseTable(TBrowser *b) /*FOLD00*/
161{
162 TSQLResult *res = fServ->GetColumns(fDataBase, fTable);
163 if (!res)
164 return;
165
166 TSQLRow *row;
167 while ((row=res->Next()))
168 {
169 TString row0((*row)[0]);
170
171 MSQLServer *sql = (MSQLServer*)fList.FindObject(Form("%s/%s/%s", (const char*)fDataBase, (const char*)fTable, (const char*)row0));
172 if (!sql)
173 {
174 sql = new MSQLColumn(fServ, fDataBase, fTable, row0);
175 fList.Add(sql);
176 }
177 b->Add(sql, row0);
178 }
179}
180
181void MSQLServer::BrowseDataBase(TBrowser *b) /*FOLD00*/
182{
183 TSQLResult *res = fServ->GetTables(fDataBase);
184 if (!res)
185 return;
186
187 TSQLRow *row;
188 while ((row=res->Next()))
189 {
190 TString row0((*row)[0]);
191
192 MSQLServer *sql = (MSQLServer*)fList.FindObject(Form("%s/%s", (const char*)fDataBase, (const char*)row0));
193 if (!sql)
194 {
195 sql = new MSQLServer(fServ, fDataBase, row0);
196 fList.Add(sql);
197 }
198 b->Add(sql, row0);
199 }
200}
201
202void MSQLServer::BrowseServer(TBrowser *b) /*FOLD00*/
203{
204 TSQLResult *res = fServ->GetDataBases();
205 if (!res)
206 return;
207
208 TSQLRow *row;
209 while ((row=res->Next()))
210 {
211 const TString row0((*row)[0]);
212
213 MSQLServer *sql = (MSQLServer*)fList.FindObject(row0);
214 if (!sql)
215 {
216 sql = new MSQLServer(fServ, row0);
217 fList.Add(sql);
218 }
219 b->Add(sql, row0);
220 }
221}
222
223void MSQLServer::PrintLine(const TArrayI &max) /*FOLD00*/
224{
225 cout << "+" << setfill('-');
226 for (int i=0; i<max.GetSize(); i++)
227 cout << setw(max[i]+1) << "-" << "-+";
228 cout << endl;
229}
230
231void MSQLServer::PrintTable(TSQLResult &res) /*FOLD00*/
232{
233 Int_t n = res.GetFieldCount();
234
235 TArrayI max(n);
236
237 for (int i=0; i<n; i++)
238 max[i] = strlen(res.GetFieldName(i));
239
240 TSQLRow *row;
241
242 TList rows;
243 while ((row=res.Next()))
244 {
245 for (int i=0; i<n; i++)
246 max[i] = TMath::Max((ULong_t)max[i], row->GetFieldLength(i));
247 rows.Add(row);
248 }
249
250 cout << endl;
251
252 PrintLine(max);
253
254 cout << "|" << setfill(' ');
255 for (int i=0; i<n; i++)
256 cout << setw(max[i]+1) << res.GetFieldName(i) << " |";
257 cout << endl;
258
259 PrintLine(max);
260
261 cout << setfill(' ');
262 TIter Next(&rows);
263 while ((row=(TSQLRow*)Next()))
264 {
265 cout << "|";
266 for (int i=0; i<n; i++)
267 {
268 const char *c = (*row)[i];
269 cout << setw(max[i]+1) << (c?c:"") << " |";
270 }
271 cout << endl;
272 }
273
274 PrintLine(max);
275}
276
277TString MSQLServer::GetFields() const /*FOLD00*/
278{
279 TSQLResult *res = fServ->GetColumns(fDataBase, fTable);
280 if (!res)
281 return "";
282
283 TString fields;
284
285 TSQLRow *row;
286
287 TList rows;
288 while ((row=res->Next()))
289 rows.Add(row);
290
291 TIter Next(&rows);
292 while ((row=(TSQLRow*)Next()))
293 {
294 fields += (*row)[0];
295 if (row!=rows.Last())
296 fields += ", ";
297 }
298
299 return fields;
300}
301
302void MSQLServer::PrintQuery(const char *query) const /*FOLD00*/
303{
304 TSQLResult *res = fServ->Query(query);
305 if (res)
306 {
307 PrintTable(*res);
308 delete res;
309 }
310 else
311 cout << "Query failed: " << query << endl;
312}
313
314void MSQLServer::Print(Option_t *o) const /*FOLD00*/
315{
316 switch (fType)
317 {
318 case kIsServer:
319 PrintQuery("SHOW DATABASES");
320 break;
321
322 case kIsDataBase:
323 PrintQuery(Form("SHOW TABLES FROM %s", (const char*)fDataBase));
324 break;
325
326 case kIsTable:
327 PrintQuery(Form("SELECT * FROM %s.%s", (const char*)fDataBase, (const char*)fTable));
328 break;
329
330 case kIsColumn:
331 PrintQuery(Form("SELECT %s FROM %s.%s", (const char*)fColumn, (const char*)fDataBase, (const char*)fTable));
332 break;
333
334 default:
335 break;
336 }
337}
338
339void MSQLServer::ShowColumns() const /*FOLD00*/
340{
341 switch (fType)
342 {
343 case kIsTable:
344 PrintQuery(Form("SHOW FULl COLUMNS FROM %s.%s", (const char*)fDataBase, (const char*)fTable));
345 break;
346
347 case kIsColumn:
348 PrintQuery(Form("SHOW FULl COLUMNS FROM %s.%s LIKE %s", (const char*)fDataBase, (const char*)fTable, (const char*)fColumn));
349 break;
350
351 default:
352 //Print();
353 break;
354 }
355}
356
357void MSQLServer::ShowStatus() const /*FOLD00*/
358{
359 switch (fType)
360 {
361 case kIsServer:
362 PrintQuery("SHOW STATUS");
363 break;
364
365 case kIsDataBase:
366 PrintQuery(Form("SHOW TABLE STATUS FROM %s", (const char*)fDataBase));
367 break;
368
369 case kIsTable:
370 PrintQuery(Form("SHOW TABLE STATUS FROM %s LIKE %s", (const char*)fDataBase, (const char*)fTable));
371 break;
372
373 default:
374 break;
375 }
376}
377
378void MSQLServer::ShowTableIndex() const /*FOLD00*/
379{
380 switch (fType)
381 {
382 case kIsTable:
383 case kIsColumn:
384 PrintQuery(Form("SHOW INDEX FROM %s.%s", (const char*)fDataBase, (const char*)fTable));
385 break;
386
387 default:
388 break;
389 }
390}
391
392void MSQLServer::ShowTableCreate() const /*FOLD00*/
393{
394 switch (fType)
395 {
396 case kIsTable:
397 case kIsColumn:
398 PrintQuery(Form("SHOW CREATE TABLE %s.%s", (const char*)fDataBase, (const char*)fTable));
399 break;
400
401 default:
402 break;
403 }
404}
405
406void MSQLServer::Close(Option_t *option) /*FOLD00*/
407{
408 if (fType==kIsServer)
409 fServ->Close(option);
410}
411
412// --------------------------------------------------------------------------
413//
414// Send a SQL query to the SQl server.
415//
416// If MSQLServer is no server (column, row, ...) NULL is returned and an
417// error message is send to stdout.
418//
419// If the query failed for some reason an error message is send to stdout
420// and NULL is returned.
421//
422// If everything works fine a TSQLResult is returned. Make sure that you
423// delete it!
424//
425TSQLResult *MSQLServer::Query(const char *sql) /*FOLD00*/
426{
427 if (fType!=kIsServer)
428 {
429 cout << "ERROR: MSQLServer::Query - this is not a server!" << endl;
430 return NULL;
431 }
432
433 TSQLResult *res = fServ->Query(sql);
434 if (!res)
435 {
436 cout << "ERROR: MSQLServer::Query - Query failed: " << sql << endl;
437 return NULL;
438 }
439
440 return res;
441}
442
443Int_t MSQLServer::SelectDataBase(const char *dbname) /*FOLD00*/
444{
445 return fType==kIsServer ? fServ->SelectDataBase(dbname) : 0;
446}
447
448TSQLResult *MSQLServer::GetDataBases(const char *wild) /*FOLD00*/
449{
450 return fType==kIsServer ? fServ->GetDataBases(wild) : NULL;
451}
452
453TSQLResult *MSQLServer::GetTables(const char *dbname, const char *wild) /*FOLD00*/
454{
455 return fType==kIsServer ? fServ->GetTables(dbname, wild) : NULL;
456}
457
458TSQLResult *MSQLServer::GetColumns(const char *dbname, const char *table, const char *wild) /*FOLD00*/
459{
460 return fType==kIsServer ? fServ->GetColumns(dbname, table, wild) : NULL;
461}
462
463Int_t MSQLServer::CreateDataBase(const char *dbname) /*FOLD00*/
464{
465 return fType==kIsServer ? fServ->CreateDataBase(dbname) : 0;
466}
467
468Int_t MSQLServer::DropDataBase(const char *dbname) /*FOLD00*/
469{
470 return fType==kIsServer ? fServ->DropDataBase(dbname) : 0;
471}
472
473Int_t MSQLServer::Reload() /*FOLD00*/
474{
475 return fType==kIsServer ? fServ->Reload() : 0;
476}
477
478Int_t MSQLServer::Shutdown() /*FOLD00*/
479{
480 return fType==kIsServer ? fServ->Shutdown() : 0;
481}
482
483const char *MSQLServer::ServerInfo() /*FOLD00*/
484{
485 return fType==kIsServer ? fServ->ServerInfo() : "";
486}
487
488Bool_t MSQLServer::IsConnected() const
489{
490 return fType==kIsServer ? fServ->IsConnected() : kFALSE;
491}
492
493const char *MSQLServer::GetName() const
494{
495 switch (fType)
496 {
497 case kIsServer: return Form("%s://%s:%d", fServ->GetDBMS(), fServ->GetHost(), fServ->GetPort());
498 case kIsDataBase: return GetNameDataBase();
499 case kIsTable: return GetNameTable();
500 case kIsColumn: return GetNameColumn();
501 default: return "n/a";
502 }
503}
504
505void MSQLServer::Init(const char *connection, const char *user, const char *password) /*FOLD00*/
506{
507 fType = kIsZombie;
508
509 fServ = TSQLServer::Connect(connection, user, password);
510 if (fServ)
511 {
512 gROOT->GetListOfBrowsables()->Add(this, connection);
513 fType = kIsServer;
514 }
515 else
516 SetBit(kZombie);
517
518 fList.SetOwner();
519}
520
521MSQLServer::MSQLServer(const char *connection, const char *user, const char *password) /*FOLD00*/
522{
523 Init(connection, user, password);
524}
525
526MSQLServer::MSQLServer(const char *u) : fType(kIsZombie) /*FOLD00*/
527{
528 TString url(u);
529
530 const Ssiz_t pos1 = url.First("://")+3;
531 const Ssiz_t pos2 = url.Last(':') +1;
532 const Ssiz_t pos3 = url.First('@');
533
534 if (pos1<0 || pos2<0 || pos3<0 || pos1>pos2 || pos2>pos3)
535 {
536 SetBit(kZombie);
537 return;
538 }
539
540 const TString user = url(pos1, pos2-pos1-1);
541 const TString pasw = url(pos2, pos3-pos2);
542
543 url.Remove(pos1, pos3+1-pos1);
544
545 Init(url, user, pasw);
546}
547
548MSQLServer::~MSQLServer() /*FOLD00*/
549{
550 Close();
551 if (gDebug>0)
552 cout << "Delete: " << GetName() << endl;
553}
554
555Bool_t MSQLServer::PrintError(const char *txt, const char *q) const /*FOLD00*/
556{
557 cout << "Fatal error acessing database: " << txt << endl;
558 cout << "Query: " << q << endl;
559 return kFALSE;
560}
561
562TString MSQLServer::GetEntry(const char *where, const char *col, const char *table) const /*FOLD00*/
563{
564 if (!fServ)
565 return "";
566
567 if (table==0)
568 table = Form("%s.%s", (const char *)fDataBase, (const char*)fTable);
569 if (col==0)
570 col = (const char *)fColumn;
571
572 const TString query(Form("SELECT %s FROM %s WHERE %s", col, table, where));
573
574 TSQLResult *res = fServ->Query(query);
575 if (!res)
576 return (PrintError("GetEntry - TSQLResult==NULL", query), "");
577
578 if (res->GetFieldCount()!=1)
579 {
580 delete res;
581 return (PrintError("GetEntry - Number of columns != 1", query), "");
582 }
583
584 if (res->GetRowCount()>1)
585 {
586 delete res;
587 return (PrintError("GetEntry - Number of rows > 1", query), "");
588 }
589
590 if (res->GetRowCount()==0)
591 {
592 delete res;
593 return "";
594 }
595
596 const char *fld = res->Next()->GetField(0);
597 if (!fld)
598 {
599 delete res;
600 return (PrintError("GetEntry - Entry is empty", query), "");
601 }
602
603 const TString rc(fld);
604 delete res;
605 return rc;
606}
Note: See TracBrowser for help on using the repository browser.