ROOT logo
// @(#)root/tree:$Id: TTreeSQL.cxx 24592 2008-06-27 17:32:03Z pcanal $
// Author: Philippe Canal and al. 08/2004

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TTreeSQL                                                             //
//                                                                      //
// Implement TTree for a SQL backend                                    //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include <Riostream.h>
#include <vector>
#include <map>
#include <stdlib.h>

#include "TString.h"
#include "TROOT.h"
#include "TSystem.h"
#include "TError.h"
#include "TFile.h"
#include "TTree.h"
#include "TLeaf.h"
#include "TBranch.h"

#include "TSQLRow.h"
#include "TSQLResult.h"
#include "TSQLServer.h"

#include "TTreeSQL.h"
#include "TBasketSQL.h"

ClassImp(TTreeSQL)

//______________________________________________________________________________
TTreeSQL::TTreeSQL(TSQLServer *server, TString DB, const TString& table) :
   TTree(table.Data(), "Database read from table: " + table, 0), fDB(DB),
   fTable(table.Data()),
   fResult(0), fRow(0),
   fServer(server),
   fBranchChecked(kFALSE)
{
   // Constructor with an explicit TSQLServer

   fCurrentEntry = -1;
   fQuery = TString("Select * from " + fTable);
   fEntries = 0;

   if (fServer==0) {
      Error("TTreeSQL","No TSQLServer specified");
      return;
   }
   if (CheckTable(fTable.Data())) {
      Init();
   }
}

//______________________________________________________________________________
TBranch* TTreeSQL::BranchImp(const char *, const char *,
                             TClass *, void *, Int_t ,
                             Int_t )
{
   // Not implemented yet

   Fatal("BranchImp","Not implemented yet");
   return 0;
}

//______________________________________________________________________________
TBranch* TTreeSQL::BranchImp(const char *, TClass *,
                             void *, Int_t , Int_t )
{
   // Not implemented yet

   Fatal("BranchImp","Not implemented yet");
   return 0;
}

//______________________________________________________________________________
Int_t TTreeSQL::Branch(TCollection *, Int_t,
                       Int_t, const char *)
{
   // Not implemented yet

   Fatal("Branch","Not implemented yet");
   return 0;
}

//______________________________________________________________________________
Int_t TTreeSQL::Branch(TList *, Int_t, Int_t)
{
   // Not implemented yet

   Fatal("Branch","Not implemented yet");
   return 0;
}

//______________________________________________________________________________
Int_t TTreeSQL::Branch(const char *, Int_t ,
                       Int_t)
{
   // Not implemented yet

   Fatal("Branch","Not implemented yet");
   return 0;
}

//______________________________________________________________________________
TBranch* TTreeSQL::Bronch(const char *, const char *, void *,
                          Int_t, Int_t)
{
   // Not implemented yet

   Fatal("Bronc","Not implemented yet");
   return 0;
}

//______________________________________________________________________________
TBranch* TTreeSQL::BranchOld(const char *, const char *,
                             void *, Int_t, Int_t)
{
   // Not implemented yet

   Fatal("BranchOld","Not implemented yet");
   return 0;
}

//______________________________________________________________________________
TBranch *TTreeSQL::Branch(const char *, const char *, void *,
                          Int_t, Int_t)
{
   // Not implemented yet

   Fatal("Branch","Not implemented yet");
   return 0;
}

//______________________________________________________________________________
TBranch * TTreeSQL::Branch(const char *name, void *address,
                           const char *leaflist, Int_t bufsize)
{
   // Create a branch

   Int_t nb = fBranches.GetEntriesFast();
   TBranch *branch;
   TString brName;

   for (int i=0;i<nb;i++) {
      branch = (TBranch*)fBranches.UncheckedAt(i);
      brName = branch->GetName();
      if (brName.Index(name) == 0) {
         // Now if the branch exists in db, root gives a warning and exit
         // Dealing with duplicate branch has been done, but not tested yet.
         // So if you want to allow duplicate branch, just comment Fatal() line and uncomment commented
         // below Fatal() line

         Fatal("Branch()", "Duplicate branch!!!");

         /* Commented. If uncommented, should comment Fatal line.
         // this is a duplicate branch. So reset data structure memory address and return.
         branch->SetAddress(address);
         return branch;
         */
      }
   }
   return TTree::Branch(name, address, leaflist, bufsize);
}

//______________________________________________________________________________
void TTreeSQL::CheckBasket(TBranch *branch)
{
   // Check if the basket is properly setup

   TBasketSQL* basket = (TBasketSQL *)branch->GetBasket(0);

   if (basket==0) {
      basket = (TBasketSQL*)CreateBasket(branch);
      branch->GetListOfBaskets()->AddAtAndExpand(basket,0);
   }
   TBuffer * buffer = basket->GetBufferRef();

   if(buffer == 0){
      vector<Int_t> *columns = GetColumnIndice(branch);
      if (columns) basket->CreateBuffer(branch->GetName(),"A", columns, branch, &fResult);
   }

   Int_t nb = branch->GetListOfBranches()->GetEntriesFast();
   for (int i=0;i<nb;i++) {
      TBranch * subbranch = (TBranch*)branch->GetListOfBranches()->UncheckedAt(i);
      if(subbranch) CheckBasket(subbranch);
   }
}

//______________________________________________________________________________
Bool_t TTreeSQL::CheckBranch(TBranch * tb)
{
   // Check if the table has a column corresponding the branch
   // and that the resultset are properly setup

   if (fServer==0) {
      return kFALSE;
   }
   TString leafName;
   TLeaf *leaf;
   Int_t nl;
   TString str = "";
   TString typeName = "";

   if (!tb) return kFALSE;

   TBasketSQL *basket = (TBasketSQL *)tb->GetBasket(0);
   if (!basket) return kFALSE;

   TSQLResult *rs = basket->GetResultSet();
   if (!rs) {
      Error("CheckBranch","%s has basket but no resultset yet",tb->GetName());
      return kFALSE;
   }

   nl = tb->GetNleaves();

   for(int j=0;j<nl;j++) {
      leaf = (TLeaf*)tb->GetListOfLeaves()->UncheckedAt(j);
      typeName = leaf->GetTypeName();
      typeName = ConvertTypeName(leaf->GetTypeName());
      leafName = leaf->GetName();
      str = "";
      str = tb->GetName();
      str += "__";
      str += leafName;

      for (int i=0; i< rs->GetFieldCount(); ++i) {
         if (strcmp(rs->GetFieldName(i), str.Data()) == 0) return kTRUE;
      }
      // We assume that if ONE of the leaf is in the table, then ALL the leaf are in
      // the table.
      // TODO: this assumption is harmful if user changes branch structure while keep its name
      CreateBranch(str, typeName);
   }
   return kFALSE;
}

//______________________________________________________________________________
Bool_t TTreeSQL::CheckTable(const TString &table) const
{
   // Check the table exist in the database

   if (fServer==0) return kFALSE;
   TSQLResult * tables = fServer->GetTables(fDB.Data(),table);
   TSQLRow * row = 0;
   while( (row = tables->Next()) ) {
      if(strcmp(row->GetField(0),table.Data())==0){
         return kTRUE;
      }
   }

   return kFALSE;
}

//______________________________________________________________________________
TString TTreeSQL::ConvertTypeName(const TString& typeName )
{
   // Convert from ROOT typename to SQL typename

   TString tn = "";

   if(typeName == "Char_t"){
      tn = "TEXT";
   }
   else if(typeName == "Int_t") {
      tn = "INTEGER";
   }
   else if(typeName == "Short_t") {
      tn = "SMALLINT";
   }
   else if( typeName == "UShort_t") {
      tn = "SMALLINT UNSIGNED";
   }
   else if(typeName == "Float_t"){
      tn = "FLOAT";
   }
   else if(typeName == "Float16_t"){
      tn = "FLOAT";
   }
   else if(typeName == "Double_t"){
      tn = "DOUBLE";
   }
   else if(typeName == "Double32_t"){
      tn = "FLOAT";
   }
   else if(typeName == "UInt_t") {
      tn = "INT UNSIGNED";
   }
   else if( typeName == "Long_t") {
      tn = "INTEGER";
   }
   else if( typeName == "ULong_t") {
      tn = "INTEGER UNSIGNED";
   }
   else if( typeName == "Long64_t") {
      tn = "BIGINT";
   }
   else if( typeName == "ULong64_t") {
      tn = "BIGINT UNSIGNED";
   }
   else if( typeName == "Bool_t") {
      tn = "BOOL";
   }
   else {
      Error("ConvertTypeName","TypeName (%s) not found",typeName.Data());
      return "";
   }

   return tn;
}

//______________________________________________________________________________
TBasket * TTreeSQL::CreateBasket(TBranch * tb)
{
   // Create a TBasketSQL

   if (fServer==0) {
      Error("CreateBasket","No TSQLServer specified");
      return 0;
   }
   vector<Int_t> *columnVec = GetColumnIndice(tb);
   return new TBasketSQL(tb->GetName(), tb->GetName(), tb,
                         &fResult, &fInsertQuery, columnVec, &fRow);
}

//______________________________________________________________________________
void TTreeSQL::CreateBranch(const TString &branchName, const TString &typeName)
{
   // Create the column(s) in the database that correspond to the branch/

   if (fServer==0) {
      Error("CreateBranch","No TSQLServer specified");
      return;
   }
   TString alterSQL = "";
   alterSQL = "";
   alterSQL = "ALTER TABLE ";
   alterSQL += fTable.Data();
   alterSQL += " ADD ";
   alterSQL += branchName.Data();;
   alterSQL += " ";
   alterSQL += typeName;
   alterSQL += " null";

   fServer->Query(alterSQL);
}

//_________________________________________________________________________
TString TTreeSQL::CreateBranches(TSQLResult * rs)
{
   // determine leaf description string

   if(!rs) return "";

   Int_t rows;
   TString type;
   TString res;
   TString branchName;
   TString leafName;
   Int_t prec=0;
   TBranch * br = 0;
   rows = rs->GetRowCount();
   TString decl;
   TString prevBranch;

   for( int i=0; i < rows; ++i ) {
      TSQLRow * row = rs->Next();
      type = row->GetField(1);
      Int_t index = type.First('(');
      if(index>0){
         prec = atoi(type(index+1,type.First(')')-1).Data());
         type = type(0,index);
      }
      branchName = row->GetField(0);
      Int_t pos;
      if ((pos=branchName.Index("__"))!=kNPOS) {
         leafName = branchName(pos+2,branchName.Length());
         branchName.Remove(pos);
      } else {
         leafName = branchName;
      }
      if (prevBranch.Length()) {
         if (prevBranch != branchName) {
            // new branch let's flush.
            if (decl.Length()) decl.Remove(decl.Length()-1);
            br = TTree::Branch(prevBranch,0,decl);
            br->ResetAddress();

            (br->GetBasketEntry())[0] = 0;
            (br->GetBasketEntry())[1] = fEntries;

            br->SetEntries(fEntries);

            br->GetListOfBaskets()->AddAtAndExpand(CreateBasket(br),0);

            prevBranch = branchName;
            decl = "";
         }
      } else {
         prevBranch = branchName;
      }

      if(type.CompareTo("varchar",TString::kIgnoreCase)==0 || type.CompareTo("char",TString::kIgnoreCase)==0 ){
         char siz[6];
         sprintf(siz,"[%d]",prec);
         decl.Append( leafName+siz+"/C:" );
      }
      else if(type.CompareTo("int",TString::kIgnoreCase)==0){
         decl.Append( leafName+"/I:" );
      }
      else if( type.CompareTo("date",TString::kIgnoreCase)==0 ||
               type.CompareTo("time",TString::kIgnoreCase)==0 ||
               type.CompareTo("timestamp",TString::kIgnoreCase)==0 ) {
         decl.Append( leafName+"/I:" );
      }
      else if(type.CompareTo("bit",TString::kIgnoreCase)==0 ||
              type.CompareTo("tinyint",TString::kIgnoreCase)==0 ||
              type.CompareTo("smallint",TString::kIgnoreCase)==0 ) {
         decl.Append( leafName+"/i:" );
      }
      else if(type.CompareTo("real",TString::kIgnoreCase)==0 || type.CompareTo("longvarchar",TString::kIgnoreCase)==0 || type.CompareTo("longvarbinary",TString::kIgnoreCase)==0 || type.CompareTo("varbinary",TString::kIgnoreCase)==0 ){
         decl.Append( leafName+"/S:" );
      }

      //   case kLONGVARCHAR: // not resolved yet how to handle
      // case kLONGVARBINARY:
      //case kVARBINARY:
      //  break;
      else /*if(type.CompareTo("bigint",TString::kIgnoreCase)==0 || type.CompareTo("decimal",TString::kIgnoreCase)==0 || type.CompareTo("numeric",TString::kIgnoreCase)==0 || type.CompareTo("double",TString::kIgnoreCase)==0 ||
      type.CompareTo("float",TString::kIgnoreCase)==0 )*/{

         decl.Append( leafName+"/F:" );
      }

   }

   // new branch let's flush.
   if (decl.Length()) decl.Remove(decl.Length()-1);
   if (prevBranch.Length()) {
      br = TTree::Branch(prevBranch,0,decl);
      br->ResetAddress();

      (br->GetBasketEntry())[0] = 0;
      (br->GetBasketEntry())[1] = fEntries;
      br->SetEntries(fEntries);
   }

   if(!res.IsNull()) res.Resize(res.Length()-1);   // cut off last ":"
   return res;
}

//______________________________________________________________________________
void TTreeSQL::CreateTable(const TString &table)
{
   // Create the database table corresponding to this TTree.

   if (fServer==0) {
      Error("CreateTable","No TSQLServer specified");
      return;
   }
   Int_t i, j;
   Int_t length;
   TString branchName, leafName, typeName;
   TString createSQL, alterSQL, str;
   Int_t nb = fBranches.GetEntriesFast();
   Int_t nl = 0;

   TBranch *branch;
   TLeaf *leaf;

   for (i=0;i<nb;i++) {
      branch = (TBranch*)fBranches.UncheckedAt(i);
      branchName = branch->GetName();
      nl = branch->GetNleaves();
      for(j=0;j<nl;j++) {
         leaf = (TLeaf*)branch->GetListOfLeaves()->UncheckedAt(j);
         leafName = leaf->GetName();
         typeName = ConvertTypeName(leaf->GetTypeName());
         length = leaf->GetLenStatic();

         if(i == 0 && j == 0) {
            createSQL = "";
            createSQL += "CREATE TABLE ";
            createSQL += table;
            createSQL += " (";
            createSQL += branchName;
            createSQL += "__";
            createSQL += leafName;
            createSQL += " ";
            createSQL += typeName;
            createSQL += " null";
            createSQL += ")";
            createSQL += ";";

            TSQLResult *sres = fServer->Query(createSQL.Data());
            if (!sres) {
               Error("CreateTable","May have failed");
            }
         }
         else {
            str = "";
            str = branchName;
            str += "__";
            str += leafName;
            CreateBranch(str, typeName);
         } //else
      }  // inner for loop
   } // outer for loop
   // retrieve table to initialize fResult
   delete fResult;
   fResult = fServer->Query(fQuery.Data());
}

//______________________________________________________________________________
void TTreeSQL::Init()
{
   // Initializeation routine

   fCurrentEntry = -1;

   GetEntries();

   delete fResult;
   fResult = fServer->Query(fQuery.Data());
   if(!fResult) return;

   CreateBranches(fServer->GetColumns(fDB,fTable));
}

//______________________________________________________________________________
Int_t TTreeSQL::Fill()
{
   // Copy the information from the user object to the TTree

   Int_t nb = fBranches.GetEntriesFast();
   TString typeName;
   TBranch *branch;

   if (fServer==0) return 0;

   if(!CheckTable(fTable.Data())) {
      CreateTable(fTable.Data());
   }

   PrepEntry(fEntries);

   for (int i=0;i<nb;i++) {
      branch = (TBranch*)fBranches.UncheckedAt(i);
      CheckBasket(branch);
   }

   if (!fBranchChecked) {
      for(int i=0;i<nb;i++) {
         branch = (TBranch*)fBranches.UncheckedAt(i);
         if (!CheckBranch(branch)) {
            Error("Fill","CheckBranch for %s failed",branch->GetName());
         }
      }
      fBranchChecked = kTRUE;
   }
   ResetQuery();

   TTree::Fill();

   fInsertQuery.Remove(fInsertQuery.Length()-1);
   fInsertQuery += ");";
   TSQLResult *res = fServer?fServer->Query(fInsertQuery):0;

   return res->GetRowCount();
}

//______________________________________________________________________________
vector<Int_t> *TTreeSQL::GetColumnIndice(TBranch *branch)
{
   // Return a vector of columns index corresponding to the
   // current SQL table and the branch given as argument
   // Returns 0 if no columns indices is found
   // Otherwise returns a pointer to a vector to be deleted by the caller

   if (!CheckTable(fTable)) return 0;

   vector<Int_t> *columns = new vector<Int_t>;

   Int_t nl = branch->GetNleaves();

   vector<TString> names;

   TSQLResult *rs = fServer->GetColumns(fDB,fTable);
   if (rs==0) { delete columns; return 0; }
   Int_t rows = rs->GetRowCount();

   pair<TString,Int_t> value;

   for (Int_t i=0;i<rows;++i) {
      TSQLRow *row = rs->Next();
      names.push_back( row->GetField(0) );
      delete row;
   }
   delete rs;

   for(int j=0;j<nl;j++) {

      Int_t col = -1;
      TLeaf *leaf = (TLeaf*)branch->GetListOfLeaves()->UncheckedAt(j);
      TString leafName = leaf->GetName();
      TString str;

      if (leafName != branch->GetName()) {
         str = "";
         str = branch->GetName();
         str += "__";
         str += leafName;
      } else {
         str = leafName;
      }
      for (Int_t i=0;i<rows;++i) {
         if (str == names[i]) {
            col = i;
            break;
         }
      }
      if(col>=0){
         columns->push_back(col);
      } else Error("GetColumnIndice","Error finding column %d %s",j,str.Data());
   }
   if (columns->empty()) {
      delete columns; return 0;
   } else
      return columns;
}

//______________________________________________________________________________
Long64_t  TTreeSQL::GetEntries() const
{
   // Get the number of rows in the database

   if (fServer==0) return GetEntriesFast();
   if (!CheckTable(fTable.Data())) return 0;

   TTreeSQL* thisvar = (TTreeSQL*)this;

   // What if the user already started to call GetEntry
   // What about the initial value of fEntries is it really 0?

   TString counting = "select count(*) from " + fTable;
   TSQLResult *count = fServer->Query(counting);

   if (count==0) {
      thisvar->fEntries = 0;
   } else {
      TString val = count->Next()->GetField(0);
      Long_t ret;
      sscanf(val.Data(), "%ld",&(ret) );
      thisvar->fEntries = ret;
   }
   return fEntries;
}

//______________________________________________________________________________
Long64_t  TTreeSQL::GetEntriesFast()    const
{
   // Return the number of entries as of the last check.
   // Use GetEntries for a more accurate count.

   return fEntries;
}

//______________________________________________________________________________
Int_t TTreeSQL::GetEntry(Long64_t entry, Int_t getall)
{
   // Load the data for the entry from the database.

   if (PrepEntry(entry)>=0) return TTree::GetEntry(entry,getall);
   else return -1;
}

//______________________________________________________________________________
Long64_t TTreeSQL::LoadTree(Long64_t entry)
{
   // Setup the tree to the load the specified entry.

   fReadEntry = entry;
   return PrepEntry(entry);
}

//______________________________________________________________________________
Long64_t TTreeSQL::PrepEntry(Long64_t entry)
{
   // Make sure the server and result set are setup for the requested entry

   if (entry < 0 || entry >= fEntries || fServer==0) return 0;
   fReadEntry = entry;

   if(entry == fCurrentEntry) return entry;

   if(entry < fCurrentEntry || fResult==0){
      delete fResult;
      fResult = fServer->Query(fQuery.Data());
      fCurrentEntry = -1;
   }

   Bool_t reset = false;
   while ( fCurrentEntry < entry ) {
      ++fCurrentEntry;
      delete fRow;
      fRow = fResult->Next();
      if (fRow==0 && !reset) {
         delete fResult;
         fResult = fServer->Query(fQuery.Data());
         fCurrentEntry = -1;
         reset = true;
      }
   }
   if (fRow==0) return -1;
   return entry;
}

//______________________________________________________________________________
// void TTreeSQL::LoadNumberEntries()
// {
//    R__ASSERT(0);

//    fResult =    fServer->Query(fQuery.Data());
//    fEntries=0;

//    while(fResult->Next()){
//       fEntries++;
//    }
//    fResult =    fServer->Query(fQuery.Data());
// }

//______________________________________________________________________________
void TTreeSQL::Refresh()
{
   //  Refresh contents of this Tree and his branches from the current
   //  Tree status in the database
   //  One can call this function in case the Tree on its file is being
   //  updated by another process

   // Note : something to be done?
   GetEntries(); // Re-load the number of entries
   fCurrentEntry = -1;
   delete fResult; fResult = 0;
   delete fRow; fRow = 0;
}

//______________________________________________________________________________
void TTreeSQL::ResetQuery()
{
   // Reset the internal query

   fInsertQuery = "INSERT INTO " + fTable + " VALUES (";
}


 TTreeSQL.cxx:1
 TTreeSQL.cxx:2
 TTreeSQL.cxx:3
 TTreeSQL.cxx:4
 TTreeSQL.cxx:5
 TTreeSQL.cxx:6
 TTreeSQL.cxx:7
 TTreeSQL.cxx:8
 TTreeSQL.cxx:9
 TTreeSQL.cxx:10
 TTreeSQL.cxx:11
 TTreeSQL.cxx:12
 TTreeSQL.cxx:13
 TTreeSQL.cxx:14
 TTreeSQL.cxx:15
 TTreeSQL.cxx:16
 TTreeSQL.cxx:17
 TTreeSQL.cxx:18
 TTreeSQL.cxx:19
 TTreeSQL.cxx:20
 TTreeSQL.cxx:21
 TTreeSQL.cxx:22
 TTreeSQL.cxx:23
 TTreeSQL.cxx:24
 TTreeSQL.cxx:25
 TTreeSQL.cxx:26
 TTreeSQL.cxx:27
 TTreeSQL.cxx:28
 TTreeSQL.cxx:29
 TTreeSQL.cxx:30
 TTreeSQL.cxx:31
 TTreeSQL.cxx:32
 TTreeSQL.cxx:33
 TTreeSQL.cxx:34
 TTreeSQL.cxx:35
 TTreeSQL.cxx:36
 TTreeSQL.cxx:37
 TTreeSQL.cxx:38
 TTreeSQL.cxx:39
 TTreeSQL.cxx:40
 TTreeSQL.cxx:41
 TTreeSQL.cxx:42
 TTreeSQL.cxx:43
 TTreeSQL.cxx:44
 TTreeSQL.cxx:45
 TTreeSQL.cxx:46
 TTreeSQL.cxx:47
 TTreeSQL.cxx:48
 TTreeSQL.cxx:49
 TTreeSQL.cxx:50
 TTreeSQL.cxx:51
 TTreeSQL.cxx:52
 TTreeSQL.cxx:53
 TTreeSQL.cxx:54
 TTreeSQL.cxx:55
 TTreeSQL.cxx:56
 TTreeSQL.cxx:57
 TTreeSQL.cxx:58
 TTreeSQL.cxx:59
 TTreeSQL.cxx:60
 TTreeSQL.cxx:61
 TTreeSQL.cxx:62
 TTreeSQL.cxx:63
 TTreeSQL.cxx:64
 TTreeSQL.cxx:65
 TTreeSQL.cxx:66
 TTreeSQL.cxx:67
 TTreeSQL.cxx:68
 TTreeSQL.cxx:69
 TTreeSQL.cxx:70
 TTreeSQL.cxx:71
 TTreeSQL.cxx:72
 TTreeSQL.cxx:73
 TTreeSQL.cxx:74
 TTreeSQL.cxx:75
 TTreeSQL.cxx:76
 TTreeSQL.cxx:77
 TTreeSQL.cxx:78
 TTreeSQL.cxx:79
 TTreeSQL.cxx:80
 TTreeSQL.cxx:81
 TTreeSQL.cxx:82
 TTreeSQL.cxx:83
 TTreeSQL.cxx:84
 TTreeSQL.cxx:85
 TTreeSQL.cxx:86
 TTreeSQL.cxx:87
 TTreeSQL.cxx:88
 TTreeSQL.cxx:89
 TTreeSQL.cxx:90
 TTreeSQL.cxx:91
 TTreeSQL.cxx:92
 TTreeSQL.cxx:93
 TTreeSQL.cxx:94
 TTreeSQL.cxx:95
 TTreeSQL.cxx:96
 TTreeSQL.cxx:97
 TTreeSQL.cxx:98
 TTreeSQL.cxx:99
 TTreeSQL.cxx:100
 TTreeSQL.cxx:101
 TTreeSQL.cxx:102
 TTreeSQL.cxx:103
 TTreeSQL.cxx:104
 TTreeSQL.cxx:105
 TTreeSQL.cxx:106
 TTreeSQL.cxx:107
 TTreeSQL.cxx:108
 TTreeSQL.cxx:109
 TTreeSQL.cxx:110
 TTreeSQL.cxx:111
 TTreeSQL.cxx:112
 TTreeSQL.cxx:113
 TTreeSQL.cxx:114
 TTreeSQL.cxx:115
 TTreeSQL.cxx:116
 TTreeSQL.cxx:117
 TTreeSQL.cxx:118
 TTreeSQL.cxx:119
 TTreeSQL.cxx:120
 TTreeSQL.cxx:121
 TTreeSQL.cxx:122
 TTreeSQL.cxx:123
 TTreeSQL.cxx:124
 TTreeSQL.cxx:125
 TTreeSQL.cxx:126
 TTreeSQL.cxx:127
 TTreeSQL.cxx:128
 TTreeSQL.cxx:129
 TTreeSQL.cxx:130
 TTreeSQL.cxx:131
 TTreeSQL.cxx:132
 TTreeSQL.cxx:133
 TTreeSQL.cxx:134
 TTreeSQL.cxx:135
 TTreeSQL.cxx:136
 TTreeSQL.cxx:137
 TTreeSQL.cxx:138
 TTreeSQL.cxx:139
 TTreeSQL.cxx:140
 TTreeSQL.cxx:141
 TTreeSQL.cxx:142
 TTreeSQL.cxx:143
 TTreeSQL.cxx:144
 TTreeSQL.cxx:145
 TTreeSQL.cxx:146
 TTreeSQL.cxx:147
 TTreeSQL.cxx:148
 TTreeSQL.cxx:149
 TTreeSQL.cxx:150
 TTreeSQL.cxx:151
 TTreeSQL.cxx:152
 TTreeSQL.cxx:153
 TTreeSQL.cxx:154
 TTreeSQL.cxx:155
 TTreeSQL.cxx:156
 TTreeSQL.cxx:157
 TTreeSQL.cxx:158
 TTreeSQL.cxx:159
 TTreeSQL.cxx:160
 TTreeSQL.cxx:161
 TTreeSQL.cxx:162
 TTreeSQL.cxx:163
 TTreeSQL.cxx:164
 TTreeSQL.cxx:165
 TTreeSQL.cxx:166
 TTreeSQL.cxx:167
 TTreeSQL.cxx:168
 TTreeSQL.cxx:169
 TTreeSQL.cxx:170
 TTreeSQL.cxx:171
 TTreeSQL.cxx:172
 TTreeSQL.cxx:173
 TTreeSQL.cxx:174
 TTreeSQL.cxx:175
 TTreeSQL.cxx:176
 TTreeSQL.cxx:177
 TTreeSQL.cxx:178
 TTreeSQL.cxx:179
 TTreeSQL.cxx:180
 TTreeSQL.cxx:181
 TTreeSQL.cxx:182
 TTreeSQL.cxx:183
 TTreeSQL.cxx:184
 TTreeSQL.cxx:185
 TTreeSQL.cxx:186
 TTreeSQL.cxx:187
 TTreeSQL.cxx:188
 TTreeSQL.cxx:189
 TTreeSQL.cxx:190
 TTreeSQL.cxx:191
 TTreeSQL.cxx:192
 TTreeSQL.cxx:193
 TTreeSQL.cxx:194
 TTreeSQL.cxx:195
 TTreeSQL.cxx:196
 TTreeSQL.cxx:197
 TTreeSQL.cxx:198
 TTreeSQL.cxx:199
 TTreeSQL.cxx:200
 TTreeSQL.cxx:201
 TTreeSQL.cxx:202
 TTreeSQL.cxx:203
 TTreeSQL.cxx:204
 TTreeSQL.cxx:205
 TTreeSQL.cxx:206
 TTreeSQL.cxx:207
 TTreeSQL.cxx:208
 TTreeSQL.cxx:209
 TTreeSQL.cxx:210
 TTreeSQL.cxx:211
 TTreeSQL.cxx:212
 TTreeSQL.cxx:213
 TTreeSQL.cxx:214
 TTreeSQL.cxx:215
 TTreeSQL.cxx:216
 TTreeSQL.cxx:217
 TTreeSQL.cxx:218
 TTreeSQL.cxx:219
 TTreeSQL.cxx:220
 TTreeSQL.cxx:221
 TTreeSQL.cxx:222
 TTreeSQL.cxx:223
 TTreeSQL.cxx:224
 TTreeSQL.cxx:225
 TTreeSQL.cxx:226
 TTreeSQL.cxx:227
 TTreeSQL.cxx:228
 TTreeSQL.cxx:229
 TTreeSQL.cxx:230
 TTreeSQL.cxx:231
 TTreeSQL.cxx:232
 TTreeSQL.cxx:233
 TTreeSQL.cxx:234
 TTreeSQL.cxx:235
 TTreeSQL.cxx:236
 TTreeSQL.cxx:237
 TTreeSQL.cxx:238
 TTreeSQL.cxx:239
 TTreeSQL.cxx:240
 TTreeSQL.cxx:241
 TTreeSQL.cxx:242
 TTreeSQL.cxx:243
 TTreeSQL.cxx:244
 TTreeSQL.cxx:245
 TTreeSQL.cxx:246
 TTreeSQL.cxx:247
 TTreeSQL.cxx:248
 TTreeSQL.cxx:249
 TTreeSQL.cxx:250
 TTreeSQL.cxx:251
 TTreeSQL.cxx:252
 TTreeSQL.cxx:253
 TTreeSQL.cxx:254
 TTreeSQL.cxx:255
 TTreeSQL.cxx:256
 TTreeSQL.cxx:257
 TTreeSQL.cxx:258
 TTreeSQL.cxx:259
 TTreeSQL.cxx:260
 TTreeSQL.cxx:261
 TTreeSQL.cxx:262
 TTreeSQL.cxx:263
 TTreeSQL.cxx:264
 TTreeSQL.cxx:265
 TTreeSQL.cxx:266
 TTreeSQL.cxx:267
 TTreeSQL.cxx:268
 TTreeSQL.cxx:269
 TTreeSQL.cxx:270
 TTreeSQL.cxx:271
 TTreeSQL.cxx:272
 TTreeSQL.cxx:273
 TTreeSQL.cxx:274
 TTreeSQL.cxx:275
 TTreeSQL.cxx:276
 TTreeSQL.cxx:277
 TTreeSQL.cxx:278
 TTreeSQL.cxx:279
 TTreeSQL.cxx:280
 TTreeSQL.cxx:281
 TTreeSQL.cxx:282
 TTreeSQL.cxx:283
 TTreeSQL.cxx:284
 TTreeSQL.cxx:285
 TTreeSQL.cxx:286
 TTreeSQL.cxx:287
 TTreeSQL.cxx:288
 TTreeSQL.cxx:289
 TTreeSQL.cxx:290
 TTreeSQL.cxx:291
 TTreeSQL.cxx:292
 TTreeSQL.cxx:293
 TTreeSQL.cxx:294
 TTreeSQL.cxx:295
 TTreeSQL.cxx:296
 TTreeSQL.cxx:297
 TTreeSQL.cxx:298
 TTreeSQL.cxx:299
 TTreeSQL.cxx:300
 TTreeSQL.cxx:301
 TTreeSQL.cxx:302
 TTreeSQL.cxx:303
 TTreeSQL.cxx:304
 TTreeSQL.cxx:305
 TTreeSQL.cxx:306
 TTreeSQL.cxx:307
 TTreeSQL.cxx:308
 TTreeSQL.cxx:309
 TTreeSQL.cxx:310
 TTreeSQL.cxx:311
 TTreeSQL.cxx:312
 TTreeSQL.cxx:313
 TTreeSQL.cxx:314
 TTreeSQL.cxx:315
 TTreeSQL.cxx:316
 TTreeSQL.cxx:317
 TTreeSQL.cxx:318
 TTreeSQL.cxx:319
 TTreeSQL.cxx:320
 TTreeSQL.cxx:321
 TTreeSQL.cxx:322
 TTreeSQL.cxx:323
 TTreeSQL.cxx:324
 TTreeSQL.cxx:325
 TTreeSQL.cxx:326
 TTreeSQL.cxx:327
 TTreeSQL.cxx:328
 TTreeSQL.cxx:329
 TTreeSQL.cxx:330
 TTreeSQL.cxx:331
 TTreeSQL.cxx:332
 TTreeSQL.cxx:333
 TTreeSQL.cxx:334
 TTreeSQL.cxx:335
 TTreeSQL.cxx:336
 TTreeSQL.cxx:337
 TTreeSQL.cxx:338
 TTreeSQL.cxx:339
 TTreeSQL.cxx:340
 TTreeSQL.cxx:341
 TTreeSQL.cxx:342
 TTreeSQL.cxx:343
 TTreeSQL.cxx:344
 TTreeSQL.cxx:345
 TTreeSQL.cxx:346
 TTreeSQL.cxx:347
 TTreeSQL.cxx:348
 TTreeSQL.cxx:349
 TTreeSQL.cxx:350
 TTreeSQL.cxx:351
 TTreeSQL.cxx:352
 TTreeSQL.cxx:353
 TTreeSQL.cxx:354
 TTreeSQL.cxx:355
 TTreeSQL.cxx:356
 TTreeSQL.cxx:357
 TTreeSQL.cxx:358
 TTreeSQL.cxx:359
 TTreeSQL.cxx:360
 TTreeSQL.cxx:361
 TTreeSQL.cxx:362
 TTreeSQL.cxx:363
 TTreeSQL.cxx:364
 TTreeSQL.cxx:365
 TTreeSQL.cxx:366
 TTreeSQL.cxx:367
 TTreeSQL.cxx:368
 TTreeSQL.cxx:369
 TTreeSQL.cxx:370
 TTreeSQL.cxx:371
 TTreeSQL.cxx:372
 TTreeSQL.cxx:373
 TTreeSQL.cxx:374
 TTreeSQL.cxx:375
 TTreeSQL.cxx:376
 TTreeSQL.cxx:377
 TTreeSQL.cxx:378
 TTreeSQL.cxx:379
 TTreeSQL.cxx:380
 TTreeSQL.cxx:381
 TTreeSQL.cxx:382
 TTreeSQL.cxx:383
 TTreeSQL.cxx:384
 TTreeSQL.cxx:385
 TTreeSQL.cxx:386
 TTreeSQL.cxx:387
 TTreeSQL.cxx:388
 TTreeSQL.cxx:389
 TTreeSQL.cxx:390
 TTreeSQL.cxx:391
 TTreeSQL.cxx:392
 TTreeSQL.cxx:393
 TTreeSQL.cxx:394
 TTreeSQL.cxx:395
 TTreeSQL.cxx:396
 TTreeSQL.cxx:397
 TTreeSQL.cxx:398
 TTreeSQL.cxx:399
 TTreeSQL.cxx:400
 TTreeSQL.cxx:401
 TTreeSQL.cxx:402
 TTreeSQL.cxx:403
 TTreeSQL.cxx:404
 TTreeSQL.cxx:405
 TTreeSQL.cxx:406
 TTreeSQL.cxx:407
 TTreeSQL.cxx:408
 TTreeSQL.cxx:409
 TTreeSQL.cxx:410
 TTreeSQL.cxx:411
 TTreeSQL.cxx:412
 TTreeSQL.cxx:413
 TTreeSQL.cxx:414
 TTreeSQL.cxx:415
 TTreeSQL.cxx:416
 TTreeSQL.cxx:417
 TTreeSQL.cxx:418
 TTreeSQL.cxx:419
 TTreeSQL.cxx:420
 TTreeSQL.cxx:421
 TTreeSQL.cxx:422
 TTreeSQL.cxx:423
 TTreeSQL.cxx:424
 TTreeSQL.cxx:425
 TTreeSQL.cxx:426
 TTreeSQL.cxx:427
 TTreeSQL.cxx:428
 TTreeSQL.cxx:429
 TTreeSQL.cxx:430
 TTreeSQL.cxx:431
 TTreeSQL.cxx:432
 TTreeSQL.cxx:433
 TTreeSQL.cxx:434
 TTreeSQL.cxx:435
 TTreeSQL.cxx:436
 TTreeSQL.cxx:437
 TTreeSQL.cxx:438
 TTreeSQL.cxx:439
 TTreeSQL.cxx:440
 TTreeSQL.cxx:441
 TTreeSQL.cxx:442
 TTreeSQL.cxx:443
 TTreeSQL.cxx:444
 TTreeSQL.cxx:445
 TTreeSQL.cxx:446
 TTreeSQL.cxx:447
 TTreeSQL.cxx:448
 TTreeSQL.cxx:449
 TTreeSQL.cxx:450
 TTreeSQL.cxx:451
 TTreeSQL.cxx:452
 TTreeSQL.cxx:453
 TTreeSQL.cxx:454
 TTreeSQL.cxx:455
 TTreeSQL.cxx:456
 TTreeSQL.cxx:457
 TTreeSQL.cxx:458
 TTreeSQL.cxx:459
 TTreeSQL.cxx:460
 TTreeSQL.cxx:461
 TTreeSQL.cxx:462
 TTreeSQL.cxx:463
 TTreeSQL.cxx:464
 TTreeSQL.cxx:465
 TTreeSQL.cxx:466
 TTreeSQL.cxx:467
 TTreeSQL.cxx:468
 TTreeSQL.cxx:469
 TTreeSQL.cxx:470
 TTreeSQL.cxx:471
 TTreeSQL.cxx:472
 TTreeSQL.cxx:473
 TTreeSQL.cxx:474
 TTreeSQL.cxx:475
 TTreeSQL.cxx:476
 TTreeSQL.cxx:477
 TTreeSQL.cxx:478
 TTreeSQL.cxx:479
 TTreeSQL.cxx:480
 TTreeSQL.cxx:481
 TTreeSQL.cxx:482
 TTreeSQL.cxx:483
 TTreeSQL.cxx:484
 TTreeSQL.cxx:485
 TTreeSQL.cxx:486
 TTreeSQL.cxx:487
 TTreeSQL.cxx:488
 TTreeSQL.cxx:489
 TTreeSQL.cxx:490
 TTreeSQL.cxx:491
 TTreeSQL.cxx:492
 TTreeSQL.cxx:493
 TTreeSQL.cxx:494
 TTreeSQL.cxx:495
 TTreeSQL.cxx:496
 TTreeSQL.cxx:497
 TTreeSQL.cxx:498
 TTreeSQL.cxx:499
 TTreeSQL.cxx:500
 TTreeSQL.cxx:501
 TTreeSQL.cxx:502
 TTreeSQL.cxx:503
 TTreeSQL.cxx:504
 TTreeSQL.cxx:505
 TTreeSQL.cxx:506
 TTreeSQL.cxx:507
 TTreeSQL.cxx:508
 TTreeSQL.cxx:509
 TTreeSQL.cxx:510
 TTreeSQL.cxx:511
 TTreeSQL.cxx:512
 TTreeSQL.cxx:513
 TTreeSQL.cxx:514
 TTreeSQL.cxx:515
 TTreeSQL.cxx:516
 TTreeSQL.cxx:517
 TTreeSQL.cxx:518
 TTreeSQL.cxx:519
 TTreeSQL.cxx:520
 TTreeSQL.cxx:521
 TTreeSQL.cxx:522
 TTreeSQL.cxx:523
 TTreeSQL.cxx:524
 TTreeSQL.cxx:525
 TTreeSQL.cxx:526
 TTreeSQL.cxx:527
 TTreeSQL.cxx:528
 TTreeSQL.cxx:529
 TTreeSQL.cxx:530
 TTreeSQL.cxx:531
 TTreeSQL.cxx:532
 TTreeSQL.cxx:533
 TTreeSQL.cxx:534
 TTreeSQL.cxx:535
 TTreeSQL.cxx:536
 TTreeSQL.cxx:537
 TTreeSQL.cxx:538
 TTreeSQL.cxx:539
 TTreeSQL.cxx:540
 TTreeSQL.cxx:541
 TTreeSQL.cxx:542
 TTreeSQL.cxx:543
 TTreeSQL.cxx:544
 TTreeSQL.cxx:545
 TTreeSQL.cxx:546
 TTreeSQL.cxx:547
 TTreeSQL.cxx:548
 TTreeSQL.cxx:549
 TTreeSQL.cxx:550
 TTreeSQL.cxx:551
 TTreeSQL.cxx:552
 TTreeSQL.cxx:553
 TTreeSQL.cxx:554
 TTreeSQL.cxx:555
 TTreeSQL.cxx:556
 TTreeSQL.cxx:557
 TTreeSQL.cxx:558
 TTreeSQL.cxx:559
 TTreeSQL.cxx:560
 TTreeSQL.cxx:561
 TTreeSQL.cxx:562
 TTreeSQL.cxx:563
 TTreeSQL.cxx:564
 TTreeSQL.cxx:565
 TTreeSQL.cxx:566
 TTreeSQL.cxx:567
 TTreeSQL.cxx:568
 TTreeSQL.cxx:569
 TTreeSQL.cxx:570
 TTreeSQL.cxx:571
 TTreeSQL.cxx:572
 TTreeSQL.cxx:573
 TTreeSQL.cxx:574
 TTreeSQL.cxx:575
 TTreeSQL.cxx:576
 TTreeSQL.cxx:577
 TTreeSQL.cxx:578
 TTreeSQL.cxx:579
 TTreeSQL.cxx:580
 TTreeSQL.cxx:581
 TTreeSQL.cxx:582
 TTreeSQL.cxx:583
 TTreeSQL.cxx:584
 TTreeSQL.cxx:585
 TTreeSQL.cxx:586
 TTreeSQL.cxx:587
 TTreeSQL.cxx:588
 TTreeSQL.cxx:589
 TTreeSQL.cxx:590
 TTreeSQL.cxx:591
 TTreeSQL.cxx:592
 TTreeSQL.cxx:593
 TTreeSQL.cxx:594
 TTreeSQL.cxx:595
 TTreeSQL.cxx:596
 TTreeSQL.cxx:597
 TTreeSQL.cxx:598
 TTreeSQL.cxx:599
 TTreeSQL.cxx:600
 TTreeSQL.cxx:601
 TTreeSQL.cxx:602
 TTreeSQL.cxx:603
 TTreeSQL.cxx:604
 TTreeSQL.cxx:605
 TTreeSQL.cxx:606
 TTreeSQL.cxx:607
 TTreeSQL.cxx:608
 TTreeSQL.cxx:609
 TTreeSQL.cxx:610
 TTreeSQL.cxx:611
 TTreeSQL.cxx:612
 TTreeSQL.cxx:613
 TTreeSQL.cxx:614
 TTreeSQL.cxx:615
 TTreeSQL.cxx:616
 TTreeSQL.cxx:617
 TTreeSQL.cxx:618
 TTreeSQL.cxx:619
 TTreeSQL.cxx:620
 TTreeSQL.cxx:621
 TTreeSQL.cxx:622
 TTreeSQL.cxx:623
 TTreeSQL.cxx:624
 TTreeSQL.cxx:625
 TTreeSQL.cxx:626
 TTreeSQL.cxx:627
 TTreeSQL.cxx:628
 TTreeSQL.cxx:629
 TTreeSQL.cxx:630
 TTreeSQL.cxx:631
 TTreeSQL.cxx:632
 TTreeSQL.cxx:633
 TTreeSQL.cxx:634
 TTreeSQL.cxx:635
 TTreeSQL.cxx:636
 TTreeSQL.cxx:637
 TTreeSQL.cxx:638
 TTreeSQL.cxx:639
 TTreeSQL.cxx:640
 TTreeSQL.cxx:641
 TTreeSQL.cxx:642
 TTreeSQL.cxx:643
 TTreeSQL.cxx:644
 TTreeSQL.cxx:645
 TTreeSQL.cxx:646
 TTreeSQL.cxx:647
 TTreeSQL.cxx:648
 TTreeSQL.cxx:649
 TTreeSQL.cxx:650
 TTreeSQL.cxx:651
 TTreeSQL.cxx:652
 TTreeSQL.cxx:653
 TTreeSQL.cxx:654
 TTreeSQL.cxx:655
 TTreeSQL.cxx:656
 TTreeSQL.cxx:657
 TTreeSQL.cxx:658
 TTreeSQL.cxx:659
 TTreeSQL.cxx:660
 TTreeSQL.cxx:661
 TTreeSQL.cxx:662
 TTreeSQL.cxx:663
 TTreeSQL.cxx:664
 TTreeSQL.cxx:665
 TTreeSQL.cxx:666
 TTreeSQL.cxx:667
 TTreeSQL.cxx:668
 TTreeSQL.cxx:669
 TTreeSQL.cxx:670
 TTreeSQL.cxx:671
 TTreeSQL.cxx:672
 TTreeSQL.cxx:673
 TTreeSQL.cxx:674
 TTreeSQL.cxx:675
 TTreeSQL.cxx:676
 TTreeSQL.cxx:677
 TTreeSQL.cxx:678
 TTreeSQL.cxx:679
 TTreeSQL.cxx:680
 TTreeSQL.cxx:681
 TTreeSQL.cxx:682
 TTreeSQL.cxx:683
 TTreeSQL.cxx:684
 TTreeSQL.cxx:685
 TTreeSQL.cxx:686
 TTreeSQL.cxx:687
 TTreeSQL.cxx:688
 TTreeSQL.cxx:689
 TTreeSQL.cxx:690
 TTreeSQL.cxx:691
 TTreeSQL.cxx:692
 TTreeSQL.cxx:693
 TTreeSQL.cxx:694
 TTreeSQL.cxx:695
 TTreeSQL.cxx:696
 TTreeSQL.cxx:697
 TTreeSQL.cxx:698
 TTreeSQL.cxx:699
 TTreeSQL.cxx:700
 TTreeSQL.cxx:701
 TTreeSQL.cxx:702
 TTreeSQL.cxx:703
 TTreeSQL.cxx:704
 TTreeSQL.cxx:705
 TTreeSQL.cxx:706
 TTreeSQL.cxx:707
 TTreeSQL.cxx:708
 TTreeSQL.cxx:709
 TTreeSQL.cxx:710
 TTreeSQL.cxx:711
 TTreeSQL.cxx:712
 TTreeSQL.cxx:713
 TTreeSQL.cxx:714
 TTreeSQL.cxx:715
 TTreeSQL.cxx:716
 TTreeSQL.cxx:717
 TTreeSQL.cxx:718
 TTreeSQL.cxx:719
 TTreeSQL.cxx:720
 TTreeSQL.cxx:721
 TTreeSQL.cxx:722
 TTreeSQL.cxx:723
 TTreeSQL.cxx:724
 TTreeSQL.cxx:725
 TTreeSQL.cxx:726
 TTreeSQL.cxx:727
 TTreeSQL.cxx:728
 TTreeSQL.cxx:729
 TTreeSQL.cxx:730
 TTreeSQL.cxx:731
 TTreeSQL.cxx:732
 TTreeSQL.cxx:733
 TTreeSQL.cxx:734
 TTreeSQL.cxx:735
 TTreeSQL.cxx:736
 TTreeSQL.cxx:737
 TTreeSQL.cxx:738
 TTreeSQL.cxx:739
 TTreeSQL.cxx:740
 TTreeSQL.cxx:741
 TTreeSQL.cxx:742
 TTreeSQL.cxx:743
 TTreeSQL.cxx:744
 TTreeSQL.cxx:745
 TTreeSQL.cxx:746
 TTreeSQL.cxx:747
 TTreeSQL.cxx:748
 TTreeSQL.cxx:749
 TTreeSQL.cxx:750
 TTreeSQL.cxx:751
 TTreeSQL.cxx:752
 TTreeSQL.cxx:753
 TTreeSQL.cxx:754
 TTreeSQL.cxx:755
 TTreeSQL.cxx:756
 TTreeSQL.cxx:757
 TTreeSQL.cxx:758
 TTreeSQL.cxx:759
 TTreeSQL.cxx:760
 TTreeSQL.cxx:761
 TTreeSQL.cxx:762
 TTreeSQL.cxx:763
 TTreeSQL.cxx:764
 TTreeSQL.cxx:765
 TTreeSQL.cxx:766
 TTreeSQL.cxx:767
 TTreeSQL.cxx:768