// @(#)root/sql:$Id$
// Author: Sergey Linev  20/11/2005

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

//________________________________________________________________________
//
// TKeySQL is represents a metainforamtion about object, which was written to
// SQL database. It keeps object id, which used to locate object data
// from database tables.
//________________________________________________________________________


#include "TKeySQL.h"

#include "TROOT.h"
#include "TClass.h"
#include "TBrowser.h"
#include "Riostream.h"

#include "TSQLResult.h"
#include "TBufferSQL2.h"
#include "TSQLStructure.h"
#include "TSQLFile.h"
#include <stdlib.h>

ClassImp(TKeySQL);

//______________________________________________________________________________
TKeySQL::TKeySQL() :
   TKey(),
   fKeyId(-1),
   fObjId(-1)
{
   // default constructor
}

//______________________________________________________________________________
TKeySQL::TKeySQL(TDirectory* mother, const TObject* obj, const char* name, const char* title) :
    TKey(mother),
    fKeyId(-1),
    fObjId(-1)
{
   // Creates TKeySQL and convert obj data to TSQLStructure via TBufferSQL2

   if (name) SetName(name); else
      if (obj!=0) {SetName(obj->GetName());  fClassName=obj->ClassName();}
      else SetName("Noname");
      
   if (title) SetTitle(title);

   StoreKeyObject((void*)obj, obj ? obj->IsA() : 0);
}

//______________________________________________________________________________
TKeySQL::TKeySQL(TDirectory* mother, const void* obj, const TClass* cl, const char* name, const char* title) :
    TKey(mother),
    fKeyId(-1),
    fObjId(-1)
{
   // Creates TKeySQL and convert obj data to TSQLStructure via TBufferSQL2

   if (name && *name) SetName(name);
   else SetName(cl ? cl->GetName() : "Noname");

   if (title) SetTitle(title);

   StoreKeyObject(obj, cl);
}

//______________________________________________________________________________
TKeySQL::TKeySQL(TDirectory* mother, Long64_t keyid, Long64_t objid, 
                 const char* name, const char* title,
                 const char* keydatetime, Int_t cycle, const char* classname) :
    TKey(mother),
    fKeyId(keyid),
    fObjId(objid)
{
   // Create TKeySQL object, which correponds to single entry in keys table

   SetName(name);
   if (title) SetTitle(title);
   TDatime dt(keydatetime);
   fDatime = dt;
   fCycle = cycle;
   fClassName = classname;
}

//______________________________________________________________________________
TKeySQL::~TKeySQL()
{
// TKeySQL destructor
}

//______________________________________________________________________________
Bool_t TKeySQL::IsKeyModified(const char* keyname, const char* keytitle, const char* keydatime, Int_t cycle, const char* classname)
{
// Compares keydata with provided and return kTRUE if key was modified
// Used in TFile::StreamKeysForDirectory() method to verify data for that keys
// should be updated
  
   Int_t len1 = (GetName()==0) ? 0 : strlen(GetName());
   Int_t len2 = (keyname==0) ? 0 : strlen(keyname);
   if (len1!=len2) return kTRUE;
   if ((len1>0) && (strcmp(GetName(), keyname)!=0)) return kTRUE;
  
   len1 = (GetTitle()==0) ? 0 : strlen(GetTitle());
   len2 = (keytitle==0) ? 0 : strlen(keytitle);
   if (len1!=len2) return kTRUE;
   if ((len1>0) && (strcmp(GetTitle(), keytitle)!=0)) return kTRUE;

   const char* tm = GetDatime().AsSQLString();
   len1 = (tm==0) ? 0 : strlen(tm);
   len2 = (keydatime==0) ? 0 : strlen(keydatime);
   if (len1!=len2) return kTRUE;
   if ((len1>0) && (strcmp(tm, keydatime)!=0)) return kTRUE;
  
   if (cycle!=GetCycle()) return kTRUE;

   len1 = (GetClassName()==0) ? 0 : strlen(GetClassName());
   len2 = (classname==0) ? 0 : strlen(classname);
   if (len1!=len2) return kTRUE;
   if ((len1>0) && (strcmp(GetClassName(), classname)!=0)) return kTRUE;
      
   return kFALSE;
}

//______________________________________________________________________________
void TKeySQL::Delete(Option_t * /*option*/)
{
// Removes key from current directory
// Note: TKeySQL object is not deleted. You still have to call "delete key"

   TSQLFile* f = (TSQLFile*) GetFile(); 

   if (f!=0)
      f->DeleteKeyFromDB(GetDBKeyId());

   fMotherDir->GetListOfKeys()->Remove(this);
}

//______________________________________________________________________________
Long64_t TKeySQL::GetDBDirId() const
{
   // return sql id of parent directory
   
   return GetMotherDir() ? GetMotherDir()->GetSeekDir() : 0;
}

//______________________________________________________________________________
void TKeySQL::StoreKeyObject(const void* obj, const TClass* cl)
{
   // Stores object, associated with key, into data tables
   
   TSQLFile* f = (TSQLFile*) GetFile(); 
    
   fCycle = GetMotherDir()->AppendKey(this);

   fKeyId = f->DefineNextKeyId();

   fObjId = f->StoreObjectInTables(fKeyId, obj, cl);

   if (cl) fClassName = cl->GetName();
   
   if (GetDBObjId()>=0) { 
      fDatime.Set();
      if (!f->WriteKeyData(this)) {
         // cannot add entry to keys table                          
         Error("StoreKeyObject","Cannot write data to key tables");
         // delete everything relevant for that key
         f->DeleteKeyFromDB(GetDBKeyId());
         fObjId = -1;
      }
   }
   
   if (GetDBObjId()<0)
      GetMotherDir()->GetListOfKeys()->Remove(this);
   // fix me !!! One should delete object by other means
   // delete this;
}

//______________________________________________________________________________
Int_t TKeySQL::Read(TObject* tobj)
{
   // To read an object from the file.
   // The object associated to this key is read from the file into memory.
   // Before invoking this function, obj has been created via the
   // default constructor.

   if (tobj==0) return 0; 
    
   void* res = ReadKeyObject(tobj, 0);
   
   return res==0 ? 0 : 1;
}

//______________________________________________________________________________
TObject* TKeySQL::ReadObj()
{
// Read object derived from TObject class
// If it is not TObject or in case of error, return 0

   TObject* tobj = (TObject*) ReadKeyObject(0, TObject::Class());
   
   if (tobj!=0) {
      if (gROOT->GetForceStyle()) tobj->UseCurrentStyle();
      if (tobj->IsA() == TDirectoryFile::Class()) {
         TDirectoryFile *dir = (TDirectoryFile*) tobj;
         dir->SetName(GetName());
         dir->SetTitle(GetTitle());
         dir->SetSeekDir(GetDBKeyId());
         dir->SetMother(fMotherDir);
         dir->ReadKeys();
         fMotherDir->Append(dir);
      }
   }
       
   return tobj;
}

//______________________________________________________________________________
TObject* TKeySQL::ReadObjWithBuffer(char * /*bufferRead*/)
{
// Read object derived from TObject class
// If it is not TObject or in case of error, return 0

   TObject* tobj = (TObject*) ReadKeyObject(0, TObject::Class());
   
   if (tobj!=0) {
      if (gROOT->GetForceStyle()) tobj->UseCurrentStyle();
      if (tobj->IsA() == TDirectoryFile::Class()) {
         TDirectoryFile *dir = (TDirectoryFile*) tobj;
         dir->SetName(GetName());
         dir->SetTitle(GetTitle());
         dir->SetSeekDir(GetDBKeyId());
         dir->SetMother(fMotherDir);
         dir->ReadKeys();
         fMotherDir->Append(dir);
      }
   }
       
   return tobj;
}

//______________________________________________________________________________
void* TKeySQL::ReadObjectAny(const TClass* expectedClass)
{
// read object of any type from SQL database

   return ReadKeyObject(0, expectedClass);
}

//______________________________________________________________________________
void* TKeySQL::ReadKeyObject(void* obj, const TClass* expectedClass)
{
   // Read object, associated with key, from database

   TSQLFile* f = (TSQLFile*) GetFile(); 

   if ((GetDBKeyId()<=0) || (f==0)) return obj;

   TBufferSQL2 buffer(TBuffer::kRead, f);
   
   TClass* cl = 0;

   void* res = buffer.SqlReadAny(GetDBKeyId(), GetDBObjId(), &cl, obj);
   
   if ((cl==0) || (res==0)) return 0;
   
   Int_t delta = 0;
   
   if (expectedClass!=0) {
      delta = cl->GetBaseClassOffset(expectedClass);
      if (delta<0) {
         if (obj==0) cl->Destructor(res);
         return 0;
      }
      if (cl->GetState() > TClass::kEmulated && expectedClass->GetState() <= TClass::kEmulated) {
         //we cannot mix a compiled class with an emulated class in the inheritance
         Warning("XmlReadAny",
                 "Trying to read an emulated class (%s) to store in a compiled pointer (%s)",
                 cl->GetName(),expectedClass->GetName());
      }
   }
   
   return ((char*)res) + delta;
}
 TKeySQL.cxx:1
 TKeySQL.cxx:2
 TKeySQL.cxx:3
 TKeySQL.cxx:4
 TKeySQL.cxx:5
 TKeySQL.cxx:6
 TKeySQL.cxx:7
 TKeySQL.cxx:8
 TKeySQL.cxx:9
 TKeySQL.cxx:10
 TKeySQL.cxx:11
 TKeySQL.cxx:12
 TKeySQL.cxx:13
 TKeySQL.cxx:14
 TKeySQL.cxx:15
 TKeySQL.cxx:16
 TKeySQL.cxx:17
 TKeySQL.cxx:18
 TKeySQL.cxx:19
 TKeySQL.cxx:20
 TKeySQL.cxx:21
 TKeySQL.cxx:22
 TKeySQL.cxx:23
 TKeySQL.cxx:24
 TKeySQL.cxx:25
 TKeySQL.cxx:26
 TKeySQL.cxx:27
 TKeySQL.cxx:28
 TKeySQL.cxx:29
 TKeySQL.cxx:30
 TKeySQL.cxx:31
 TKeySQL.cxx:32
 TKeySQL.cxx:33
 TKeySQL.cxx:34
 TKeySQL.cxx:35
 TKeySQL.cxx:36
 TKeySQL.cxx:37
 TKeySQL.cxx:38
 TKeySQL.cxx:39
 TKeySQL.cxx:40
 TKeySQL.cxx:41
 TKeySQL.cxx:42
 TKeySQL.cxx:43
 TKeySQL.cxx:44
 TKeySQL.cxx:45
 TKeySQL.cxx:46
 TKeySQL.cxx:47
 TKeySQL.cxx:48
 TKeySQL.cxx:49
 TKeySQL.cxx:50
 TKeySQL.cxx:51
 TKeySQL.cxx:52
 TKeySQL.cxx:53
 TKeySQL.cxx:54
 TKeySQL.cxx:55
 TKeySQL.cxx:56
 TKeySQL.cxx:57
 TKeySQL.cxx:58
 TKeySQL.cxx:59
 TKeySQL.cxx:60
 TKeySQL.cxx:61
 TKeySQL.cxx:62
 TKeySQL.cxx:63
 TKeySQL.cxx:64
 TKeySQL.cxx:65
 TKeySQL.cxx:66
 TKeySQL.cxx:67
 TKeySQL.cxx:68
 TKeySQL.cxx:69
 TKeySQL.cxx:70
 TKeySQL.cxx:71
 TKeySQL.cxx:72
 TKeySQL.cxx:73
 TKeySQL.cxx:74
 TKeySQL.cxx:75
 TKeySQL.cxx:76
 TKeySQL.cxx:77
 TKeySQL.cxx:78
 TKeySQL.cxx:79
 TKeySQL.cxx:80
 TKeySQL.cxx:81
 TKeySQL.cxx:82
 TKeySQL.cxx:83
 TKeySQL.cxx:84
 TKeySQL.cxx:85
 TKeySQL.cxx:86
 TKeySQL.cxx:87
 TKeySQL.cxx:88
 TKeySQL.cxx:89
 TKeySQL.cxx:90
 TKeySQL.cxx:91
 TKeySQL.cxx:92
 TKeySQL.cxx:93
 TKeySQL.cxx:94
 TKeySQL.cxx:95
 TKeySQL.cxx:96
 TKeySQL.cxx:97
 TKeySQL.cxx:98
 TKeySQL.cxx:99
 TKeySQL.cxx:100
 TKeySQL.cxx:101
 TKeySQL.cxx:102
 TKeySQL.cxx:103
 TKeySQL.cxx:104
 TKeySQL.cxx:105
 TKeySQL.cxx:106
 TKeySQL.cxx:107
 TKeySQL.cxx:108
 TKeySQL.cxx:109
 TKeySQL.cxx:110
 TKeySQL.cxx:111
 TKeySQL.cxx:112
 TKeySQL.cxx:113
 TKeySQL.cxx:114
 TKeySQL.cxx:115
 TKeySQL.cxx:116
 TKeySQL.cxx:117
 TKeySQL.cxx:118
 TKeySQL.cxx:119
 TKeySQL.cxx:120
 TKeySQL.cxx:121
 TKeySQL.cxx:122
 TKeySQL.cxx:123
 TKeySQL.cxx:124
 TKeySQL.cxx:125
 TKeySQL.cxx:126
 TKeySQL.cxx:127
 TKeySQL.cxx:128
 TKeySQL.cxx:129
 TKeySQL.cxx:130
 TKeySQL.cxx:131
 TKeySQL.cxx:132
 TKeySQL.cxx:133
 TKeySQL.cxx:134
 TKeySQL.cxx:135
 TKeySQL.cxx:136
 TKeySQL.cxx:137
 TKeySQL.cxx:138
 TKeySQL.cxx:139
 TKeySQL.cxx:140
 TKeySQL.cxx:141
 TKeySQL.cxx:142
 TKeySQL.cxx:143
 TKeySQL.cxx:144
 TKeySQL.cxx:145
 TKeySQL.cxx:146
 TKeySQL.cxx:147
 TKeySQL.cxx:148
 TKeySQL.cxx:149
 TKeySQL.cxx:150
 TKeySQL.cxx:151
 TKeySQL.cxx:152
 TKeySQL.cxx:153
 TKeySQL.cxx:154
 TKeySQL.cxx:155
 TKeySQL.cxx:156
 TKeySQL.cxx:157
 TKeySQL.cxx:158
 TKeySQL.cxx:159
 TKeySQL.cxx:160
 TKeySQL.cxx:161
 TKeySQL.cxx:162
 TKeySQL.cxx:163
 TKeySQL.cxx:164
 TKeySQL.cxx:165
 TKeySQL.cxx:166
 TKeySQL.cxx:167
 TKeySQL.cxx:168
 TKeySQL.cxx:169
 TKeySQL.cxx:170
 TKeySQL.cxx:171
 TKeySQL.cxx:172
 TKeySQL.cxx:173
 TKeySQL.cxx:174
 TKeySQL.cxx:175
 TKeySQL.cxx:176
 TKeySQL.cxx:177
 TKeySQL.cxx:178
 TKeySQL.cxx:179
 TKeySQL.cxx:180
 TKeySQL.cxx:181
 TKeySQL.cxx:182
 TKeySQL.cxx:183
 TKeySQL.cxx:184
 TKeySQL.cxx:185
 TKeySQL.cxx:186
 TKeySQL.cxx:187
 TKeySQL.cxx:188
 TKeySQL.cxx:189
 TKeySQL.cxx:190
 TKeySQL.cxx:191
 TKeySQL.cxx:192
 TKeySQL.cxx:193
 TKeySQL.cxx:194
 TKeySQL.cxx:195
 TKeySQL.cxx:196
 TKeySQL.cxx:197
 TKeySQL.cxx:198
 TKeySQL.cxx:199
 TKeySQL.cxx:200
 TKeySQL.cxx:201
 TKeySQL.cxx:202
 TKeySQL.cxx:203
 TKeySQL.cxx:204
 TKeySQL.cxx:205
 TKeySQL.cxx:206
 TKeySQL.cxx:207
 TKeySQL.cxx:208
 TKeySQL.cxx:209
 TKeySQL.cxx:210
 TKeySQL.cxx:211
 TKeySQL.cxx:212
 TKeySQL.cxx:213
 TKeySQL.cxx:214
 TKeySQL.cxx:215
 TKeySQL.cxx:216
 TKeySQL.cxx:217
 TKeySQL.cxx:218
 TKeySQL.cxx:219
 TKeySQL.cxx:220
 TKeySQL.cxx:221
 TKeySQL.cxx:222
 TKeySQL.cxx:223
 TKeySQL.cxx:224
 TKeySQL.cxx:225
 TKeySQL.cxx:226
 TKeySQL.cxx:227
 TKeySQL.cxx:228
 TKeySQL.cxx:229
 TKeySQL.cxx:230
 TKeySQL.cxx:231
 TKeySQL.cxx:232
 TKeySQL.cxx:233
 TKeySQL.cxx:234
 TKeySQL.cxx:235
 TKeySQL.cxx:236
 TKeySQL.cxx:237
 TKeySQL.cxx:238
 TKeySQL.cxx:239
 TKeySQL.cxx:240
 TKeySQL.cxx:241
 TKeySQL.cxx:242
 TKeySQL.cxx:243
 TKeySQL.cxx:244
 TKeySQL.cxx:245
 TKeySQL.cxx:246
 TKeySQL.cxx:247
 TKeySQL.cxx:248
 TKeySQL.cxx:249
 TKeySQL.cxx:250
 TKeySQL.cxx:251
 TKeySQL.cxx:252
 TKeySQL.cxx:253
 TKeySQL.cxx:254
 TKeySQL.cxx:255
 TKeySQL.cxx:256
 TKeySQL.cxx:257
 TKeySQL.cxx:258
 TKeySQL.cxx:259
 TKeySQL.cxx:260
 TKeySQL.cxx:261
 TKeySQL.cxx:262
 TKeySQL.cxx:263
 TKeySQL.cxx:264
 TKeySQL.cxx:265
 TKeySQL.cxx:266
 TKeySQL.cxx:267
 TKeySQL.cxx:268
 TKeySQL.cxx:269
 TKeySQL.cxx:270
 TKeySQL.cxx:271
 TKeySQL.cxx:272
 TKeySQL.cxx:273
 TKeySQL.cxx:274
 TKeySQL.cxx:275
 TKeySQL.cxx:276
 TKeySQL.cxx:277
 TKeySQL.cxx:278
 TKeySQL.cxx:279
 TKeySQL.cxx:280
 TKeySQL.cxx:281
 TKeySQL.cxx:282
 TKeySQL.cxx:283
 TKeySQL.cxx:284
 TKeySQL.cxx:285
 TKeySQL.cxx:286
 TKeySQL.cxx:287
 TKeySQL.cxx:288
 TKeySQL.cxx:289
 TKeySQL.cxx:290
 TKeySQL.cxx:291
 TKeySQL.cxx:292
 TKeySQL.cxx:293