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

Last change on this file since 17978 was 17064, checked in by tbretz, 11 years ago
Added some additional output to help understanding what goes wrong with a database request.
File size: 10.0 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 if (!res)
126 Error("CheckTable", "%s", ("Table "+table+" not found.").Data());
127
128 return res ? kTRUE : kFALSE;
129}
130
131//______________________________________________________________________________
132void MTreeSQL::Init()
133{
134 // Initializeation routine
135 // Number of entries needed to create the branches
136 //GetEntries();
137
138 vector<pair<TString,TString>> cols;
139
140 for (auto it=fTables.begin(); it!=fTables.end(); it++)
141 {
142 TSQLResult *res = fServer->GetColumns(*it);
143
144 TSQLRow *row = 0;
145 while ((row=res->Next()))
146 {
147 TString f1 = row->GetField(1);
148
149 Int_t p0 = f1.First('(');
150 if (p0<0)
151 p0 = f1.First(' ');
152 if (p0<0)
153 p0 = f1.Length();
154
155 const TString type = f1(0, p0);
156
157 if (type.CompareTo("int", TString::kIgnoreCase) &&
158 type.CompareTo("date", TString::kIgnoreCase) &&
159 type.CompareTo("time", TString::kIgnoreCase) &&
160 type.CompareTo("datetime", TString::kIgnoreCase) &&
161 type.CompareTo("year", TString::kIgnoreCase) &&
162 type.CompareTo("timestamp", TString::kIgnoreCase) &&
163 type.CompareTo("bit", TString::kIgnoreCase) &&
164 type.CompareTo("tinyint", TString::kIgnoreCase) &&
165 type.CompareTo("smallint", TString::kIgnoreCase) &&
166 type.CompareTo("mediumint", TString::kIgnoreCase) &&
167 type.CompareTo("integer", TString::kIgnoreCase) &&
168 type.CompareTo("bigint", TString::kIgnoreCase) &&
169 type.CompareTo("decimal", TString::kIgnoreCase) &&
170 type.CompareTo("int", TString::kIgnoreCase) &&
171 type.CompareTo("real", TString::kIgnoreCase) &&
172 type.CompareTo("float", TString::kIgnoreCase) &&
173 type.CompareTo("double", TString::kIgnoreCase))
174 {
175 Info("Init", "%s", ("Skipping "+*it+"."+TString(row->GetField(0))+" ["+type+"]").Data());
176 continue;
177 }
178
179 const TString name = *it+"."+row->GetField(0);
180 cols.push_back(make_pair(name, type));
181
182 delete row;
183 }
184 delete res;
185 }
186
187 TString list;
188 for (auto it=cols.begin(); it!=cols.end(); it++)
189 list += ","+it->first;
190
191 list.Remove(0, 1);
192
193 fResult = fServer->Query(("SELECT "+list+" FROM "+fQuery).Data());
194 if (!fResult)
195 return;
196
197 TSQLRow *row = 0;
198 while ((row=(TSQLRow*)fResult->Next()))
199 fRows.push_back(row);
200
201 fEntries = fRows.size();
202
203 // ==============================================================
204
205 // determine leaf description string
206 Int_t idx = 0;
207 for (auto it=cols.begin(); it!=cols.end(); it++, idx++)
208 {
209 const TString name = it->first;
210
211 TBranch *br = TTree::Branch(name, 0, name+"/D");
212
213 br->ResetAddress();
214 br->SetEntries(fEntries);
215
216 auto entry = br->GetBasketEntry();
217 entry[0] = 0;
218 entry[1] = fEntries;
219
220 TBasket *bsk = new MBasketSQL(br, &fRow, idx, it->second);
221
222 br->GetListOfBaskets()->AddAtAndExpand(bsk, 0);
223 }
224}
225
226//______________________________________________________________________________
227Long64_t MTreeSQL::GetEntries() const
228{
229 // Get the number of rows in the database
230 return GetEntriesFast();
231}
232
233//______________________________________________________________________________
234Long64_t MTreeSQL::GetEntriesFast() const
235{
236 // Return the number of entries as of the last check.
237 // Use GetEntries for a more accurate count.
238
239 return fEntries;
240}
241
242//______________________________________________________________________________
243Long64_t MTreeSQL::LoadTree(Long64_t entry)
244{
245 // Setup the tree to the load the specified entry.
246 // Make sure the server and result set are setup for the requested entry
247 if (entry<0 || entry>=fEntries)
248 return -1;
249
250 fReadEntry = entry;
251 fRow = fRows[entry];
252
253 return entry;
254}
255
256//______________________________________________________________________________
257void MTreeSQL::Refresh()
258{
259 if (!fServer)
260 return;
261
262 // Refresh contents of this Tree and his branches from the current
263 // Tree status in the database
264 // One can call this function in case the Tree on its file is being
265 // updated by another process
266 for (auto it=fRows.begin(); it!=fRows.end(); it++)
267 delete *it;
268
269 fRows.clear();
270
271 delete fResult;
272
273 Init();
274}
275
276//______________________________________________________________________________
277TBranch* MTreeSQL::BranchImp(const char *, const char *,
278 TClass *, void *, Int_t ,
279 Int_t )
280{
281 // Not implemented yet
282
283 Fatal("BranchImp","Not implemented yet");
284 return 0;
285}
286
287//______________________________________________________________________________
288TBranch* MTreeSQL::BranchImp(const char *, TClass *,
289 void *, Int_t , Int_t )
290{
291 // Not implemented yet
292
293 Fatal("BranchImp","Not implemented yet");
294 return 0;
295}
296
297//______________________________________________________________________________
298Int_t MTreeSQL::Branch(TCollection *, Int_t,
299 Int_t, const char *)
300{
301 // Not implemented yet
302
303 Fatal("Branch","Not implemented yet");
304 return 0;
305}
306
307//______________________________________________________________________________
308Int_t MTreeSQL::Branch(TList *, Int_t, Int_t)
309{
310 // Not implemented yet
311
312 Fatal("Branch","Not implemented yet");
313 return 0;
314}
315
316//______________________________________________________________________________
317Int_t MTreeSQL::Branch(const char *, Int_t ,
318 Int_t)
319{
320 // Not implemented yet
321
322 Fatal("Branch","Not implemented yet");
323 return 0;
324}
325
326//______________________________________________________________________________
327TBranch* MTreeSQL::Bronch(const char *, const char *, void *,
328 Int_t, Int_t)
329{
330 // Not implemented yet
331
332 Fatal("Bronc","Not implemented yet");
333 return 0;
334}
335
336//______________________________________________________________________________
337TBranch* MTreeSQL::BranchOld(const char *, const char *,
338 void *, Int_t, Int_t)
339{
340 // Not implemented yet
341
342 Fatal("BranchOld","Not implemented yet");
343 return 0;
344}
345
346//______________________________________________________________________________
347TBranch *MTreeSQL::Branch(const char *, const char *, void *,
348 Int_t, Int_t)
349{
350 // Not implemented yet
351
352 Fatal("Branch","Not implemented yet");
353 return 0;
354}
355
356//______________________________________________________________________________
357Int_t MTreeSQL::Fill()
358{
359 Fatal("Fill","Not implemented yet");
360 return -1;
361}
Note: See TracBrowser for help on using the repository browser.