diff --git a/sql/inc/TSQLClassInfo.h b/sql/inc/TSQLClassInfo.h index 81576a9b2d738d44066c567b786cd62cee86c59a..a084dba85ad09d4b72291027cb46dbeed194c7f0 100644 --- a/sql/inc/TSQLClassInfo.h +++ b/sql/inc/TSQLClassInfo.h @@ -1,4 +1,4 @@ -// @(#)root/sql:$Name: $:$Id: TSQLClassInfo.h,v 1.2 2005/11/22 20:42:36 pcanal Exp $ +// @(#)root/sql:$Name: $:$Id: TSQLClassInfo.h,v 1.3 2005/12/07 14:59:57 rdm Exp $ // Author: Sergey Linev 20/11/2005 /************************************************************************* @@ -38,7 +38,7 @@ public: virtual ~TSQLClassInfo(); virtual const char* GetName() const { return fClassName.Data(); } - Int_t GetClassVarsion() const { return fClassVersion; } + Int_t GetClassVersion() const { return fClassVersion; } const char* GetClassTableName() const { return fClassTable.Data(); } const char* GetRawTableName() const { return fRawTable.Data(); } diff --git a/sql/inc/TSQLFile.h b/sql/inc/TSQLFile.h index 46cd185247112721fea77f9e8bb8c9cdf90f0067..407bfae97e042a7d8a71ec3ce78684f6fc13e667 100644 --- a/sql/inc/TSQLFile.h +++ b/sql/inc/TSQLFile.h @@ -1,4 +1,4 @@ -// @(#)root/sql:$Name: $:$Id: TSQLFile.h,v 1.6 2005/12/07 14:59:57 rdm Exp $ +// @(#)root/sql:$Name: $:$Id: TSQLFile.h,v 1.7 2006/02/01 18:57:41 pcanal Exp $ // Author: Sergey Linev 20/11/2005 /************************************************************************* @@ -29,12 +29,12 @@ class TStreamerElement; class TStreamerInfo; class TSQLServer; +class TSQLStatement; class TSQLResult; class TSQLRow; class TKeySQL; class TBufferSQL2; class TSQLClassInfo; -class TSQLObjectData; class TSQLFile : public TFile { @@ -96,6 +96,7 @@ protected: TSQLClassInfo* FindSQLClassInfo(const char* clname, Int_t version); TSQLClassInfo* RequestSQLClassInfo(const char* clname, Int_t version, Bool_t force = kFALSE); TSQLClassInfo* RequestSQLClassInfo(const TClass* cl, Bool_t force = kFALSE); + Bool_t SyncSQLClassInfoRawTables(TSQLClassInfo* sqlinfo, Bool_t hasrawdata); Bool_t SyncSQLClassInfo(TSQLClassInfo* sqlinfo, TObjArray* columns, Bool_t hasrawdata); Bool_t ProduceClassSelectQuery(TStreamerInfo* info, TSQLClassInfo* sqlinfo, TString& columns, TString& tables, Int_t& tablecnt); @@ -112,7 +113,7 @@ protected: TSQLResult* GetNormalClassData(Long64_t objid, TSQLClassInfo* sqlinfo); TSQLResult* GetNormalClassDataAll(Long64_t minobjid, Long64_t maxobjid, TSQLClassInfo* sqlinfo); TSQLResult* GetBlobClassData(Long64_t objid, TSQLClassInfo* sqlinfo); - TSQLObjectData* GetObjectClassData(Long64_t objid, TSQLClassInfo* sqlinfo); + TSQLStatement* GetBlobClassDataStmt(Long64_t objid, TSQLClassInfo* sqlinfo); Long64_t StoreObjectInTables(Long64_t keyid, const void* obj, const TClass* cl); Bool_t WriteSpecialObject(Long64_t keyid, TObject* obj, const char* name, const char* title); TObject* ReadSpecialObject(Long64_t keyid, TObject* obj = 0); @@ -224,6 +225,7 @@ public: Bool_t IsMySQL() const; virtual Bool_t IsOpen() const; Bool_t IsOracle() const; + Bool_t IsODBC() const; virtual void MakeFree(Long64_t, Long64_t) {} virtual void MakeProject(const char *, const char* ="*", Option_t* ="new") {} // *MENU* diff --git a/sql/inc/TSQLObjectData.h b/sql/inc/TSQLObjectData.h index 3b0b5ae59968c3d7db047ef160919346437a7bdb..84a61e9817856243ead7709f8ec7629c5a13d0d9 100644 --- a/sql/inc/TSQLObjectData.h +++ b/sql/inc/TSQLObjectData.h @@ -1,4 +1,4 @@ -// @(#)root/sql:$Name: $:$Id: TSQLObjectData.h,v 1.6 2006/05/11 10:29:45 brun Exp $ +// @(#)root/sql:$Name: $:$Id: TSQLObjectData.h,v 1.7 2006/05/12 08:17:02 brun Exp $ // Author: Sergey Linev 20/11/2005 /************************************************************************* @@ -33,6 +33,7 @@ class TList; class TSQLClassInfo; class TSQLResult; class TSQLRow; +class TSQLStatement; class TSQLObjectInfo : public TObject { @@ -68,7 +69,8 @@ public: Long64_t objid, TSQLResult* classdata, TSQLRow* classrow, - TSQLResult* blobdata); + TSQLResult* blobdata, + TSQLStatement* blobstmt); virtual ~TSQLObjectData(); @@ -84,33 +86,35 @@ public: const char* GetValue() const { return fLocatedValue; } const char* GetColumnName() const { return fLocatedField; } - const char* GetBlobName1() const { return fBlobName1.Data(); } - const char* GetBlobName2() const { return fBlobName2.Data(); } + const char* GetBlobPrefixName() const { return fBlobPrefixName; } + const char* GetBlobTypeName() const { return fBlobTypeName; } Bool_t VerifyDataType(const char* tname, Bool_t errormsg = kTRUE); Bool_t PrepareForRawData(); protected: Bool_t ExtractBlobValues(); + Bool_t ShiftBlobRow(); Int_t GetNumClassFields(); const char* GetClassFieldName(Int_t n); - TSQLClassInfo* fInfo; //! - Long64_t fObjId; //! - Bool_t fOwner; //! - TSQLResult* fClassData; //! - TSQLResult* fBlobData; //! - Int_t fLocatedColumn; //! - Int_t fLocatedBlob; //! - TSQLRow* fClassRow; //! - TSQLRow* fBlobRow; //! - const char* fLocatedField; //! - const char* fLocatedValue; //! - Bool_t fCurrentBlob; //! - TString fBlobName1; //! - TString fBlobName2; //! - TObjArray* fUnpack; //! + TSQLClassInfo* fInfo; //! + Long64_t fObjId; //! + Bool_t fOwner; //! + TSQLResult* fClassData; //! + TSQLResult* fBlobData; //! + TSQLStatement* fBlobStmt; //! + Int_t fLocatedColumn; //! + Int_t fLocatedBlob; //! + TSQLRow* fClassRow; //! + TSQLRow* fBlobRow; //! + const char* fLocatedField; //! + const char* fLocatedValue; //! + Bool_t fCurrentBlob; //! + const char* fBlobPrefixName; //! name prefix in current blob row + const char* fBlobTypeName; //! name type (without prefix) in current blob row + TObjArray* fUnpack; //! ClassDef(TSQLObjectData, 1) // Keeps the data requested from the SQL server for an object. @@ -136,7 +140,7 @@ protected: Bool_t fIsMoreRows; //! indicates if class data has not yet read rows TList* fRowsPool; //! pool of extrcted, but didnot used rows -ClassDef(TSQLObjectDataPool,1) //XML object keeper class + ClassDef(TSQLObjectDataPool,1) // XML object keeper class }; diff --git a/sql/src/TBufferSQL2.cxx b/sql/src/TBufferSQL2.cxx index 6954b24bc2a7d46b4ec1724d67fc227f4e06711e..a3415d13b0a79a732e3093887dd6bde9c2df070d 100644 --- a/sql/src/TBufferSQL2.cxx +++ b/sql/src/TBufferSQL2.cxx @@ -1,4 +1,4 @@ -// @(#)root/sql:$Name: $:$Id: TBufferSQL2.cxx,v 1.10 2006/04/12 20:54:30 rdm Exp $ +// @(#)root/sql:$Name: $:$Id: TBufferSQL2.cxx,v 1.11 2006/05/11 10:29:45 brun Exp $ // Author: Sergey Linev 20/11/2005 /************************************************************************* @@ -238,45 +238,60 @@ Bool_t TBufferSQL2::SqlObjectInfo(Long64_t objid, TString& clname, Version_t& ve //______________________________________________________________________________ TSQLObjectData* TBufferSQL2::SqlObjectData(Long64_t objid, TSQLClassInfo* sqlinfo) { - //please Sergey document this function - if (!sqlinfo->IsClassTableExist()) - return fSQL->GetObjectClassData(objid, sqlinfo); + // creates TSQLObjectData for specifed object id and specified class + // Object data for each class can be stored in two different tables. + // First table contains data in column-wise form for simple types like integer, + // strings and so on when second table contains any other data which cannot + // be converted into column-wise representation. + // TSQLObjectData will contain results of the requests to both such tables for + // concrete object id. - TSQLObjectDataPool* pool = 0; + TSQLResult *classdata = 0; + TSQLRow *classrow = 0; - if (fPoolsMap!=0) - pool = (TSQLObjectDataPool*) fPoolsMap->GetValue(sqlinfo); + if (sqlinfo->IsClassTableExist()) { + + TSQLObjectDataPool* pool = 0; + + if (fPoolsMap!=0) + pool = (TSQLObjectDataPool*) fPoolsMap->GetValue(sqlinfo); + + if ((pool==0) && (fLastObjId>=fFirstObjId)) { + if (gDebug>4) Info("SqlObjectData","Before request to %s",sqlinfo->GetClassTableName()); + TSQLResult *alldata = fSQL->GetNormalClassDataAll(fFirstObjId, fLastObjId, sqlinfo); + if (gDebug>4) Info("SqlObjectData","After request res = %x",alldata); + if (alldata==0) { + Error("SqlObjectData","Cannot get data from table %s",sqlinfo->GetClassTableName()); + return 0; + } - if ((pool==0) && (fLastObjId>=fFirstObjId)) { - if (gDebug>4) Info("SqlObjectData","Before request to %s",sqlinfo->GetClassTableName()); - TSQLResult *alldata = fSQL->GetNormalClassDataAll(fFirstObjId, fLastObjId, sqlinfo); - if (gDebug>4) Info("SqlObjectData","After request res = %x",alldata); - if (alldata==0) { - Error("SqlObjectData","Cannot get data from table %s",sqlinfo->GetClassTableName()); + if (fPoolsMap==0) fPoolsMap = new TMap(); + pool = new TSQLObjectDataPool(sqlinfo, alldata); + fPoolsMap->Add(sqlinfo, pool); + } + + if (pool==0) return 0; + + if (pool->GetSqlInfo()!=sqlinfo) { + Error("SqlObjectData","Missmatch in pools map !!! CANNOT BE !!!"); return 0; } + + classdata = pool->GetClassData(); + + classrow = pool->GetObjectRow(objid); + if (classrow==0) { + Error("SqlObjectData","Can not find row for objid = %lld in table %s", objid, sqlinfo->GetClassTableName()); + return 0; + } + } + + TSQLResult *blobdata = 0; + TSQLStatement* stmt = fSQL->GetBlobClassDataStmt(objid, sqlinfo); - if (fPoolsMap==0) fPoolsMap = new TMap(); - pool = new TSQLObjectDataPool(sqlinfo, alldata); - fPoolsMap->Add(sqlinfo, pool); - } - - if (pool==0) return 0; - - if (pool->GetSqlInfo()!=sqlinfo) { - Error("SqlObjectData","Missmatch in pools map !!! CANNOT BE !!!"); - return 0; - } - - TSQLResult *classdata = pool->GetClassData(); + if (stmt==0) blobdata = fSQL->GetBlobClassData(objid, sqlinfo); - TSQLRow* row = pool->GetObjectRow(objid); - if (row==0) { - Error("SqlObjectData","Can not find row for objid = %lld in table %s", objid, sqlinfo->GetClassTableName()); - return 0; - } - TSQLResult *blobdata = fSQL->GetBlobClassData(objid, sqlinfo); - return new TSQLObjectData(sqlinfo, objid, classdata, row, blobdata); + return new TSQLObjectData(sqlinfo, objid, classdata, classrow, blobdata, stmt); } //______________________________________________________________________________ @@ -349,9 +364,6 @@ void* TBufferSQL2::SqlReadObject(void* obj, TClass** cl, TMemberStreamer *stream { // Read object from the buffer - if (gDebug>2) - cout << "TBufferSQL2::SqlReadObject " << fCurrentData->GetBlobName2() << endl; - if (cl) *cl = 0; if (fErrorFlag>0) return obj; @@ -368,6 +380,9 @@ void* TBufferSQL2::SqlReadObject(void* obj, TClass** cl, TMemberStreamer *stream Long64_t objid = -1; sscanf(refid, FLong64, &objid); + if (gDebug>2) + Info("SqlReadObject","Starting objid = %lld column=%s", objid, fCurrentData->GetColumnName()); + if (!fCurrentData->IsBlobData() || fCurrentData->VerifyDataType(sqlio::ObjectPtr,kFALSE)) if (objid==0) { @@ -545,7 +560,7 @@ void TBufferSQL2::SetStreamerElementNumber(Int_t number) return; } TStreamerElement* elem = info->GetStreamerElementReal(number, 0); - + Int_t comp_type = info->GetTypes()[number]; Int_t elem_type = elem->GetType(); @@ -768,7 +783,10 @@ void TBufferSQL2::WorkWithClass(const char* classname, Version_t classversion) if (IsReading()) { Long64_t objid = 0; - + +// if ((fCurrentData!=0) && fCurrentData->VerifyDataType(sqlio::ObjectInst, kFALSE)) +// if (!fCurrentData->IsBlobData()) Info("WorkWithClass","Big problem %s", fCurrentData->GetValue()); + if ((fCurrentData!=0) && fCurrentData->IsBlobData() && fCurrentData->VerifyDataType(sqlio::ObjectInst, kFALSE)) { objid = atoi(fCurrentData->GetValue()); @@ -813,7 +831,7 @@ void TBufferSQL2::WorkWithElement(TStreamerElement* elem, Int_t number) // when several data memebers of the same basic type streamed with single ...FastArray call if (gDebug>2) - cout << " TBufferSQL2::WorkWithElement " << elem->GetName() << endl; + Info("WorkWithElement","elem = %s",elem->GetName()); if (number>=0) PushStack()->SetStreamerElement(elem, number); @@ -829,7 +847,7 @@ void TBufferSQL2::WorkWithElement(TStreamerElement* elem, Int_t number) } fCurrentData = Stack()->GetObjectData(kTRUE); - + Int_t located = Stack()->LocateElementColumn(fSQL, this, fCurrentData); if (located==TSQLStructure::kColUnknown) { @@ -905,7 +923,7 @@ Version_t TBufferSQL2::ReadVersion(UInt_t *start, UInt_t *bcnt, const TClass *) TString value = fCurrentData->GetValue(); res = value.Atoi(); if (gDebug>3) - cout << "TBufferSQL2::ReadVersion from blob " << fCurrentData->GetBlobName1() << " = " << res << endl; + cout << "TBufferSQL2::ReadVersion from blob " << fCurrentData->GetBlobPrefixName() << " = " << res << endl; fCurrentData->ShiftToNextValue(); } else { Error("ReadVersion", "No correspondent tags to read version"); @@ -965,11 +983,11 @@ void TBufferSQL2::WriteObject(const void *actualObjStart, const TClass *actualCl #define SQLReadArrayCompress(vname, arrsize) \ { \ while(indx<arrsize) { \ - const char* name = fCurrentData->GetBlobName1(); \ + const char* name = fCurrentData->GetBlobPrefixName(); \ Int_t first, last, res; \ if (strstr(name,sqlio::IndexSepar)==0) { \ - res = sscanf(name,"[%d]", &first); last = first; \ - } else res = sscanf(name,"[%d..%d]", &first, &last); \ + res = sscanf(name,"[%d", &first); last = first; \ + } else res = sscanf(name,"[%d..%d", &first, &last); \ if (gDebug>5) cout << name << " first = " << first << " last = " << last << " res = " << res << endl; \ if ((first!=indx) || (last<first) || (last>=arrsize)) { \ Error("SQLReadArrayCompress","Error reading array content %s", name); \ @@ -1420,7 +1438,7 @@ void TBufferSQL2::ReadFastArray(void *start, const TClass *cl, Int_t n, TMember // object data is started and finished if (gDebug>2) - cout << "TBufferSQL2::ReadFastArray(* " << endl; + Info("ReadFastArray","(void *"); if (streamer) { StreamObject(start, streamer, cl, 0); @@ -1447,7 +1465,7 @@ void TBufferSQL2::ReadFastArray(void **start, const TClass *cl, Int_t n, Bool_t // object data is started and finished if (gDebug>2) - cout << "TBufferSQL2::ReadFastArray(** " << endl; + Info("ReadFastArray","(void ** pre = %d n = %d", isPreAlloc, n); if (streamer) { if (isPreAlloc) { @@ -1476,6 +1494,9 @@ void TBufferSQL2::ReadFastArray(void **start, const TClass *cl, Int_t n, Bool_t } } + if (gDebug>2) + Info("ReadFastArray","(void ** Done" ); + // TBuffer::ReadFastArray(startp, cl, n, isPreAlloc, s); } diff --git a/sql/src/TKeySQL.cxx b/sql/src/TKeySQL.cxx index e5980d31446b96e763961080ff4a50509f055136..67d664c5c5fce1106301e4993a419c97a280fdab 100644 --- a/sql/src/TKeySQL.cxx +++ b/sql/src/TKeySQL.cxx @@ -1,4 +1,4 @@ -// @(#)root/sql:$Name: $:$Id: TKeySQL.cxx,v 1.7 2006/02/01 18:57:41 pcanal Exp $ +// @(#)root/sql:$Name: $:$Id: TKeySQL.cxx,v 1.8 2006/05/11 10:29:45 brun Exp $ // Author: Sergey Linev 20/11/2005 /************************************************************************* @@ -149,13 +149,15 @@ void TKeySQL::Delete(Option_t * /*option*/) 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) { - //please Sergey: document this function + // Stores object, associated with key, into data tables + TSQLFile* f = (TSQLFile*) GetFile(); fCycle = GetMotherDir()->AppendKey(this); @@ -170,7 +172,7 @@ void TKeySQL::StoreKeyObject(const void* obj, const TClass* cl) fDatime.Set(); if (!f->WriteKeyData(this)) { // cannot add entry to keys table - Error("StoreObject","Cannot write data to key tables"); + Error("StoreKeyObject","Cannot write data to key tables"); // delete everything relevant for that key f->DeleteKeyFromDB(GetDBKeyId()); fObjId = -1; @@ -233,7 +235,7 @@ void* TKeySQL::ReadObjectAny(const TClass* expectedClass) //______________________________________________________________________________ void* TKeySQL::ReadKeyObject(void* obj, const TClass* expectedClass) { - //please Sergey: document this function + // Read object, associated with key, from database TSQLFile* f = (TSQLFile*) GetFile(); diff --git a/sql/src/TSQLFile.cxx b/sql/src/TSQLFile.cxx index bf229f35ccd120385872fc8f04ca376e7cf97b2a..3bff48d358ca728c6519872bf24e9c08f949bbb5 100644 --- a/sql/src/TSQLFile.cxx +++ b/sql/src/TSQLFile.cxx @@ -1,4 +1,4 @@ -// @(#)root/sql:$Name: $:$Id: TSQLFile.cxx,v 1.8 2006/03/20 21:43:44 pcanal Exp $ +// @(#)root/sql:$Name: $:$Id: TSQLFile.cxx,v 1.9 2006/05/11 10:29:45 brun Exp $ // Author: Sergey Linev 20/11/2005 /************************************************************************* @@ -180,6 +180,7 @@ #include "TClass.h" #include "TSQLServer.h" +#include "TSQLStatement.h" #include "TSQLResult.h" #include "TSQLRow.h" #include "TBufferSQL2.h" @@ -504,6 +505,7 @@ TSQLFile::TSQLFile(const char* dbname, Option_t* option, const char* user, const gROOT->cd(); fSQL = TSQLServer::Connect(dbname, user, pass); + if (fSQL==0) { Error("TSQLFile", "Cannot connect to DB %s", dbname); goto zombie; @@ -610,6 +612,16 @@ Bool_t TSQLFile::IsOracle() const return strcmp(fSQL->ClassName(),"TOracleServer")==0; } +//______________________________________________________________________________ +Bool_t TSQLFile::IsODBC() const +{ + // checks, if ODBC driver used for database connection + + if (fSQL==0) return kFALSE; + return strcmp(fSQL->ClassName(),"TODBCServer")==0; + +} + //______________________________________________________________________________ void TSQLFile::SetUseSuffixes(Bool_t on) { @@ -912,10 +924,8 @@ void TSQLFile::WriteHeader() void TSQLFile::WriteStreamerInfo() { // Store all TStreamerInfo, used in file, in sql database - // For the moment function is disabled while no proper reader is - // existing - return; + // return; // do not write anything when no basic tables was created if (!IsTablesExists()) return; @@ -1001,11 +1011,8 @@ TList* TSQLFile::GetStreamerInfoList() // Read back streamer infos from database // List of streamer infos is always stored with key:id 0, // which is not shown in normal keys list - // Method is not active while TStreamerElement and TStreamerBase has custom - // streamers, which can not be handled by TBufferSQL2. - // Hopefully, problem will be solved soon - return new TList; +// return new TList; if (gDebug>1) Info("GetStreamerInfoList","Start reading of streamer infos"); @@ -1057,10 +1064,12 @@ Int_t TSQLFile::StreamKeysForDirectory(TDirectory* dir, Bool_t doupdate, Long64_ if (res==0) return -1; - Int_t nkeys = res->GetRowCount(); + Int_t nkeys = 0; + + TSQLRow* row = 0; - for(Int_t nrow=0;nrow<nkeys;nrow++) { - TSQLRow* row = res->Next(); + while ((row = res->Next()) != 0) { + nkeys++; Long64_t keyid = sqlio::atol64((*row)[0]); // Int_t dirid = atoi((*row)[1]); @@ -1072,18 +1081,18 @@ Int_t TSQLFile::StreamKeysForDirectory(TDirectory* dir, Bool_t doupdate, Long64_ const char* classname = (*row)[7]; if (gDebug>4) - cout << " Reading keyid = " << keyid << " name = " << keyname << endl; + cout << " Reading keyid = " << keyid << " name = " << keyname << endl; if ((keyid>=sqlio::Ids_FirstKey) || (keyid==specialkeyid)) if (doupdate) { - TKeySQL* key = FindSQLKey(dir, keyid); + TKeySQL* key = FindSQLKey(dir, keyid); - if (key==0) { - Error("StreamKeysForDirectory","Key with id %d not exist in list", keyid); - nkeys = -1; // this will finish execution - } else - if (key->IsKeyModified(keyname, keytitle, keydatime, cycle, classname)) - UpdateKeyData(key); + if (key==0) { + Error("StreamKeysForDirectory","Key with id %d not exist in list", keyid); + nkeys = -1; // this will finish execution + } else + if (key->IsKeyModified(keyname, keytitle, keydatime, cycle, classname)) + UpdateKeyData(key); } else { TKeySQL* key = new TKeySQL(dir, keyid, objid, @@ -1187,9 +1196,9 @@ Bool_t TSQLFile::ReadConfigurations() if ((field.CompareTo(name, TString::kIgnoreCase)==0)) \ target = value; else + TSQLRow* row = 0; - for(Int_t nrow=0;nrow<res->GetRowCount();nrow++) { - TSQLRow* row = res->Next(); + while ((row = res->Next()) != 0) { TString field = row->GetField(0); TString value = row->GetField(1); @@ -1300,7 +1309,11 @@ void TSQLFile::CreateBasicTables() //______________________________________________________________________________ void TSQLFile::IncrementModifyCounter() { - //please Sergey: document this function + // Update value of modify counter in config table + // Modify counter used to indicate that something was changed in database. + // It will be used when multiple instances of TSQLFile for the same data base + // will be connected. + if (!IsWritable()) { Error("IncrementModifyCounter","Cannot update tables without write accsess"); return; @@ -1526,8 +1539,8 @@ TSQLResult* TSQLFile::SQLQuery(const char* cmd, Int_t flag, Bool_t* ok) delete res; return 0; } - if ((flag==2) && IsOracle()) - res = new TSQLResultCopy(res); +// if ((flag==2) && IsOracle()) +// res = new TSQLResultCopy(res); return res; } @@ -1568,11 +1581,9 @@ TObjArray* TSQLFile::SQLTablesList(const char* searchtable) TString sqlcmd; TString user = fUserName; user.ToUpper(); - sqlcmd.Form("SELECT object_name FROM ALL_OBJECTS WHERE object_type='TABLE' and owner='%s'",user.Data()); - if (searchtable!=0) { - TString table = searchtable; - sqlcmd += Form(" and object_name='%s'",table.Data()); - } + sqlcmd.Form("SELECT table_name FROM all_tables WHERE owner='%s'",user.Data()); + if (searchtable!=0) + sqlcmd += ::Form(" and table_name LIKE '%s'",searchtable); TSQLResult* tables = SQLQuery(sqlcmd.Data(), 1); if (tables==0) return 0; @@ -1588,6 +1599,20 @@ TObjArray* TSQLFile::SQLTablesList(const char* searchtable) row = tables->Next(); } delete tables; + } else + if (IsODBC()) { + TSQLResult* tables = fSQL->GetTables("",searchtable); + if (tables==0) return 0; + + TSQLRow* row = tables->Next(); + while (row!=0) { + if (res==0) res = new TObjArray; + res->Add(new TObjString(row->GetField(2))); + delete row; + row = tables->Next(); + } + delete tables; + } else { TSQLResult* tables = fSQL->GetTables(GetDataBaseName(), searchtable); if (tables==0) return 0; @@ -1640,6 +1665,20 @@ TObjArray* TSQLFile::SQLTableColumns(const char* tablename) res->Add(col); } delete cols; + } else + if (IsODBC()) { + TSQLResult* cols = fSQL->GetColumns("", tablename); + if (cols==0) return 0; + + TSQLRow* row = cols->Next(); + while (row!=0) { + TNamed* col = new TNamed(row->GetField(3), row->GetField(5)); + if (res==0) res = new TObjArray; + res->Add(col); + delete row; + row = cols->Next(); + } + delete cols; } else { TSQLResult* cols = fSQL->GetColumns(GetDataBaseName(), tablename, ""); @@ -1875,7 +1914,8 @@ Bool_t TSQLFile::WriteKeyData(TKeySQL* key) //______________________________________________________________________________ Bool_t TSQLFile::UpdateKeyData(TKeySQL* key) { - //please Sergey: document this function + // updates (overwrites) key data in KeysTable + if ((fSQL==0) || (key==0)) return kFALSE; TString sqlcmd; @@ -1926,7 +1966,7 @@ TSQLClassInfo* TSQLFile::FindSQLClassInfo(const char* clname, Int_t version) while ((info = (TSQLClassInfo*) iter()) !=0 ) { if (strcmp(info->GetName(), clname)==0) - if (info->GetClassVarsion()==version) return info; + if (info->GetClassVersion()==version) return info; } return 0; } @@ -2029,7 +2069,7 @@ Bool_t TSQLFile::SyncSQLClassInfo(TSQLClassInfo* sqlinfo, TObjArray* columns, Bo sqlinfo->SetColumns(newcolumns); if (GetUseIndexes()>kIndexesBasic) { - sqlcmd.Form("CREATE UNIQUE INDEX %s%s_Index%s ON %s%s%s (%s%s%s)", + sqlcmd.Form("CREATE UNIQUE INDEX %s%s_I1%s ON %s%s%s (%s%s%s)", quote, sqlinfo->GetClassTableName(), quote, quote, sqlinfo->GetClassTableName(), quote, quote, SQLObjectIdColumn(), quote); @@ -2037,6 +2077,9 @@ Bool_t TSQLFile::SyncSQLClassInfo(TSQLClassInfo* sqlinfo, TObjArray* columns, Bo } } + SyncSQLClassInfoRawTables(sqlinfo, hasrawdata); + +/* if (hasrawdata && !sqlinfo->IsRawTableExist()) { TString sqlcmd; @@ -2065,6 +2108,51 @@ Bool_t TSQLFile::SyncSQLClassInfo(TSQLClassInfo* sqlinfo, TObjArray* columns, Bo } } +*/ + + return kTRUE; +} + +//______________________________________________________________________________ +Bool_t TSQLFile::SyncSQLClassInfoRawTables(TSQLClassInfo* sqlinfo, Bool_t hasrawdata) +{ + // creates table for class raw data, if it is not exists + + if (sqlinfo==0) return kFALSE; + + const char* quote = SQLIdentifierQuote(); + + if (hasrawdata && !sqlinfo->IsRawTableExist()) { + if (gDebug>2) + Info("SyncSQLClassInfoRawTables", sqlinfo->GetName()); + + TString sqlcmd; + + sqlcmd.Form("CREATE TABLE %s%s%s (%s%s%s %s, %s%s%s %s, %s %s, %s %s)", + quote, sqlinfo->GetRawTableName(), quote, + quote, SQLObjectIdColumn(), quote, SQLIntType(), + quote, SQLRawIdColumn(), quote, SQLIntType(), + sqlio::BT_Field, SQLSmallTextType(), + sqlio::BT_Value, SQLSmallTextType()); + + if ((fTablesType.Length()>0) && IsMySQL()) { + sqlcmd +=" TYPE="; + sqlcmd += fTablesType; + } + + SQLQuery(sqlcmd.Data()); + sqlinfo->SetRawExist(kTRUE); + + if (GetUseIndexes()>kIndexesClass) { + sqlcmd.Form("CREATE UNIQUE INDEX %s%s_I2%s ON %s%s%s (%s%s%s, %s%s%s)", + quote, sqlinfo->GetClassTableName(), quote, + quote, sqlinfo->GetRawTableName(), quote, + quote, SQLObjectIdColumn(), quote, + quote, SQLRawIdColumn(), quote); + SQLQuery(sqlcmd.Data()); + } + + } return kTRUE; } @@ -2259,10 +2347,37 @@ TObjArray* TSQLFile::SQLObjectsInfo(Long64_t keyid) quote, sqlio::ObjectsTable, quote, quote, SQLKeyIdColumn(), quote, keyid, quote, SQLObjectIdColumn(), quote); + + TObjArray* arr = 0; + + if (fLogFile!=0) + *fLogFile << sqlcmd << endl; + if (gDebug>2) Info("SQLObjectsInfo",sqlcmd); + fQuerisCounter++; + + TSQLStatement* stmt = fSQL->Statement(sqlcmd.Data(), 1000); + + if (stmt!=0) { + stmt->Process(); + stmt->StoreResult(); + + while (stmt->NextResultRow()) { + Long64_t objid = stmt->GetLong64(0); + const char* clname = stmt->GetString(1); + Int_t version = stmt->GetInt(2); + + TSQLObjectInfo* info = new TSQLObjectInfo(objid, clname, version); + if (arr==0) arr = new TObjArray(); + arr->Add(info); + } + + delete stmt; + return arr; + } + TSQLResult* res = SQLQuery(sqlcmd.Data(), 1); if (res==0) return 0; - TObjArray* arr = 0; TSQLRow* row = 0; while ((row = res->Next()) != 0) { Long64_t objid = atoi(row->GetField(0)); @@ -2296,7 +2411,8 @@ TSQLResult* TSQLFile::GetNormalClassData(Long64_t objid, TSQLClassInfo* sqlinfo) //______________________________________________________________________________ TSQLResult* TSQLFile::GetNormalClassDataAll(Long64_t minobjid, Long64_t maxobjid, TSQLClassInfo* sqlinfo) { - //please Sergey: document this function + // return data for several objects from the range from normal class table + if (!sqlinfo->IsClassTableExist()) return 0; TString sqlcmd; const char* quote = SQLIdentifierQuote(); @@ -2312,41 +2428,46 @@ TSQLResult* TSQLFile::GetBlobClassData(Long64_t objid, TSQLClassInfo* sqlinfo) { // Method return request results for specified objid from _streamer_ classtable - if (sqlinfo->IsRawTableExist()) { - TString sqlcmd; - const char* quote = SQLIdentifierQuote(); - sqlcmd.Form("SELECT %s, %s FROM %s%s%s WHERE %s%s%s=%lld ORDER BY %s%s%s", - sqlio::BT_Field, sqlio::BT_Value, - quote, sqlinfo->GetRawTableName(), quote, - quote, SQLObjectIdColumn(), quote, objid, - quote, SQLRawIdColumn(), quote); - return SQLQuery(sqlcmd.Data(), 2); - } - - return 0; + if (!sqlinfo->IsRawTableExist()) return 0; + TString sqlcmd; + const char* quote = SQLIdentifierQuote(); + sqlcmd.Form("SELECT %s, %s FROM %s%s%s WHERE %s%s%s=%lld ORDER BY %s%s%s", + sqlio::BT_Field, sqlio::BT_Value, + quote, sqlinfo->GetRawTableName(), quote, + quote, SQLObjectIdColumn(), quote, objid, + quote, SQLRawIdColumn(), quote); + return SQLQuery(sqlcmd.Data(), 2); } //______________________________________________________________________________ -TSQLObjectData* TSQLFile::GetObjectClassData(Long64_t objid, TSQLClassInfo* sqlinfo) +TSQLStatement* TSQLFile::GetBlobClassDataStmt(Long64_t objid, TSQLClassInfo* sqlinfo) { - // Get data for specified object from particular class table - // Returns TSQLObjectData object, which contains one row from - // normal class table and data from _streamer_ table. - // TSQLObjectData object used later in TBufferSQL2 to unstream object - - if ((fSQL==0) || (objid<0) || (sqlinfo==0)) return 0; - - if (gDebug>1) - Info("GetObjectClassData","Request for %s id = %lld", sqlinfo->GetName(), objid); +// Method return request results for specified objid from _streamer_ classtable +// Data returned in form of statement, where direct access to values are possible - TSQLResult *classdata = GetNormalClassData(objid, sqlinfo); + if (!sqlinfo->IsRawTableExist()) return 0; - TSQLResult *blobdata = GetBlobClassData(objid, sqlinfo); - - if (gDebug>3) - Info("GetObjectClassData","normal = %x blobdata = %x", classdata, blobdata); - - return new TSQLObjectData(sqlinfo, objid, classdata, 0, blobdata); + TString sqlcmd; + const char* quote = SQLIdentifierQuote(); + sqlcmd.Form("SELECT %s, %s FROM %s%s%s WHERE %s%s%s=%lld ORDER BY %s%s%s", + sqlio::BT_Field, sqlio::BT_Value, + quote, sqlinfo->GetRawTableName(), quote, + quote, SQLObjectIdColumn(), quote, objid, + quote, SQLRawIdColumn(), quote); + + if (fLogFile!=0) + *fLogFile << sqlcmd << endl; + if (gDebug>2) Info("BuildStatement",sqlcmd); + fQuerisCounter++; + + TSQLStatement* stmt = fSQL->Statement(sqlcmd.Data(), 1000); + if (stmt==0) return 0; + + stmt->Process(); + + stmt->StoreResult(); + + return stmt; } //______________________________________________________________________________ @@ -2382,11 +2503,11 @@ Long64_t TSQLFile::StoreObjectInTables(Long64_t keyid, const void* obj, const TC } if (!SQLApplyCommands(&cmds)) { - Error("StoreObject","Cannot correctly store object data in database"); - objid = -1; - if (needcommit) SQLRollback(); + Error("StoreObject","Cannot correctly store object data in database"); + objid = -1; + if (needcommit) SQLRollback(); } else { - if (needcommit) SQLCommit(); + if (needcommit) SQLCommit(); } } cmds.Delete(); diff --git a/sql/src/TSQLObjectData.cxx b/sql/src/TSQLObjectData.cxx index a41b7bad51645a00650d0dfdba5e86c9e04fe8fa..7653019535b5d15ee2b3eafb791e3579d7a2cf6e 100644 --- a/sql/src/TSQLObjectData.cxx +++ b/sql/src/TSQLObjectData.cxx @@ -1,4 +1,4 @@ -// @(#)root/sql:$Name: $:$Id: TSQLObjectData.cxx,v 1.5 2006/04/27 10:19:43 brun Exp $ +// @(#)root/sql:$Name: $:$Id: TSQLObjectData.cxx,v 1.6 2006/05/11 10:29:45 brun Exp $ // Author: Sergey Linev 20/11/2005 /************************************************************************* @@ -28,6 +28,7 @@ #include "TSQLResult.h" #include "TSQLClassInfo.h" #include "TSQLStructure.h" +#include "TSQLStatement.h" ClassImp(TSQLObjectInfo) @@ -66,14 +67,15 @@ TSQLObjectData::TSQLObjectData() : fOwner(kFALSE), fClassData(0), fBlobData(0), + fBlobStmt(0), fLocatedColumn(-1), fClassRow(0), fBlobRow(0), fLocatedField(0), fLocatedValue(0), fCurrentBlob(kFALSE), - fBlobName1(), - fBlobName2(), + fBlobPrefixName(0), + fBlobTypeName(0), fUnpack(0) { // default contrsuctor @@ -84,21 +86,23 @@ TSQLObjectData::TSQLObjectData(TSQLClassInfo* sqlinfo, Long64_t objid, TSQLResult* classdata, TSQLRow* classrow, - TSQLResult* blobdata) : + TSQLResult* blobdata, + TSQLStatement* blobstmt) : TObject(), fInfo(sqlinfo), fObjId(objid), fOwner(kFALSE), fClassData(classdata), fBlobData(blobdata), + fBlobStmt(blobstmt), fLocatedColumn(-1), fClassRow(classrow), fBlobRow(0), fLocatedField(0), fLocatedValue(0), fCurrentBlob(kFALSE), - fBlobName1(), - fBlobName2(), + fBlobPrefixName(0), + fBlobTypeName(0), fUnpack(0) { // normal contrsuctor, @@ -108,8 +112,8 @@ TSQLObjectData::TSQLObjectData(TSQLClassInfo* sqlinfo, fOwner = kTRUE; fClassRow = fClassData->Next(); } - if (fBlobData!=0) - fBlobRow = fBlobData->Next(); + + ShiftBlobRow(); } //______________________________________________________________________________ @@ -122,6 +126,7 @@ TSQLObjectData::~TSQLObjectData() if (fBlobRow!=0) delete fBlobRow; if (fBlobData!=0) delete fBlobData; if (fUnpack!=0) { fUnpack->Delete(); delete fUnpack; } + if (fBlobStmt!=0) delete fBlobStmt; } //______________________________________________________________________________ @@ -175,7 +180,7 @@ Bool_t TSQLObjectData::LocateColumn(const char* colname, Bool_t isblob) if (!isblob) return kTRUE; - if (fBlobRow==0) return kFALSE; + if ((fBlobRow==0) && (fBlobStmt==0)) return kFALSE; fCurrentBlob = kTRUE; @@ -184,28 +189,66 @@ Bool_t TSQLObjectData::LocateColumn(const char* colname, Bool_t isblob) return kTRUE; } +//______________________________________________________________________________ +Bool_t TSQLObjectData::ShiftBlobRow() +{ + // shift cursor to next blob value + + if (fBlobStmt!=0) { + Bool_t res = fBlobStmt->NextResultRow(); + if (!res) { delete fBlobStmt; fBlobStmt = 0; } + return res; + } + + delete fBlobRow; + fBlobRow = fBlobData ? fBlobData->Next() : 0; + return fBlobRow!=0; +} + //______________________________________________________________________________ Bool_t TSQLObjectData::ExtractBlobValues() { - // extract from blob table value and names + // extract from curent blob row value and names identifiers - if (fBlobRow==0) return kFALSE; + const char* name = 0; + + Bool_t hasdata = kFALSE; - fLocatedValue = fBlobRow->GetField(1); + if (fBlobStmt!=0) { + name = fBlobStmt->GetString(0); + fLocatedValue = fBlobStmt->GetString(1); + hasdata = kTRUE; + } - const char* name = fBlobRow->GetField(0); + if (!hasdata) { + if (fBlobRow!=0) { + fLocatedValue = fBlobRow->GetField(1); + name = fBlobRow->GetField(0); + } + } + + if (name==0) { + fBlobPrefixName = 0; + fBlobTypeName = 0; + return kFALSE; + } + const char* separ = strstr(name, ":"); //SQLNameSeparator() if (separ==0) { - fBlobName1 = ""; - fBlobName2 = name; + fBlobPrefixName = 0; + fBlobTypeName = name; } else { - fBlobName1 = ""; - fBlobName1.Append(name, separ-name); + fBlobPrefixName = name; separ+=strlen(":"); //SQLNameSeparator() - fBlobName2 = separ; + fBlobTypeName = separ; } +// if (gDebug>4) +// Info("ExtractBlobValues","Prefix:%s Type:%s", +// (fBlobPrefixName ? fBlobPrefixName : "null"), +// (fBlobTypeName ? fBlobTypeName : "null")); + return kTRUE; } @@ -218,8 +261,8 @@ void TSQLObjectData::AddUnpack(const char* tname, const char* value) TNamed* str = new TNamed(tname, value); if (fUnpack==0) { fUnpack = new TObjArray(); - fBlobName1 = ""; - fBlobName2 = str->GetName(); + fBlobPrefixName = 0; + fBlobTypeName = str->GetName(); fLocatedValue = str->GetTitle(); } @@ -250,8 +293,8 @@ void TSQLObjectData::ShiftToNextValue() fUnpack->Compress(); if (fUnpack->GetLast()>=0) { TNamed* curr = (TNamed*) fUnpack->First(); - fBlobName1 = ""; - fBlobName2 = curr->GetName(); + fBlobPrefixName = 0; + fBlobTypeName = curr->GetName(); fLocatedValue = curr->GetTitle(); return; } @@ -261,10 +304,7 @@ void TSQLObjectData::ShiftToNextValue() } if (fCurrentBlob) { - if (doshift) { - delete fBlobRow; - fBlobRow = fBlobData->Next(); - } + if (doshift) ShiftBlobRow(); ExtractBlobValues(); } else if (fClassData!=0) { @@ -293,9 +333,20 @@ Bool_t TSQLObjectData::VerifyDataType(const char* tname, Bool_t errormsg) // here maybe type of column can be checked if (!IsBlobData()) return kTRUE; - if (fBlobName2!=tname) { + if (gDebug>4) + if (fBlobTypeName==0) { + Error("VerifyDataType","fBlobTypeName is null"); + return kFALSE; + } + + + TString v1(fBlobTypeName); + TString v2(tname); + +// if (strcmp(fBlobTypeName,tname)!=0) { + if (v1!=v2) { if (errormsg) - Error("VerifyDataType","Data type meissmatch %s - %s", fBlobName2.Data(), tname); + Error("VerifyDataType","Data type missmatch %s - %s", fBlobTypeName, tname); return kFALSE; } @@ -316,6 +367,17 @@ Bool_t TSQLObjectData::PrepareForRawData() //=================================================================================== +//________________________________________________________________________ +// +// TSQLObjectDataPool contains list (pool) of data from single class table +// for differents objects, all belonging to the same key. +// This is typical situation when list of objects stored as single key. +// To optimize reading of such data, one query is submitted and results of that +// query kept in TSQLObjectDataPool object +// +//________________________________________________________________________ + + ClassImp(TSQLObjectDataPool); //______________________________________________________________________________ @@ -341,7 +403,9 @@ TSQLObjectDataPool::TSQLObjectDataPool(TSQLClassInfo* info, TSQLResult* data) : //______________________________________________________________________________ TSQLObjectDataPool::~TSQLObjectDataPool() { - //please Sergey: document this function + // Destructor of TSQLObjectDataPool class + // Deletes not used rows and class data table + if (fClassData!=0) delete fClassData; if (fRowsPool!=0) { fRowsPool->Delete(); @@ -352,7 +416,8 @@ TSQLObjectDataPool::~TSQLObjectDataPool() //______________________________________________________________________________ TSQLRow* TSQLObjectDataPool::GetObjectRow(Long64_t objid) { - //please Sergey: document this function + // Returns single sql row with object data for that class + if (fClassData==0) return 0; Long64_t rowid; diff --git a/sql/src/TSQLStructure.cxx b/sql/src/TSQLStructure.cxx index 474ee804aa039011615a0245cf2c0c652ce149ef..0775ac63fc2a293498b666a9541d65efaaf9d81f 100644 --- a/sql/src/TSQLStructure.cxx +++ b/sql/src/TSQLStructure.cxx @@ -1,4 +1,4 @@ -// @(#)root/sql:$Name: $:$Id: TSQLStructure.cxx,v 1.10 2006/05/11 10:29:45 brun Exp $ +// @(#)root/sql:$Name: $:$Id: TSQLStructure.cxx,v 1.11 2006/05/12 08:17:02 brun Exp $ // Author: Sergey Linev 20/11/2005 /************************************************************************* @@ -36,6 +36,10 @@ #include "TSQLObjectData.h" #include "TBufferSQL2.h" +#include "TSQLStatement.h" +#include "TSQLServer.h" +#include "TDataType.h" + namespace sqlio { const Int_t Ids_NullPtr = 0; // used to identify NULL pointer in tables const Int_t Ids_RootDir = 0; // dir:id, used for keys stored in root directory. @@ -300,7 +304,8 @@ void TSQLStructure::SetStreamerElement(const TStreamerElement* elem, Int_t numbe //________________________________________________________________________ void TSQLStructure::SetCustomClass(const TClass* cl, Version_t version) { - //please Sergey: document this function + // set structure type as kSqlCustomClass + fType = kSqlCustomClass; fPointer = (void*) cl; fArrayIndex = version; @@ -309,7 +314,8 @@ void TSQLStructure::SetCustomClass(const TClass* cl, Version_t version) //________________________________________________________________________ void TSQLStructure::SetCustomElement(TStreamerElement* elem) { - //please Sergey: document this function + // set structure type as kSqlCustomElement + fType = kSqlCustomElement; fPointer = elem; } @@ -412,21 +418,24 @@ const char* TSQLStructure::GetValueType() const //________________________________________________________________________ TClass* TSQLStructure::GetCustomClass() const { - //please Sergey: document this function + // return element custom class if strutures is kSqlCustomClass + return (fType==kSqlCustomClass) ? (TClass*) fPointer : 0; } //________________________________________________________________________ Version_t TSQLStructure::GetCustomClassVersion() const { - //please Sergey: document this function + // return custom class version if strutures is kSqlCustomClass + return (fType==kSqlCustomClass) ? fArrayIndex : 0; } //________________________________________________________________________ Bool_t TSQLStructure::GetClassInfo(TClass* &cl, Version_t &version) { - //please Sergey: document this function + // provides class info if structure kSqlStreamerInfo or kSqlCustomClass + if (GetType()==kSqlStreamerInfo) { TStreamerInfo* info = GetStreamerInfo(); if (info==0) return kFALSE; @@ -492,6 +501,7 @@ Long64_t TSQLStructure::DefineObjectId(Bool_t recursive) TSQLStructure* curr = this; while (curr!=0) { if ((curr->GetType()==kSqlObject) || + (curr->GetType()==kSqlPointer) || // workaround to store object id in element structure (curr->GetType()==kSqlElement) || (curr->GetType()==kSqlCustomElement) || @@ -675,7 +685,9 @@ class TSqlCmdsBuffer : public TObject { public: TSqlCmdsBuffer(TSQLClassInfo* info = 0) : TObject(), - fInfo(info) + fInfo(info), + fBlobStmt(0), + fNormStmt(0) { } @@ -683,6 +695,8 @@ public: { fNormCmds.Delete(); fBlobCmds.Delete(); + if (fBlobStmt!=0) delete fBlobStmt; + if (fNormStmt!=0) delete fNormStmt; } void AddValues(Bool_t isnorm, const char* values) @@ -695,6 +709,8 @@ public: TSQLClassInfo* fInfo; TObjArray fNormCmds; TObjArray fBlobCmds; + TSQLStatement* fBlobStmt; + TSQLStatement* fNormStmt; }; @@ -715,7 +731,8 @@ public: fLastLongStrId(0), fPool(), fLongStrValues(), - fRegValues() + fRegValues(), + fRegStmt(0) { } @@ -733,12 +750,16 @@ public: TMap fPool; TObjArray fLongStrValues; TObjArray fRegValues; + + TSQLStatement* fRegStmt; + virtual ~TSqlRegistry() { fPool.DeleteValues(); fLongStrValues.Delete(); fRegValues.Delete(); + if (fRegStmt) delete fRegStmt; } Long64_t GetNextObjId() { return ++fLastObjId; } @@ -807,10 +828,15 @@ public: if (buf==0) continue; ConvertSqlValues(buf->fNormCmds, sqlinfo->GetClassTableName()); ConvertSqlValues(buf->fBlobCmds, sqlinfo->GetRawTableName()); + if (buf->fBlobStmt) + buf->fBlobStmt->Process(); + if (buf->fNormStmt) + buf->fNormStmt->Process(); } ConvertSqlValues(fLongStrValues, sqlio::StringsTable); ConvertSqlValues(fRegValues, sqlio::ObjectsTable); + if (fRegStmt) fRegStmt->Process(); } @@ -821,6 +847,27 @@ public: Error("AddRegCmd","Something wrong with objid = %lld", objid); return; } + + if (f->IsOracle()) { + if (fRegStmt==0) { + const char* quote = f->SQLIdentifierQuote(); + TString sqlcmd; + sqlcmd.Form("INSERT INTO %s%s%s VALUES (:1, :2, :3, :4)", + quote, sqlio::ObjectsTable, quote); + fRegStmt = f->fSQL->Statement(sqlcmd.Data(), 1000); + f->fQuerisCounter++; + } + + fRegStmt->NextIteration(); + + fRegStmt->SetLong64(0, fKeyId); + fRegStmt->SetLong64(1, objid); + fRegStmt->SetString(2, cl->GetName()); + fRegStmt->SetInt(3, cl->GetClassVersion()); + + return; + } + const char* valuequote = f->SQLValueQuote(); TString cmd; cmd.Form("%lld, %lld, %s%s%s, %d", @@ -848,12 +895,83 @@ public: return strid; } + + void ConvertBlobsOracle(TObjArray* blobs, TSQLClassInfo* sqlinfo, Int_t& rawid) + { + TSqlCmdsBuffer* buf = GetCmdsBuffer(sqlinfo); + if (buf==0) return; + + TSQLStatement* stmt = buf->fBlobStmt; + if (stmt==0) { + const char* quote = f->SQLIdentifierQuote(); + TString sqlcmd; + sqlcmd.Form("INSERT INTO %s%s%s VALUES (:1, :2, :3, :4)", + quote, sqlinfo->GetRawTableName(), quote); + stmt = f->fSQL->Statement(sqlcmd.Data(), 2000); + f->fQuerisCounter++; + buf->fBlobStmt = stmt; + } - void ConvertBlobs(TObjArray* blobs, TSQLClassInfo* sqlinfo, Int_t& rawid) + TIter iter(blobs); + TNamed* cmd = 0; + + while ((cmd = (TNamed*)iter())!=0) { + stmt->NextIteration(); + + stmt->SetLong64(0, fCurrentObjId); + stmt->SetInt(1, rawid); + stmt->SetString(2, cmd->GetName()); + stmt->SetString(3, cmd->GetTitle()); + + rawid++; + } + } + + void InsertToNormalTableOracle(TObjArray* columns, TSQLClassInfo* sqlinfo) { TSqlCmdsBuffer* buf = GetCmdsBuffer(sqlinfo); if (buf==0) return; + + TSQLStatement* stmt = buf->fNormStmt; + if (stmt==0) { + const char* quote = f->SQLIdentifierQuote(); + TString sqlcmd; + sqlcmd.Form("INSERT INTO %s%s%s VALUES (:", + quote, sqlinfo->GetClassTableName(), quote); + for (int n=0;n<=columns->GetLast();n++) { + if (n>0) sqlcmd +=", :"; + sqlcmd += (n+1); + } + sqlcmd += ")"; + + stmt = f->fSQL->Statement(sqlcmd.Data(), 1000); + f->fQuerisCounter++; + buf->fNormStmt = stmt; + } + + stmt->NextIteration(); + + TIter iter(columns); + TSQLColumnData* col; + Int_t ncol = 0; + while ((col=(TSQLColumnData*)iter())!=0) { + const char* value = col->GetValue(); + stmt->SetString(ncol, value); + ncol++; + } + } + + void ConvertBlobs(TObjArray* blobs, TSQLClassInfo* sqlinfo, Int_t& rawid) + { + if (f->IsOracle()) { + ConvertBlobsOracle(blobs, sqlinfo, rawid); + return; + } + + TSqlCmdsBuffer* buf = GetCmdsBuffer(sqlinfo); + if (buf==0) return; + TString value, onecmd, cmdmask; const char* valuequote = f->SQLValueQuote(); @@ -874,17 +992,22 @@ public: { // produce SQL query to insert object data into normal table + if (f->IsOracle()) { + InsertToNormalTableOracle(columns, sqlinfo); + return; + } + TIter iter(columns); TSQLColumnData* col; const char* valuequote = f->SQLValueQuote(); TString values; - + Bool_t first = kTRUE; while ((col=(TSQLColumnData*)iter())!=0) { - if (first) first = kFALSE; - else values+=", "; + if (first) first = kFALSE; + else values+=", "; if (col->IsNumeric()) values+=col->GetValue(); else { @@ -893,10 +1016,9 @@ public: values += value; } } - + TSqlCmdsBuffer* buf = GetCmdsBuffer(sqlinfo); if (buf!=0) buf->AddValues(kTRUE, values.Data()); - } }; @@ -1108,9 +1230,9 @@ Bool_t TSQLStructure::StoreObject(TSqlRegistry* reg, Long64_t objid, TClass* cl, res = kFALSE; else { sqlinfo = reg->f->RequestSQLClassInfo(cl); + reg->f->SyncSQLClassInfo(sqlinfo, 0, kTRUE); Int_t currrawid = 0; reg->ConvertBlobs(&objblobs, sqlinfo, currrawid); - reg->f->SyncSQLClassInfo(sqlinfo, 0, kTRUE); } objblobs.Delete(); @@ -1193,6 +1315,7 @@ Bool_t TSQLStructure::StoreClassInNormalForm(TSqlRegistry* reg) Int_t blobid = -1; if (blobs.GetLast()>=0) { + reg->f->SyncSQLClassInfoRawTables(sqlinfo, kTRUE); blobid = currrawid; // column will contain first raw id reg->ConvertBlobs(&blobs, sqlinfo, currrawid); needblob = kTRUE; @@ -1327,8 +1450,10 @@ Bool_t TSQLStructure::StoreElementInNormalForm(TSqlRegistry* reg, TObjArray* col Long64_t objid = -1; if (child->GetType()==kSqlObject) { - objid = child->DefineObjectId(kFALSE); + objid = child->DefineObjectId(kFALSE); normal = child->StoreObject(reg, objid, child->GetObjectClass()); + } else { + objid = child->DefineObjectId(kFALSE); } if (!normal) {