Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TSQLObjectData.cxx
Go to the documentation of this file.
1 // @(#)root/sql:$Id$
2 // Author: Sergey Linev 20/11/2005
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2005, 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 \class TSQLObjectData
14 \ingroup IO
15 
16 TSQLObjectData is used in TBufferSQL2 class in reading procedure.
17 It contains data, request from database table for one specific
18 object for one specific class. For instance, when data for
19 class TH1 required, requests will be done to
20 TH1_ver4 and TH1_raw4 tables and result of these requests
21 will be kept in single TSQLObjectData instance.
22 */
23 
24 #include "TSQLObjectData.h"
25 
26 #include "TObjArray.h"
27 #include "TNamed.h"
28 #include "TList.h"
29 #include "TSQLRow.h"
30 #include "TSQLResult.h"
31 #include "TSQLClassInfo.h"
32 #include "TSQLStructure.h"
33 #include "TSQLStatement.h"
34 
35 /**
36 \class TSQLObjectInfo
37 \ingroup IO
38 Info (classname, version) about object in database
39 */
40 
41 ClassImp(TSQLObjectInfo);
42 
43 ////////////////////////////////////////////////////////////////////////////////
44 
45 TSQLObjectInfo::TSQLObjectInfo() : TObject(), fObjId(0), fClassName(), fVersion(0)
46 {
47 }
48 
49 ////////////////////////////////////////////////////////////////////////////////
50 
51 TSQLObjectInfo::TSQLObjectInfo(Long64_t objid, const char *classname, Version_t version)
52  : TObject(), fObjId(objid), fClassName(classname), fVersion(version)
53 {
54 }
55 
56 ////////////////////////////////////////////////////////////////////////////////
57 
58 TSQLObjectInfo::~TSQLObjectInfo()
59 {
60 }
61 
62 /**
63 \class TSQLObjectData
64 \ingroup IO
65 Keeps the data requested from the SQL server for an object.
66 */
67 
68 ClassImp(TSQLObjectData);
69 
70 ////////////////////////////////////////////////////////////////////////////////
71 /// default contrsuctor
72 
73 TSQLObjectData::TSQLObjectData()
74  : TObject(), fInfo(0), fObjId(0), fOwner(kFALSE), fClassData(0), fBlobData(0), fBlobStmt(0), fLocatedColumn(-1),
75  fClassRow(0), fBlobRow(0), fLocatedField(0), fLocatedValue(0), fCurrentBlob(kFALSE), fBlobPrefixName(0),
76  fBlobTypeName(0), fUnpack(0)
77 {
78 }
79 
80 ////////////////////////////////////////////////////////////////////////////////
81 /// normal contrsuctor,
82 
83 TSQLObjectData::TSQLObjectData(TSQLClassInfo *sqlinfo, Long64_t objid, TSQLResult *classdata, TSQLRow *classrow,
84  TSQLResult *blobdata, TSQLStatement *blobstmt)
85  : TObject(), fInfo(sqlinfo), fObjId(objid), fOwner(kFALSE), fClassData(classdata), fBlobData(blobdata),
86  fBlobStmt(blobstmt), fLocatedColumn(-1), fClassRow(classrow), fBlobRow(0), fLocatedField(0), fLocatedValue(0),
87  fCurrentBlob(kFALSE), fBlobPrefixName(0), fBlobTypeName(0), fUnpack(0)
88 {
89  // take ownership if no special row from data pool is provided
90  if ((fClassData != 0) && (fClassRow == 0)) {
91  fOwner = kTRUE;
92  fClassRow = fClassData->Next();
93  }
94 
95  ShiftBlobRow();
96 }
97 
98 ////////////////////////////////////////////////////////////////////////////////
99 /// destructor of TSQLObjectData object
100 
101 TSQLObjectData::~TSQLObjectData()
102 {
103  if ((fClassData != 0) && fOwner)
104  delete fClassData;
105  if (fClassRow != 0)
106  delete fClassRow;
107  if (fBlobRow != 0)
108  delete fBlobRow;
109  if (fBlobData != 0)
110  delete fBlobData;
111  if (fUnpack != 0) {
112  fUnpack->Delete();
113  delete fUnpack;
114  }
115  if (fBlobStmt != 0)
116  delete fBlobStmt;
117 }
118 
119 ////////////////////////////////////////////////////////////////////////////////
120 /// return number of columns in class table result
121 
122 Int_t TSQLObjectData::GetNumClassFields()
123 {
124  if (fClassData != 0)
125  return fClassData->GetFieldCount();
126  return 0;
127 }
128 
129 ////////////////////////////////////////////////////////////////////////////////
130 /// get name of class table column
131 
132 const char *TSQLObjectData::GetClassFieldName(Int_t n)
133 {
134  if (fClassData != 0)
135  return fClassData->GetFieldName(n);
136  return 0;
137 }
138 
139 ////////////////////////////////////////////////////////////////////////////////
140 /// locate column of that name in results
141 
142 Bool_t TSQLObjectData::LocateColumn(const char *colname, Bool_t isblob)
143 {
144  if (fUnpack != 0) {
145  fUnpack->Delete();
146  delete fUnpack;
147  fUnpack = 0;
148  }
149 
150  fLocatedField = 0;
151  fLocatedValue = 0;
152  fCurrentBlob = kFALSE;
153 
154  if ((fClassData == 0) || (fClassRow == 0))
155  return kFALSE;
156 
157  // Int_t numfields = GetNumClassFields();
158 
159  Int_t ncol = fInfo->FindColumn(colname, kFALSE);
160  if (ncol > 0) {
161  fLocatedColumn = ncol;
162  fLocatedField = GetClassFieldName(ncol);
163  fLocatedValue = fClassRow->GetField(ncol);
164  }
165 
166  /* for (Int_t ncol=1;ncol<numfields;ncol++) {
167  const char* fieldname = GetClassFieldName(ncol);
168  if (strcmp(colname, fieldname)==0) {
169  fLocatedColumn = ncol;
170  fLocatedField = fieldname;
171  fLocatedValue = fClassRow->GetField(ncol);
172  break;
173  }
174  }
175  */
176 
177  if (fLocatedField == 0)
178  return kFALSE;
179 
180  if (!isblob)
181  return kTRUE;
182 
183  if ((fBlobRow == 0) && (fBlobStmt == 0))
184  return kFALSE;
185 
186  fCurrentBlob = kTRUE;
187 
188  ExtractBlobValues();
189 
190  return kTRUE;
191 }
192 
193 ////////////////////////////////////////////////////////////////////////////////
194 /// shift cursor to next blob value
195 
196 Bool_t TSQLObjectData::ShiftBlobRow()
197 {
198  if (fBlobStmt != 0) {
199  Bool_t res = fBlobStmt->NextResultRow();
200  if (!res) {
201  delete fBlobStmt;
202  fBlobStmt = 0;
203  }
204  return res;
205  }
206 
207  delete fBlobRow;
208  fBlobRow = fBlobData ? fBlobData->Next() : 0;
209  return fBlobRow != 0;
210 }
211 
212 ////////////////////////////////////////////////////////////////////////////////
213 /// extract from curent blob row value and names identifiers
214 
215 Bool_t TSQLObjectData::ExtractBlobValues()
216 {
217  const char *name = 0;
218 
219  Bool_t hasdata = kFALSE;
220 
221  if (fBlobStmt != 0) {
222  name = fBlobStmt->GetString(0);
223  fLocatedValue = fBlobStmt->GetString(1);
224  hasdata = kTRUE;
225  }
226 
227  if (!hasdata) {
228  if (fBlobRow != 0) {
229  fLocatedValue = fBlobRow->GetField(1);
230  name = fBlobRow->GetField(0);
231  }
232  }
233 
234  if (name == 0) {
235  fBlobPrefixName = 0;
236  fBlobTypeName = 0;
237  return kFALSE;
238  }
239 
240  const char *separ = strstr(name, ":"); // SQLNameSeparator()
241 
242  if (separ == 0) {
243  fBlobPrefixName = 0;
244  fBlobTypeName = name;
245  } else {
246  fBlobPrefixName = name;
247  separ += strlen(":"); // SQLNameSeparator()
248  fBlobTypeName = separ;
249  }
250 
251  // if (gDebug>4)
252  // Info("ExtractBlobValues","Prefix:%s Type:%s",
253  // (fBlobPrefixName ? fBlobPrefixName : "null"),
254  // (fBlobTypeName ? fBlobTypeName : "null"));
255 
256  return kTRUE;
257 }
258 
259 ////////////////////////////////////////////////////////////////////////////////
260 /// add emulated data
261 /// this used to place version or TObject raw data, read from normal tables
262 
263 void TSQLObjectData::AddUnpack(const char *tname, const char *value)
264 {
265  TNamed *str = new TNamed(tname, value);
266  if (fUnpack == 0) {
267  fUnpack = new TObjArray();
268  fBlobPrefixName = 0;
269  fBlobTypeName = str->GetName();
270  fLocatedValue = str->GetTitle();
271  }
272 
273  fUnpack->Add(str);
274 }
275 
276 ////////////////////////////////////////////////////////////////////////////////
277 /// emulate integer value in raw data
278 
279 void TSQLObjectData::AddUnpackInt(const char *tname, Int_t value)
280 {
281  TString sbuf;
282  sbuf.Form("%d", value);
283  AddUnpack(tname, sbuf.Data());
284 }
285 
286 ////////////////////////////////////////////////////////////////////////////////
287 /// shift to next column or next row in blob data
288 
289 void TSQLObjectData::ShiftToNextValue()
290 {
291  Bool_t doshift = kTRUE;
292 
293  if (fUnpack != 0) {
294  TObject *prev = fUnpack->First();
295  fUnpack->Remove(prev);
296  delete prev;
297  fUnpack->Compress();
298  if (fUnpack->GetLast() >= 0) {
299  TNamed *curr = (TNamed *)fUnpack->First();
300  fBlobPrefixName = 0;
301  fBlobTypeName = curr->GetName();
302  fLocatedValue = curr->GetTitle();
303  return;
304  }
305  delete fUnpack;
306  fUnpack = 0;
307  doshift = kFALSE;
308  }
309 
310  if (fCurrentBlob) {
311  if (doshift)
312  ShiftBlobRow();
313  ExtractBlobValues();
314  } else if (fClassData != 0) {
315  if (doshift)
316  fLocatedColumn++;
317  if (fLocatedColumn < GetNumClassFields()) {
318  fLocatedField = GetClassFieldName(fLocatedColumn);
319  fLocatedValue = fClassRow->GetField(fLocatedColumn);
320  } else {
321  fLocatedField = 0;
322  fLocatedValue = 0;
323  }
324  }
325 }
326 
327 ////////////////////////////////////////////////////////////////////////////////
328 /// checks if data type corresponds to that stored in raw table
329 
330 Bool_t TSQLObjectData::VerifyDataType(const char *tname, Bool_t errormsg)
331 {
332  if (tname == 0) {
333  if (errormsg)
334  Error("VerifyDataType", "Data type not specified");
335  return kFALSE;
336  }
337 
338  // here maybe type of column can be checked
339  if (!IsBlobData())
340  return kTRUE;
341 
342  if (gDebug > 4)
343  if ((fBlobTypeName == 0) && errormsg) {
344  Error("VerifyDataType", "fBlobTypeName is null");
345  return kFALSE;
346  }
347 
348  TString v1(fBlobTypeName);
349  TString v2(tname);
350 
351  // if (strcmp(fBlobTypeName,tname)!=0) {
352  if (v1 != v2) {
353  if (errormsg)
354  Error("VerifyDataType", "Data type missmatch %s - %s", fBlobTypeName, tname);
355  return kFALSE;
356  }
357 
358  return kTRUE;
359 }
360 
361 ////////////////////////////////////////////////////////////////////////////////
362 /// prepare to read data from raw table
363 
364 Bool_t TSQLObjectData::PrepareForRawData()
365 {
366  if (!ExtractBlobValues())
367  return kFALSE;
368 
369  fCurrentBlob = kTRUE;
370 
371  return kTRUE;
372 }
373 
374 //===================================================================================
375 
376 //________________________________________________________________________
377 //
378 // TSQLObjectDataPool contains list (pool) of data from single class table
379 // for differents objects, all belonging to the same key.
380 // This is typical situation when list of objects stored as single key.
381 // To optimize reading of such data, one query is submitted and results of that
382 // query kept in TSQLObjectDataPool object
383 //
384 //________________________________________________________________________
385 
386 ClassImp(TSQLObjectDataPool);
387 
388 ////////////////////////////////////////////////////////////////////////////////
389 
390 TSQLObjectDataPool::TSQLObjectDataPool() : TObject(), fInfo(0), fClassData(0), fIsMoreRows(kTRUE), fRowsPool(0)
391 {
392 }
393 
394 ////////////////////////////////////////////////////////////////////////////////
395 
396 TSQLObjectDataPool::TSQLObjectDataPool(TSQLClassInfo *info, TSQLResult *data)
397  : TObject(), fInfo(info), fClassData(data), fIsMoreRows(kTRUE), fRowsPool(0)
398 {
399 }
400 
401 ////////////////////////////////////////////////////////////////////////////////
402 /// Destructor of TSQLObjectDataPool class
403 /// Deletes not used rows and class data table
404 
405 TSQLObjectDataPool::~TSQLObjectDataPool()
406 {
407  if (fClassData != 0)
408  delete fClassData;
409  if (fRowsPool != 0) {
410  fRowsPool->Delete();
411  delete fRowsPool;
412  }
413 }
414 
415 ////////////////////////////////////////////////////////////////////////////////
416 /// Returns single sql row with object data for that class
417 
418 TSQLRow *TSQLObjectDataPool::GetObjectRow(Long64_t objid)
419 {
420  if (fClassData == 0)
421  return 0;
422 
423  Long64_t rowid;
424 
425  if (fRowsPool != 0) {
426  TObjLink *link = fRowsPool->FirstLink();
427  while (link != 0) {
428  TSQLRow *row = (TSQLRow *)link->GetObject();
429  rowid = sqlio::atol64(row->GetField(0));
430  if (rowid == objid) {
431  fRowsPool->Remove(link);
432  return row;
433  }
434 
435  link = link->Next();
436  }
437  }
438 
439  while (fIsMoreRows) {
440  TSQLRow *row = fClassData->Next();
441  if (row == 0)
442  fIsMoreRows = kFALSE;
443  else {
444  rowid = sqlio::atol64(row->GetField(0));
445  if (rowid == objid)
446  return row;
447  if (fRowsPool == 0)
448  fRowsPool = new TList();
449  fRowsPool->Add(row);
450  }
451  }
452 
453  return 0;
454 }