Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TTreeSQL.cxx
Go to the documentation of this file.
1 // @(#)root/tree:$Id$
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 /** \class TTreeSQL
13 \ingroup tree
14 
15 Implement TTree for a SQL backend
16 */
17 
18 #include <Riostream.h>
19 #include <vector>
20 #include <map>
21 #include <stdlib.h>
22 
23 #include "TString.h"
24 #include "TROOT.h"
25 #include "TSystem.h"
26 #include "TError.h"
27 #include "TFile.h"
28 #include "TTree.h"
29 #include "TLeaf.h"
30 #include "TBranch.h"
31 
32 #include "TSQLRow.h"
33 #include "TSQLResult.h"
34 #include "TSQLServer.h"
35 #include "TSQLTableInfo.h"
36 #include "TSQLColumnInfo.h"
37 
38 #include "TTreeSQL.h"
39 #include "TBasketSQL.h"
40 
41 ClassImp(TTreeSQL);
42 
43 ////////////////////////////////////////////////////////////////////////////////
44 /// Constructor with an explicit TSQLServer
45 
46 TTreeSQL::TTreeSQL(TSQLServer *server, TString DB, const TString& table) :
47  TTree(table.Data(), "Database read from table: " + table, 0), fDB(DB),
48  fTable(table.Data()),
49  fResult(0), fRow(0),
50  fServer(server),
51  fBranchChecked(kFALSE),
52  fTableInfo(0)
53 {
54  fCurrentEntry = -1;
55  fQuery = TString("Select * from " + fTable);
56  fEntries = 0;
57 
58  if (fServer==0) {
59  Error("TTreeSQL","No TSQLServer specified");
60  return;
61  }
62  if (CheckTable(fTable.Data())) {
63  Init();
64  }
65 }
66 
67 ////////////////////////////////////////////////////////////////////////////////
68 /// Not implemented yet
69 
70 TBranch* TTreeSQL::BranchImp(const char *, const char *,
71  TClass *, void *, Int_t ,
72  Int_t )
73 {
74  Fatal("BranchImp","Not implemented yet");
75  return 0;
76 }
77 
78 ////////////////////////////////////////////////////////////////////////////////
79 /// Not implemented yet
80 
81 TBranch* TTreeSQL::BranchImp(const char *, TClass *,
82  void *, Int_t , Int_t )
83 {
84  Fatal("BranchImp","Not implemented yet");
85  return 0;
86 }
87 ////////////////////////////////////////////////////////////////////////////////
88 /// Not implemented yet
89 
90 Int_t TTreeSQL::Branch(TCollection *, Int_t,
91  Int_t, const char *)
92 {
93  Fatal("Branch","Not implemented yet");
94  return 0;
95 }
96 
97 ////////////////////////////////////////////////////////////////////////////////
98 /// Not implemented yet
99 
100 Int_t TTreeSQL::Branch(TList *, Int_t, Int_t)
101 {
102  Fatal("Branch","Not implemented yet");
103  return 0;
104 }
105 
106 ////////////////////////////////////////////////////////////////////////////////
107 /// Not implemented yet
108 
109 Int_t TTreeSQL::Branch(const char *, Int_t ,
110  Int_t)
111 {
112  Fatal("Branch","Not implemented yet");
113  return 0;
114 }
115 
116 ////////////////////////////////////////////////////////////////////////////////
117 /// Not implemented yet
118 
119 TBranch* TTreeSQL::Bronch(const char *, const char *, void *,
120  Int_t, Int_t)
121 {
122  Fatal("Bronch","Not implemented yet");
123  return 0;
124 }
125 
126 ////////////////////////////////////////////////////////////////////////////////
127 /// Not implemented yet
128 
129 TBranch* TTreeSQL::BranchOld(const char *, const char *,
130  void *, Int_t, Int_t)
131 {
132  Fatal("BranchOld","Not implemented yet");
133  return 0;
134 }
135 
136 ////////////////////////////////////////////////////////////////////////////////
137 /// Not implemented yet
138 
139 TBranch *TTreeSQL::Branch(const char *, const char *, void *,
140  Int_t, Int_t)
141 {
142  Fatal("Branch","Not implemented yet");
143  return 0;
144 }
145 
146 ///////////////////////////////////////////////////////////////////////////////
147 /// Create a branch
148 
149 TBranch * TTreeSQL::Branch(const char *name, void *address,
150  const char *leaflist, Int_t bufsize)
151 {
152  Int_t nb = fBranches.GetEntriesFast();
153  TBranch *branch;
154  TString brName;
155 
156  for (int i=0;i<nb;i++) {
157  branch = (TBranch*)fBranches.UncheckedAt(i);
158  brName = branch->GetName();
159  if (brName.CompareTo(name) == 0) {
160  // Now if the branch exists in db, root gives a warning and exit
161  // Dealing with duplicate branch has been done, but not tested yet.
162  // So if you want to allow duplicate branch, just comment Fatal() line and uncomment commented
163  // below Fatal() line
164 
165  Fatal("Branch()", "Duplicate branch!!!");
166 
167  /* Commented. If uncommented, should comment Fatal line.
168  // this is a duplicate branch. So reset data structure memory address and return.
169  branch->SetAddress(address);
170  return branch;
171  */
172  }
173  }
174 
175  return TTree::Branch(name, address, leaflist, bufsize);
176 }
177 
178 ////////////////////////////////////////////////////////////////////////////////
179 /// Check if the basket is properly setup
180 
181 void TTreeSQL::CheckBasket(TBranch *branch)
182 {
183  TBasketSQL* basket = (TBasketSQL *)branch->GetBasket(0);
184 
185  if (basket==0) {
186  basket = (TBasketSQL*)CreateBasket(branch);
187  if (basket==0) return;
188  //++(branch->fNBaskets);
189  branch->GetListOfBaskets()->AddAtAndExpand(basket,0);
190  }
191  TBuffer * buffer = basket->GetBufferRef();
192 
193  if(buffer == 0){
194  std::vector<Int_t> *columns = GetColumnIndice(branch);
195  if (columns) basket->CreateBuffer(branch->GetName(),"A", columns, branch, &fResult);
196  }
197 
198  Int_t nb = branch->GetListOfBranches()->GetEntriesFast();
199  for (int i=0;i<nb;i++) {
200  TBranch * subbranch = (TBranch*)branch->GetListOfBranches()->UncheckedAt(i);
201  if(subbranch) CheckBasket(subbranch);
202  }
203 }
204 
205 ////////////////////////////////////////////////////////////////////////////////
206 /// Check if the table has a column corresponding the branch
207 /// and that the resultset are properly setup
208 
209 Bool_t TTreeSQL::CheckBranch(TBranch * tb)
210 {
211  if (fServer==0) {
212  return kFALSE;
213  }
214  TString leafName;
215  TLeaf *leaf;
216  Int_t nl;
217  TString str = "";
218  TString typeName = "";
219 
220  if (!tb) return kFALSE;
221 
222  TBasketSQL *basket = (TBasketSQL *)tb->GetBasket(0);
223  if (!basket) return kFALSE;
224 
225  TSQLResult *rs = basket->GetResultSet();
226  if (!rs) {
227  Error("CheckBranch","%s has basket but no resultset yet",tb->GetName());
228  return kFALSE;
229  }
230 
231  nl = tb->GetNleaves();
232 
233  for(int j=0;j<nl;j++) {
234  leaf = (TLeaf*)tb->GetListOfLeaves()->UncheckedAt(j);
235  typeName = leaf->GetTypeName();
236  typeName = ConvertTypeName(leaf->GetTypeName());
237  leafName = leaf->GetName();
238  str = "";
239  str = tb->GetName();
240  str += "__";
241  str += leafName;
242 
243  for (int i=0; i< rs->GetFieldCount(); ++i) {
244  if (str.CompareTo(rs->GetFieldName(i),TString::kIgnoreCase) == 0) return kTRUE;
245  }
246  // We assume that if ONE of the leaf is in the table, then ALL the leaf are in
247  // the table.
248  // TODO: this assumption is harmful if user changes branch structure while keep its name
249  CreateBranch(str, typeName);
250  }
251  return kFALSE;
252 }
253 
254 ////////////////////////////////////////////////////////////////////////////////
255 /// Check the table exist in the database
256 
257 Bool_t TTreeSQL::CheckTable(const TString &table) const
258 {
259  if (fServer==0) return kFALSE;
260  TSQLResult * tables = fServer->GetTables(fDB.Data(),table);
261  if (!tables) return kFALSE;
262  TSQLRow * row = 0;
263  while( (row = tables->Next()) ) {
264  if(table.CompareTo(row->GetField(0),TString::kIgnoreCase)==0){
265  return kTRUE;
266  }
267  }
268  // The table is a not a permanent table, let's see if it is a 'temporary' table
269  Int_t before = gErrorIgnoreLevel;
270  gErrorIgnoreLevel = kFatal;
271  TSQLResult *res = fServer->GetColumns(fDB.Data(),table);
272  if (res) {
273  delete res;
274  return kTRUE;
275  }
276  gErrorIgnoreLevel = before;
277 
278  return kFALSE;
279 }
280 
281 ////////////////////////////////////////////////////////////////////////////////
282 /// Convert from ROOT typename to SQL typename
283 
284 TString TTreeSQL::ConvertTypeName(const TString& typeName )
285 {
286  TString tn = "";
287 
288  if(typeName == "Char_t"){
289  tn = "TEXT";
290  }
291  else if(typeName == "Int_t") {
292  tn = "INTEGER";
293  }
294  else if(typeName == "Short_t") {
295  tn = "SMALLINT";
296  }
297  else if( typeName == "UShort_t") {
298  tn = "SMALLINT UNSIGNED";
299  }
300  else if(typeName == "Float_t"){
301  tn = "FLOAT";
302  }
303  else if(typeName == "Float16_t"){
304  tn = "FLOAT";
305  }
306  else if(typeName == "Double_t"){
307  tn = "DOUBLE";
308  }
309  else if(typeName == "Double32_t"){
310  tn = "FLOAT";
311  }
312  else if(typeName == "UInt_t") {
313  tn = "INT UNSIGNED";
314  }
315  else if( typeName == "Long_t") {
316  tn = "INTEGER";
317  }
318  else if( typeName == "ULong_t") {
319  tn = "INTEGER UNSIGNED";
320  }
321  else if( typeName == "Long64_t") {
322  tn = "BIGINT";
323  }
324  else if( typeName == "ULong64_t") {
325  tn = "BIGINT UNSIGNED";
326  }
327  else if( typeName == "Bool_t") {
328  tn = "BOOL";
329  }
330  else if( typeName == "TString") {
331  tn = "TEXT";
332  }
333 
334  else {
335  Error("ConvertTypeName","TypeName (%s) not found",typeName.Data());
336  return "";
337  }
338 
339  return tn;
340 }
341 
342 ////////////////////////////////////////////////////////////////////////////////
343 /// Create a TBasketSQL
344 
345 TBasket * TTreeSQL::CreateBasket(TBranch * tb)
346 {
347  if (fServer==0) {
348  Error("CreateBasket","No TSQLServer specified");
349  return 0;
350  }
351  std::vector<Int_t> *columnVec = GetColumnIndice(tb);
352  if (columnVec) {
353  return new TBasketSQL(tb->GetName(), tb->GetName(), tb,
354  &fResult, &fInsertQuery, columnVec, &fRow);
355  } else {
356  return 0;
357  }
358 }
359 
360 ////////////////////////////////////////////////////////////////////////////////
361 /// Create the column(s) in the database that correspond to the branch/
362 
363 void TTreeSQL::CreateBranch(const TString &branchName, const TString &typeName)
364 {
365  if (fServer==0) {
366  Error("CreateBranch","No TSQLServer specified");
367  return;
368  }
369  TString alterSQL = "";
370  alterSQL = "";
371  alterSQL = "ALTER TABLE ";
372  alterSQL += fTable.Data();
373  alterSQL += " ADD ";
374  alterSQL += branchName.Data();;
375  alterSQL += " ";
376  alterSQL += typeName;
377  alterSQL += " ";
378 
379  fServer->Query(alterSQL);
380 }
381 
382 ////////////////////////////////////////////////////////////////////////////////
383 /// determine leaf description string
384 
385 void TTreeSQL::CreateBranches()
386 {
387  TList * columns = fTableInfo->GetColumns();
388  if(!columns) return;
389 
390  TIter next(columns);
391 
392  TString branchName;
393  TString type;
394  TString leafName;
395  TBranch * br = 0;
396  TSQLColumnInfo * info;
397  while ( (info = ((TSQLColumnInfo*) next()) ))
398  {
399  type = info->GetTypeName();
400  branchName = info->GetName();
401 
402 
403  Int_t pos;
404  if ((pos=branchName.Index("__"))!=kNPOS) {
405  leafName = branchName(pos+2,branchName.Length());
406  branchName.Remove(pos);
407  } else {
408  leafName = branchName;
409  }
410 
411  TString str;
412  int i;
413  unsigned ui;
414  double d;
415  float f;
416 
417  br = 0;
418 
419  if(type.CompareTo("varchar",TString::kIgnoreCase)==0 ||
420  type.CompareTo("varchar2",TString::kIgnoreCase)==0 ||
421  type.CompareTo("char",TString::kIgnoreCase)==0 ||
422  type.CompareTo("longvarchar",TString::kIgnoreCase)==0 ||
423  type.CompareTo("longvarbinary",TString::kIgnoreCase)==0 ||
424  type.CompareTo("varbinary",TString::kIgnoreCase)==0 ||
425  type.CompareTo("text",TString::kIgnoreCase )==0 ) {
426  br = TTree::Branch(leafName,&str);
427 
428  }
429  else if(type.CompareTo("int",TString::kIgnoreCase)==0 ){
430  br = TTree::Branch(leafName,&i);
431  }
432 
433  //Somehow it should be possible to special-case the time classes
434  //but I think we'd need to create a new TSQLTime or something like that...
435  else if( type.CompareTo("date",TString::kIgnoreCase)==0 ||
436  type.CompareTo("time",TString::kIgnoreCase)==0 ||
437  type.CompareTo("timestamp",TString::kIgnoreCase)==0 ||
438  type.CompareTo("datetime",TString::kIgnoreCase)==0 ) {
439  br = TTree::Branch(leafName,&str);
440 
441  }
442 
443  else if(type.CompareTo("bit",TString::kIgnoreCase)==0 ||
444  type.CompareTo("tinyint",TString::kIgnoreCase)==0 ||
445  type.CompareTo("smallint",TString::kIgnoreCase)==0 ) {
446  br = TTree::Branch(leafName,&ui);
447  }
448 
449  else if( type.CompareTo("decimal",TString::kIgnoreCase)==0 ||
450  type.CompareTo("numeric",TString::kIgnoreCase)==0 ||
451  type.CompareTo("double",TString::kIgnoreCase)==0 ||
452  type.CompareTo("float",TString::kIgnoreCase)==0 )
453  {
454  br = TTree::Branch(leafName,&f);
455  }
456  else if( type.CompareTo("bigint",TString::kIgnoreCase)==0 ||
457  type.CompareTo("real",TString::kIgnoreCase) == 0)
458  {
459  br = TTree::Branch(leafName,&d);
460  }
461 
462  if (br == 0)
463  {
464  Error("CreateBranches", "Skipped %s", branchName.Data());
465  continue;
466  }
467 
468  br->ResetAddress();
469 
470  (br->GetBasketEntry())[0] = 0;
471  (br->GetBasketEntry())[1] = fEntries;
472  br->SetEntries(fEntries);
473 
474  //++(br->fNBaskets);
475  br->GetListOfBaskets()->AddAtAndExpand(CreateBasket(br),0);
476  }
477 }
478 
479 ////////////////////////////////////////////////////////////////////////////////
480 /// Create the database table corresponding to this TTree.
481 
482 Bool_t TTreeSQL::CreateTable(const TString &table)
483 {
484  if (fServer==0) {
485  Error("CreateTable","No TSQLServer specified");
486  return false;
487  }
488  Int_t i, j;
489  TString branchName, leafName, typeName;
490  TString createSQL, alterSQL, str;
491  Int_t nb = fBranches.GetEntriesFast();
492  Int_t nl = 0;
493 
494  TBranch *branch;
495  TLeaf *leaf;
496 
497  for (i=0;i<nb;i++) {
498  branch = (TBranch*)fBranches.UncheckedAt(i);
499  branchName = branch->GetName();
500  nl = branch->GetNleaves();
501  for(j=0;j<nl;j++) {
502  leaf = (TLeaf*)branch->GetListOfLeaves()->UncheckedAt(j);
503  leafName = leaf->GetName();
504  typeName = ConvertTypeName(leaf->GetTypeName());
505  // length = leaf->GetLenStatic();
506 
507  if(i == 0 && j == 0) {
508  createSQL = "";
509  createSQL += "CREATE TABLE ";
510  createSQL += table;
511  createSQL += " (";
512  createSQL += branchName;
513  createSQL += "__";
514  createSQL += leafName;
515  createSQL += " ";
516  createSQL += typeName;
517  createSQL += " ";
518  createSQL += ")";
519 
520  TSQLResult *sres = fServer->Query(createSQL.Data());
521  if (!sres) {
522  Error("CreateTable","May have failed");
523  return false;
524  }
525  }
526  else {
527  str = "";
528  str = branchName;
529  str += "__";
530  str += leafName;
531  CreateBranch(str, typeName);
532  } //else
533  } // inner for loop
534  } // outer for loop
535  // retrieve table to initialize fResult
536  delete fResult;
537  fResult = fServer->Query(fQuery.Data());
538  return (fResult!=0);
539 }
540 
541 ////////////////////////////////////////////////////////////////////////////////
542 /// Initializeation routine
543 
544 void TTreeSQL::Init()
545 {
546  fCurrentEntry = -1;
547 
548  GetEntries();
549 
550  delete fResult;
551  fResult = fServer->Query(fQuery.Data());
552  if(!fResult) return;
553 
554  if (fDB != "") {
555  fServer->SelectDataBase(fDB);
556  }
557  fTableInfo = fServer->GetTableInfo(fTable);
558  CreateBranches();
559 }
560 
561 ////////////////////////////////////////////////////////////////////////////////
562 /// Copy the information from the user object to the TTree
563 
564 Int_t TTreeSQL::Fill()
565 {
566  Int_t nb = fBranches.GetEntriesFast();
567  TString typeName;
568  TBranch *branch;
569 
570  if (fServer==0) return 0;
571 
572  if(!CheckTable(fTable.Data())) {
573  if (!CreateTable(fTable.Data())) {
574  return -1;
575  }
576  }
577 
578  PrepEntry(fEntries);
579 
580  for (int i=0;i<nb;i++) {
581  branch = (TBranch*)fBranches.UncheckedAt(i);
582  CheckBasket(branch);
583  }
584 
585  if (!fBranchChecked) {
586  for(int i=0;i<nb;i++) {
587  branch = (TBranch*)fBranches.UncheckedAt(i);
588  if (!CheckBranch(branch)) {
589  Error("Fill","CheckBranch for %s failed",branch->GetName());
590  }
591  }
592  fBranchChecked = kTRUE;
593  }
594  ResetQuery();
595 
596  TTree::Fill();
597 
598  if (fInsertQuery[fInsertQuery.Length()-1]!='(') {
599  fInsertQuery.Remove(fInsertQuery.Length()-1);
600  fInsertQuery += ")";
601  TSQLResult *res = fServer?fServer->Query(fInsertQuery):0;
602 
603  if (res) {
604  return res->GetRowCount();
605  }
606  }
607  return -1;
608 }
609 
610 ////////////////////////////////////////////////////////////////////////////////
611 /// Return a vector of columns index corresponding to the
612 /// current SQL table and the branch given as argument
613 /// Returns 0 if no columns indices is found
614 /// Otherwise returns a pointer to a vector to be deleted by the caller
615 
616 std::vector<Int_t> *TTreeSQL::GetColumnIndice(TBranch *branch)
617 {
618  if (!CheckTable(fTable)) return 0;
619 
620  std::vector<Int_t> *columns = new std::vector<Int_t>;
621 
622  Int_t nl = branch->GetNleaves();
623 
624  std::vector<TString> names;
625 
626  TList *col_list = fTableInfo->GetColumns();
627  if (col_list==0) {
628  delete columns;
629  return 0;
630  }
631 
632  std::pair<TString,Int_t> value;
633 
634  TIter next(col_list);
635  TSQLColumnInfo * cinfo;
636  int rows = 0;
637  while ((cinfo = (TSQLColumnInfo*) next())) {
638  names.push_back( cinfo->GetName() );
639  rows++;
640  }
641 
642  for(int j=0;j<nl;j++) {
643 
644  Int_t col = -1;
645  TLeaf *leaf = (TLeaf*)branch->GetListOfLeaves()->UncheckedAt(j);
646  TString leafName = leaf->GetName();
647  TString str;
648 
649  str = "";
650  str = branch->GetName();
651  str += "__";
652  str += leafName;
653  for (Int_t i=0;i<rows;++i) {
654  if (str.CompareTo(names[i],TString::kIgnoreCase)==0) {
655  col = i;
656  break;
657  }
658  }
659  if (col<0) {
660  str = leafName;
661  for (Int_t i=0;i<rows;++i) {
662  if (str.CompareTo(names[i],TString::kIgnoreCase)==0) {
663  col = i;
664  break;
665  }
666  }
667  }
668  if(col>=0){
669  columns->push_back(col);
670  } else Error("GetColumnIndice","Error finding column %d %s",j,str.Data());
671  }
672  if (columns->empty()) {
673  delete columns;
674  return 0;
675  } else
676  return columns;
677 }
678 
679 ////////////////////////////////////////////////////////////////////////////////
680 /// Get the number of rows in the database
681 
682 Long64_t TTreeSQL::GetEntries() const
683 {
684  if (fServer==0) return GetEntriesFast();
685  if (!CheckTable(fTable.Data())) return 0;
686 
687  TTreeSQL* thisvar = const_cast<TTreeSQL*>(this);
688 
689  // What if the user already started to call GetEntry
690  // What about the initial value of fEntries is it really 0?
691 
692  TString counting = "select count(*) from " + fTable;
693  TSQLResult *count = fServer->Query(counting);
694 
695  if (count==0) {
696  thisvar->fEntries = 0;
697  } else {
698  TSQLRow * row = count->Next();
699  if (row) {
700  TString val = row->GetField(0);
701  Long_t ret;
702  sscanf(val.Data(), "%ld",&(ret) );
703  thisvar->fEntries = ret;
704  } else {
705  thisvar->fEntries = 0;
706  }
707  }
708  return fEntries;
709 }
710 
711 ////////////////////////////////////////////////////////////////////////////////
712 /// Return the number of entries as of the last check.
713 /// Use GetEntries for a more accurate count.
714 
715 Long64_t TTreeSQL::GetEntriesFast() const
716 {
717  return fEntries;
718 }
719 
720 ////////////////////////////////////////////////////////////////////////////////
721 /// Load the data for the entry from the database.
722 
723 Int_t TTreeSQL::GetEntry(Long64_t entry, Int_t getall)
724 {
725  if (PrepEntry(entry)>=0) return TTree::GetEntry(entry,getall);
726  else return -1;
727 }
728 
729 ////////////////////////////////////////////////////////////////////////////////
730 /// Setup the tree to the load the specified entry.
731 
732 Long64_t TTreeSQL::LoadTree(Long64_t entry)
733 {
734  fReadEntry = entry;
735  return PrepEntry(entry);
736 }
737 
738 ////////////////////////////////////////////////////////////////////////////////
739 /// Make sure the server and result set are setup for the requested entry
740 
741 Long64_t TTreeSQL::PrepEntry(Long64_t entry)
742 {
743  if (entry < 0 || entry >= fEntries || fServer==0) return 0;
744  fReadEntry = entry;
745 
746  if(entry == fCurrentEntry) return entry;
747 
748  if(entry < fCurrentEntry || fResult==0){
749  delete fResult;
750  fResult = fServer->Query(fQuery.Data());
751  fCurrentEntry = -1;
752  }
753 
754  Bool_t reset = false;
755  while ( fResult && fCurrentEntry < entry ) {
756  ++fCurrentEntry;
757  delete fRow;
758  fRow = fResult->Next();
759  if (fRow==0 && !reset) {
760  delete fResult;
761  fResult = fServer->Query(fQuery.Data());
762  fCurrentEntry = -1;
763  reset = true;
764  }
765  }
766  if (fRow==0) return -1;
767  return entry;
768 }
769 
770 //______________________________________________________________________________
771 // void TTreeSQL::LoadNumberEntries()
772 // {
773 // R__ASSERT(0);
774 
775 // fResult = fServer->Query(fQuery.Data());
776 // fEntries=0;
777 
778 // while(fResult->Next()){
779 // fEntries++;
780 // }
781 // fResult = fServer->Query(fQuery.Data());
782 // }
783 
784 ////////////////////////////////////////////////////////////////////////////////
785 /// Refresh contents of this Tree and its branches from the current
786 /// Tree status in the database
787 /// One can call this function in case the Tree on its file is being
788 /// updated by another process
789 
790 void TTreeSQL::Refresh()
791 {
792  // Note : something to be done?
793  GetEntries(); // Re-load the number of entries
794  fCurrentEntry = -1;
795  delete fResult; fResult = 0;
796  delete fRow; fRow = 0;
797 }
798 
799 ////////////////////////////////////////////////////////////////////////////////
800 /// Reset the internal query
801 
802 void TTreeSQL::ResetQuery()
803 {
804  fInsertQuery = "INSERT INTO " + fTable + " VALUES (";
805 }
806 
807 
808 ////////////////////////////////////////////////////////////////////////////////
809 // Destructor
810 
811 TTreeSQL::~TTreeSQL()
812 {
813  delete fTableInfo;
814  delete fResult;
815  delete fRow;
816 }