source: trunk/Mars/msql/MTreeSQL.cc@ 16569

Last change on this file since 16569 was 15440, checked in by tbretz, 12 years ago
Support more than one MTreeSQL per database connection.
File size: 9.9 KB
Line 
1// @(#)root/tree:$Id: MTreeSQL.cxx 43270 2012-03-06 22:46:11Z pcanal $
2// Author: Philippe Canal and al. 08/2004
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12//////////////////////////////////////////////////////////////////////////
13// //
14// MTreeSQL //
15// //
16// Implement TTree for a SQL backend //
17// //
18//////////////////////////////////////////////////////////////////////////
19
20#include <Riostream.h>
21#include <map>
22#include <stdlib.h>
23
24#include "TString.h"
25#include "TROOT.h"
26#include "TSystem.h"
27#include "TError.h"
28#include "TFile.h"
29#include "TTree.h"
30#include "TLeaf.h"
31#include "TBranch.h"
32#include "TPRegexp.h"
33
34#include "TSQLRow.h"
35#include "TSQLResult.h"
36
37#include "MSQLServer.h"
38
39#include "MTreeSQL.h"
40#include "MBasketSQL.h"
41
42ClassImp(MTreeSQL);
43
44using namespace std;
45
46//______________________________________________________________________________
47MTreeSQL::MTreeSQL(MSQLServer *server, const TString& table, const TString &addon) :
48 TTree(table, addon, 0), fServer(server), fQuery(table+" "+addon), fResult(0), fRow(0)
49{
50 fEntries = 0;
51
52 if (fServer==0)
53 {
54 Error("MTreeSQL","No TSQLServer specified");
55 return;
56 }
57
58 fTables.push_back(table);
59
60 // Constructor with an explicit TSQLServer
61 TPRegexp reg(" +JOIN +([a-zA-Z0-9_.]+)");
62
63 Int_t p = -1;
64 while (p<addon.Length())
65 {
66 TArrayI pos;
67 if (reg.Match(addon, "ig", ++p, 100, &pos)!=2)
68 continue;
69
70 if (pos[2] >= 0 && pos[3] >= 0)
71 {
72 const TString subStr = addon(pos[2], pos[3]-pos[2]);
73 fTables.push_back(subStr);
74 }
75
76 p = pos[3];
77 }
78
79 for (auto it=fTables.begin(); it!=fTables.end(); it++)
80 if (!CheckTable(*it))
81 return;
82
83 Init();
84}
85
86MTreeSQL::~MTreeSQL()
87{
88 for (auto it=fRows.begin(); it!=fRows.end(); it++)
89 delete *it;
90
91 delete fResult;
92}
93
94//______________________________________________________________________________
95Bool_t MTreeSQL::CheckTable(const TString &table) const
96{
97 // Check the table exist in the database
98 if (fServer==0)
99 return kFALSE;
100
101 TSQLResult *tables = fServer->GetTables(table);
102 if (!tables)
103 return kFALSE;
104
105 TSQLRow * row = 0;
106 while ((row = tables->Next()))
107 {
108 if (table.CompareTo(row->GetField(0),TString::kIgnoreCase)==0)
109 return kTRUE;
110
111 delete row;
112 }
113 delete tables;
114
115 // The table is a not a permanent table, let's see if it is a 'temporary' table
116 const Int_t before = gErrorIgnoreLevel;
117 gErrorIgnoreLevel = kFatal;
118
119 TSQLResult *res = fServer->GetColumns(table);
120 if (res)
121 delete res;
122
123 gErrorIgnoreLevel = before;
124
125 return res ? kTRUE : kFALSE;
126}
127
128//______________________________________________________________________________
129void MTreeSQL::Init()
130{
131 // Initializeation routine
132 // Number of entries needed to create the branches
133 //GetEntries();
134
135 vector<pair<TString,TString>> cols;
136
137 for (auto it=fTables.begin(); it!=fTables.end(); it++)
138 {
139 TSQLResult *res = fServer->GetColumns(*it);
140
141 TSQLRow *row = 0;
142 while ((row=res->Next()))
143 {
144 TString f1 = row->GetField(1);
145
146 Int_t p0 = f1.First('(');
147 if (p0<0)
148 p0 = f1.First(' ');
149 if (p0<0)
150 p0 = f1.Length();
151
152 const TString type = f1(0, p0);
153
154 if (type.CompareTo("int", TString::kIgnoreCase) &&
155 type.CompareTo("date", TString::kIgnoreCase) &&
156 type.CompareTo("time", TString::kIgnoreCase) &&
157 type.CompareTo("datetime", TString::kIgnoreCase) &&
158 type.CompareTo("year", TString::kIgnoreCase) &&
159 type.CompareTo("timestamp", TString::kIgnoreCase) &&
160 type.CompareTo("bit", TString::kIgnoreCase) &&
161 type.CompareTo("tinyint", TString::kIgnoreCase) &&
162 type.CompareTo("smallint", TString::kIgnoreCase) &&
163 type.CompareTo("mediumint", TString::kIgnoreCase) &&
164 type.CompareTo("integer", TString::kIgnoreCase) &&
165 type.CompareTo("bigint", TString::kIgnoreCase) &&
166 type.CompareTo("decimal", TString::kIgnoreCase) &&
167 type.CompareTo("int", TString::kIgnoreCase) &&
168 type.CompareTo("real", TString::kIgnoreCase) &&
169 type.CompareTo("float", TString::kIgnoreCase) &&
170 type.CompareTo("double", TString::kIgnoreCase))
171 {
172 //cout << "Skip: " << type << endl;
173 continue;
174 }
175
176 const TString name = *it+"."+row->GetField(0);
177 cols.push_back(make_pair(name, type));
178
179 delete row;
180 }
181 delete res;
182 }
183
184 TString list;
185 for (auto it=cols.begin(); it!=cols.end(); it++)
186 list += ","+it->first;
187
188 list.Remove(0, 1);
189
190 fResult = fServer->Query(("SELECT "+list+" FROM "+fQuery).Data());
191 if (!fResult)
192 return;
193
194 TSQLRow *row = 0;
195 while ((row=(TSQLRow*)fResult->Next()))
196 fRows.push_back(row);
197
198 fEntries = fRows.size();
199
200 // ==============================================================
201
202 // determine leaf description string
203 Int_t idx = 0;
204 for (auto it=cols.begin(); it!=cols.end(); it++, idx++)
205 {
206 const TString name = it->first;
207
208 TBranch *br = TTree::Branch(name, 0, name+"/D");
209
210 br->ResetAddress();
211 br->SetEntries(fEntries);
212
213 auto entry = br->GetBasketEntry();
214 entry[0] = 0;
215 entry[1] = fEntries;
216
217 TBasket *bsk = new MBasketSQL(br, &fRow, idx, it->second);
218
219 br->GetListOfBaskets()->AddAtAndExpand(bsk, 0);
220 }
221}
222
223//______________________________________________________________________________
224Long64_t MTreeSQL::GetEntries() const
225{
226 // Get the number of rows in the database
227 return GetEntriesFast();
228}
229
230//______________________________________________________________________________
231Long64_t MTreeSQL::GetEntriesFast() const
232{
233 // Return the number of entries as of the last check.
234 // Use GetEntries for a more accurate count.
235
236 return fEntries;
237}
238
239//______________________________________________________________________________
240Long64_t MTreeSQL::LoadTree(Long64_t entry)
241{
242 // Setup the tree to the load the specified entry.
243 // Make sure the server and result set are setup for the requested entry
244 if (entry<0 || entry>=fEntries)
245 return -1;
246
247 fReadEntry = entry;
248 fRow = fRows[entry];
249
250 return entry;
251}
252
253//______________________________________________________________________________
254void MTreeSQL::Refresh()
255{
256 if (!fServer)
257 return;
258
259 // Refresh contents of this Tree and his branches from the current
260 // Tree status in the database
261 // One can call this function in case the Tree on its file is being
262 // updated by another process
263 for (auto it=fRows.begin(); it!=fRows.end(); it++)
264 delete *it;
265
266 fRows.clear();
267
268 delete fResult;
269
270 Init();
271}
272
273//______________________________________________________________________________
274TBranch* MTreeSQL::BranchImp(const char *, const char *,
275 TClass *, void *, Int_t ,
276 Int_t )
277{
278 // Not implemented yet
279
280 Fatal("BranchImp","Not implemented yet");
281 return 0;
282}
283
284//______________________________________________________________________________
285TBranch* MTreeSQL::BranchImp(const char *, TClass *,
286 void *, Int_t , Int_t )
287{
288 // Not implemented yet
289
290 Fatal("BranchImp","Not implemented yet");
291 return 0;
292}
293
294//______________________________________________________________________________
295Int_t MTreeSQL::Branch(TCollection *, Int_t,
296 Int_t, const char *)
297{
298 // Not implemented yet
299
300 Fatal("Branch","Not implemented yet");
301 return 0;
302}
303
304//______________________________________________________________________________
305Int_t MTreeSQL::Branch(TList *, Int_t, Int_t)
306{
307 // Not implemented yet
308
309 Fatal("Branch","Not implemented yet");
310 return 0;
311}
312
313//______________________________________________________________________________
314Int_t MTreeSQL::Branch(const char *, Int_t ,
315 Int_t)
316{
317 // Not implemented yet
318
319 Fatal("Branch","Not implemented yet");
320 return 0;
321}
322
323//______________________________________________________________________________
324TBranch* MTreeSQL::Bronch(const char *, const char *, void *,
325 Int_t, Int_t)
326{
327 // Not implemented yet
328
329 Fatal("Bronc","Not implemented yet");
330 return 0;
331}
332
333//______________________________________________________________________________
334TBranch* MTreeSQL::BranchOld(const char *, const char *,
335 void *, Int_t, Int_t)
336{
337 // Not implemented yet
338
339 Fatal("BranchOld","Not implemented yet");
340 return 0;
341}
342
343//______________________________________________________________________________
344TBranch *MTreeSQL::Branch(const char *, const char *, void *,
345 Int_t, Int_t)
346{
347 // Not implemented yet
348
349 Fatal("Branch","Not implemented yet");
350 return 0;
351}
352
353//______________________________________________________________________________
354Int_t MTreeSQL::Fill()
355{
356 Fatal("Fill","Not implemented yet");
357 return -1;
358}
Note: See TracBrowser for help on using the repository browser.