#include "TSQLStructure.h"
#include "Riostream.h"
#include "TMap.h"
#include "TClass.h"
#include "TStreamerInfo.h"
#include "TStreamerElement.h"
#include "TObjString.h"
#include "TClonesArray.h"
#include "TSQLFile.h"
#include "TSQLClassInfo.h"
#include "TSQLObjectData.h"
#include "TBufferSQL2.h"
#include "TSQLStatement.h"
#include "TSQLServer.h"
#include "TDataType.h"
namespace sqlio {
const Int_t Ids_NullPtr = 0;
const Int_t Ids_RootDir = 0;
const Int_t Ids_TSQLFile = 0;
const Int_t Ids_StreamerInfos = 1;
const Int_t Ids_FirstKey =10;
const Int_t Ids_FirstObject = 1;
const char* ObjectRef = "ObjectRef";
const char* ObjectRef_Arr = "ObjectRefArr";
const char* ObjectPtr = "ObjectPtr";
const char* ObjectInst = "ObjectInst";
const char* Version = "Version";
const char* TObjectUniqueId = "UniqueId";
const char* TObjectBits = "Bits";
const char* TObjectProcessId = "ProcessId";
const char* TStringValue= "StringValue";
const char* IndexSepar = "..";
const char* RawSuffix = ":rawdata";
const char* ParentSuffix = ":parent";
const char* ObjectSuffix = ":object";
const char* PointerSuffix = ":pointer";
const char* StrSuffix = ":str";
const char* LongStrPrefix = "#~#";
const char* Array = "Array";
const char* Bool = "Bool_t";
const char* Char = "Char_t";
const char* Short = "Short_t";
const char* Int = "Int_t";
const char* Long = "Long_t";
const char* Long64 = "Long64_t";
const char* Float = "Float_t";
const char* Double = "Double_t";
const char* UChar = "UChar_t";
const char* UShort = "UShort_t";
const char* UInt = "UInt_t";
const char* ULong = "ULong_t";
const char* ULong64 = "ULong64_t";
const char* CharStar = "CharStar";
const char* True = "1";
const char* False = "0";
const char* KeysTable = "KeysTable";
const char* KeysTableIndex = "KeysTableIndex";
const char* ObjectsTable = "ObjectsTable";
const char* ObjectsTableIndex = "ObjectsTableIndex";
const char* IdsTable = "IdsTable";
const char* IdsTableIndex = "IdsTableIndex";
const char* StringsTable = "StringsTable";
const char* ConfigTable = "Configurations";
const char* KT_Name = "Name";
const char* KT_Title = "Title";
const char* KT_Datetime = "Datime";
const char* KT_Cycle = "Cycle";
const char* KT_Class = "Class";
const char* DT_Create = "CreateDatime";
const char* DT_Modified = "ModifiedDatime";
const char* DT_UUID = "UUID";
const char* OT_Class = "Class";
const char* OT_Version = "Version";
const char* IT_TableID = "TableId";
const char* IT_SubID = "SubId";
const char* IT_Type = "Type";
const char* IT_FullName = "FullName";
const char* IT_SQLName = "SQLName";
const char* IT_Info = "Info";
const char* BT_Field = "Field";
const char* BT_Value = "Value";
const char* ST_Value = "LongStringValue";
const char* CT_Field = "Field";
const char* CT_Value = "Value";
const char* cfg_Version = "SQL_IO_version";
const char* cfg_UseSufixes = "UseNameSuffix";
const char* cfg_ArrayLimit = "ArraySizeLimit";
const char* cfg_TablesType = "TablesType";
const char* cfg_UseTransactions = "UseTransactions";
const char* cfg_UseIndexes = "UseIndexes";
const char* cfg_LockingMode = "LockingMode";
const char* cfg_ModifyCounter = "ModifyCounter";
};
#ifdef R__VISUAL_CPLUSPLUS
#define FLong64 "%I64d"
#define FULong64 "%I64u"
#else
#define FLong64 "%lld"
#define FULong64 "%llu"
#endif
Long64_t sqlio::atol64(const char* value)
{
if ((value==0) || (*value==0)) return 0;
Long64_t res = 0;
sscanf(value, FLong64, &res);
return res;
}
ClassImp(TSQLColumnData)
TSQLColumnData::TSQLColumnData() :
TObject(),
fName(),
fType(),
fValue(),
fNumeric(kFALSE)
{
}
TSQLColumnData::TSQLColumnData(const char* name,
const char* sqltype,
const char* value,
Bool_t numeric) :
TObject(),
fName(name),
fType(sqltype),
fValue(value),
fNumeric(numeric)
{
}
TSQLColumnData::TSQLColumnData(const char* name, Long64_t value) :
TObject(),
fName(name),
fType("INT"),
fValue(),
fNumeric(kTRUE)
{
fValue.Form("%lld",value);
}
TSQLColumnData::~TSQLColumnData()
{
}
ClassImp(TSQLTableData);
TSQLTableData::TSQLTableData(TSQLFile* f, TSQLClassInfo* info) :
TObject(),
fFile(f),
fInfo(info),
fColumns(),
fColInfos(0)
{
if (!info->IsClassTableExist())
fColInfos = new TObjArray;
}
TSQLTableData::~TSQLTableData()
{
fColumns.Delete();
if (fColInfos!=0) {
fColInfos->Delete();
delete fColInfos;
}
}
void TSQLTableData::AddColumn(const char* name, Long64_t value)
{
TObjString* v = new TObjString(Form("%lld",value));
v->SetBit(BIT(20), kTRUE);
fColumns.Add(v);
if (fColInfos!=0)
fColInfos->Add(new TSQLClassColumnInfo(name, DefineSQLName(name), "INT"));
}
void TSQLTableData::AddColumn(const char* name,
const char* sqltype,
const char* value,
Bool_t numeric)
{
TObjString* v = new TObjString(value);
v->SetBit(BIT(20), numeric);
fColumns.Add(v);
if (fColInfos!=0)
fColInfos->Add(new TSQLClassColumnInfo(name, DefineSQLName(name), sqltype));
}
TString TSQLTableData::DefineSQLName(const char* fullname)
{
Int_t maxlen = fFile->SQLMaxIdentifierLength();
Int_t len = strlen(fullname);
if ((len<=maxlen) && !HasSQLName(fullname)) return TString(fullname);
Int_t cnt = -1;
TString res, scnt;
do {
scnt.Form("%d",cnt);
Int_t numlen = cnt<0 ? 0 : scnt.Length();
res = fullname;
if (len + numlen > maxlen)
res.Resize(maxlen - numlen);
if (cnt>=0) res+=scnt;
if (!HasSQLName(res.Data())) return res;
cnt++;
} while (cnt<10000);
Error("DefineSQLName","Cannot find reasonable column name for field %s",fullname);
return TString(fullname);
}
Bool_t TSQLTableData::HasSQLName(const char* sqlname)
{
TIter next(fColInfos);
TSQLClassColumnInfo* col = 0;
while ((col = (TSQLClassColumnInfo*) next()) != 0) {
const char* colname = col->GetSQLName();
if (strcmp(colname, sqlname)==0) return kTRUE;
}
return kFALSE;
}
Int_t TSQLTableData::GetNumColumns()
{
return fColumns.GetLast() +1;
}
const char* TSQLTableData::GetColumn(Int_t n)
{
return fColumns[n]->GetName();
}
Bool_t TSQLTableData::IsNumeric(Int_t n)
{
return fColumns[n]->TestBit(BIT(20));
}
TObjArray* TSQLTableData::TakeColInfos()
{
TObjArray* res = fColInfos;
fColInfos = 0;
return res;
}
ClassImp(TSQLStructure);
TSQLStructure::TSQLStructure() :
TObject(),
fParent(0),
fType(0),
fPointer(0),
fValue(),
fArrayIndex(-1),
fRepeatCnt(0),
fChilds()
{
}
TSQLStructure::~TSQLStructure()
{
fChilds.Delete();
if (GetType()==kSqlObjectData) {
TSQLObjectData* objdata = (TSQLObjectData*) fPointer;
delete objdata;
} else
if (GetType()==kSqlCustomElement) {
TStreamerElement* elem = (TStreamerElement*) fPointer;
delete elem;
}
}
Int_t TSQLStructure::NumChilds() const
{
return fChilds.GetLast()+1;
}
TSQLStructure* TSQLStructure::GetChild(Int_t n) const
{
return (n<0) || (n>fChilds.GetLast()) ? 0 : (TSQLStructure*) fChilds[n];
}
void TSQLStructure::SetObjectRef(Long64_t refid, const TClass* cl)
{
fType = kSqlObject;
fValue.Form("%lld",refid);
fPointer = cl;
}
void TSQLStructure::SetObjectPointer(Long64_t ptrid)
{
fType = kSqlPointer;
fValue.Form("%lld",ptrid);
}
void TSQLStructure::SetVersion(const TClass* cl, Int_t version)
{
fType = kSqlVersion;
fPointer = cl;
if (version<0) version = cl->GetClassVersion();
fValue.Form("%d",version);
}
void TSQLStructure::SetClassStreamer(const TClass* cl)
{
fType = kSqlClassStreamer;
fPointer = cl;
}
void TSQLStructure::SetStreamerInfo(const TStreamerInfo* info)
{
fType = kSqlStreamerInfo;
fPointer = info;
}
void TSQLStructure::SetStreamerElement(const TStreamerElement* elem, Int_t number)
{
fType = kSqlElement;
fPointer = elem;
fArrayIndex = number;
}
void TSQLStructure::SetCustomClass(const TClass* cl, Version_t version)
{
fType = kSqlCustomClass;
fPointer = (void*) cl;
fArrayIndex = version;
}
void TSQLStructure::SetCustomElement(TStreamerElement* elem)
{
fType = kSqlCustomElement;
fPointer = elem;
}
void TSQLStructure::SetValue(const char* value, const char* tname)
{
fType = kSqlValue;
fValue = value;
fPointer = tname;
}
void TSQLStructure::ChangeValueOnly(const char* value)
{
fValue = value;
}
void TSQLStructure::SetArrayIndex(Int_t indx, Int_t cnt)
{
fArrayIndex = indx;
fRepeatCnt = cnt;
}
void TSQLStructure::ChildArrayIndex(Int_t index, Int_t cnt)
{
TSQLStructure* last = (TSQLStructure*) fChilds.Last();
if ((last!=0) && (last->GetType()==kSqlValue))
last->SetArrayIndex(index, cnt);
}
void TSQLStructure::SetArray(Int_t sz)
{
fType = kSqlArray;
if (sz>=0) fValue.Form("%d",sz);
}
TClass* TSQLStructure::GetObjectClass() const
{
return (fType==kSqlObject) ? (TClass*) fPointer : 0;
}
TClass* TSQLStructure::GetVersionClass() const
{
return (fType==kSqlVersion) ? (TClass*) fPointer : 0;
}
TStreamerInfo* TSQLStructure::GetStreamerInfo() const
{
return (fType==kSqlStreamerInfo) ? (TStreamerInfo*) fPointer : 0;
}
TStreamerElement* TSQLStructure::GetElement() const
{
return (fType==kSqlElement) || (fType==kSqlCustomElement) ? (TStreamerElement*) fPointer : 0;
}
Int_t TSQLStructure::GetElementNumber() const
{
return (fType==kSqlElement) ? fArrayIndex : 0;
}
const char* TSQLStructure::GetValueType() const
{
return (fType==kSqlValue) ? (const char*) fPointer : 0;
}
TClass* TSQLStructure::GetCustomClass() const
{
return (fType==kSqlCustomClass) ? (TClass*) fPointer : 0;
}
Version_t TSQLStructure::GetCustomClassVersion() const
{
return (fType==kSqlCustomClass) ? fArrayIndex : 0;
}
Bool_t TSQLStructure::GetClassInfo(TClass* &cl, Version_t &version)
{
if (GetType()==kSqlStreamerInfo) {
TStreamerInfo* info = GetStreamerInfo();
if (info==0) return kFALSE;
cl = info->GetClass();
version = info->GetClassVersion();
} else
if (GetType()==kSqlCustomClass) {
cl = GetCustomClass();
version = GetCustomClassVersion();
} else
return kFALSE;
return kTRUE;
}
const char* TSQLStructure::GetValue() const
{
return fValue.Data();
}
void TSQLStructure::Add(TSQLStructure* child)
{
if (child!=0) {
child->SetParent(this);
fChilds.Add(child);
}
}
void TSQLStructure::AddVersion(const TClass* cl, Int_t version)
{
TSQLStructure* ver = new TSQLStructure;
ver->SetVersion(cl, version);
Add(ver);
}
void TSQLStructure::AddValue(const char* value, const char* tname)
{
TSQLStructure* child = new TSQLStructure;
child->SetValue(value, tname);
Add(child);
}
Long64_t TSQLStructure::DefineObjectId(Bool_t recursive)
{
TSQLStructure* curr = this;
while (curr!=0) {
if ((curr->GetType()==kSqlObject) ||
(curr->GetType()==kSqlPointer) ||
(curr->GetType()==kSqlElement) ||
(curr->GetType()==kSqlCustomElement) ||
(curr->GetType()==kSqlCustomClass) ||
(curr->GetType()==kSqlStreamerInfo)) {
const char* value = curr->GetValue();
if ((value!=0) && (strlen(value)>0))
return sqlio::atol64(value);
}
curr = recursive ? curr->GetParent() : 0;
}
return -1;
}
void TSQLStructure::SetObjectData(TSQLObjectData* objdata)
{
fType = kSqlObjectData;
fPointer = objdata;
}
void TSQLStructure::AddObjectData(TSQLObjectData* objdata)
{
TSQLStructure* child = new TSQLStructure;
child->SetObjectData(objdata);
Add(child);
}
TSQLObjectData* TSQLStructure::GetObjectData(Bool_t search)
{
TSQLStructure* child = GetChild(0);
if ((child!=0) && (child->GetType()==kSqlObjectData))
return (TSQLObjectData*) child->fPointer;
if (search && (GetParent()!=0))
return GetParent()->GetObjectData(search);
return 0;
}
void TSQLStructure::Print(Option_t*) const
{
PrintLevel(0);
}
void TSQLStructure::PrintLevel(Int_t level) const
{
for(Int_t n=0;n<level;n++) cout << " ";
switch (fType) {
case 0: cout << "Undefined type"; break;
case kSqlObject: cout << "Object ref = " << fValue; break;
case kSqlPointer: cout << "Pointer ptr = " << fValue; break;
case kSqlVersion: {
const TClass* cl = (const TClass*) fPointer;
cout << "Version cl = " << cl->GetName() << " ver = " << cl->GetClassVersion();
break;
}
case kSqlStreamerInfo: {
const TStreamerInfo* info = (const TStreamerInfo*) fPointer;
cout << "Class: " << info->GetName();
break;
}
case kSqlCustomElement:
case kSqlElement: {
const TStreamerElement* elem = (const TStreamerElement*) fPointer;
cout << "Member: " << elem->GetName();
break;
}
case kSqlValue: {
cout << "Value: " << fValue;
if (fRepeatCnt>1) cout << " cnt:" << fRepeatCnt;
if (fPointer!=0) cout << " type = " << (const char*)fPointer;
break;
}
case kSqlArray: {
cout << "Array ";
if (fValue.Length()>0) cout << " sz = " << fValue;
break;
}
case kSqlCustomClass: {
TClass* cl = (TClass*) fPointer;
cout << "CustomClass: " << cl->GetName() << " ver = " << fValue;
break;
}
default:
cout << "Unknown type";
}
cout << endl;
for(Int_t n=0;n<NumChilds();n++)
GetChild(n)->PrintLevel(level+2);
}
Bool_t TSQLStructure::IsNumericType(Int_t typ)
{
switch(typ) {
case TStreamerInfo::kShort : return kTRUE;
case TStreamerInfo::kInt : return kTRUE;
case TStreamerInfo::kLong : return kTRUE;
case TStreamerInfo::kFloat : return kTRUE;
case TStreamerInfo::kFloat16 : return kTRUE;
case TStreamerInfo::kCounter : return kTRUE;
case TStreamerInfo::kDouble : return kTRUE;
case TStreamerInfo::kDouble32: return kTRUE;
case TStreamerInfo::kUChar : return kTRUE;
case TStreamerInfo::kUShort : return kTRUE;
case TStreamerInfo::kUInt : return kTRUE;
case TStreamerInfo::kULong : return kTRUE;
case TStreamerInfo::kBits : return kTRUE;
case TStreamerInfo::kLong64 : return kTRUE;
case TStreamerInfo::kULong64 : return kTRUE;
case TStreamerInfo::kBool : return kTRUE;
}
return kFALSE;
}
const char* TSQLStructure::GetSimpleTypeName(Int_t typ)
{
switch(typ) {
case TStreamerInfo::kChar : return sqlio::Char;
case TStreamerInfo::kShort : return sqlio::Short;
case TStreamerInfo::kInt : return sqlio::Int;
case TStreamerInfo::kLong : return sqlio::Long;
case TStreamerInfo::kFloat : return sqlio::Float;
case TStreamerInfo::kFloat16 : return sqlio::Float;
case TStreamerInfo::kCounter : return sqlio::Int;
case TStreamerInfo::kDouble : return sqlio::Double;
case TStreamerInfo::kDouble32: return sqlio::Double;
case TStreamerInfo::kUChar : return sqlio::UChar;
case TStreamerInfo::kUShort : return sqlio::UShort;
case TStreamerInfo::kUInt : return sqlio::UInt;
case TStreamerInfo::kULong : return sqlio::ULong;
case TStreamerInfo::kBits : return sqlio::UInt;
case TStreamerInfo::kLong64 : return sqlio::Long64;
case TStreamerInfo::kULong64 : return sqlio::ULong64;
case TStreamerInfo::kBool : return sqlio::Bool;
}
return 0;
}
class TSqlCmdsBuffer : public TObject {
public:
TSqlCmdsBuffer(TSQLFile* f, TSQLClassInfo* info) :
TObject(),
fFile(f),
fInfo(info),
fBlobStmt(0),
fNormStmt(0)
{
}
virtual ~TSqlCmdsBuffer()
{
fNormCmds.Delete();
fBlobCmds.Delete();
fFile->SQLDeleteStatement(fBlobStmt);
fFile->SQLDeleteStatement(fNormStmt);
}
void AddValues(Bool_t isnorm, const char* values)
{
TObjString* str = new TObjString(values);
if (isnorm) fNormCmds.Add(str);
else fBlobCmds.Add(str);
}
TSQLFile* fFile;
TSQLClassInfo* fInfo;
TObjArray fNormCmds;
TObjArray fBlobCmds;
TSQLStatement* fBlobStmt;
TSQLStatement* fNormStmt;
};
class TSqlRegistry : public TObject {
public:
TSqlRegistry() :
TObject(),
f(0),
fKeyId(0),
fLastObjId(-1),
fCmds(0),
fFirstObjId(0),
fCurrentObjId(0),
fCurrentObjClass(0),
fLastLongStrId(0),
fPool(),
fLongStrValues(),
fRegValues(),
fRegStmt(0)
{
}
TSQLFile* f;
Long64_t fKeyId;
Long64_t fLastObjId;
TObjArray* fCmds;
Long64_t fFirstObjId;
Long64_t fCurrentObjId;
TClass* fCurrentObjClass;
Int_t fLastLongStrId;
TMap fPool;
TObjArray fLongStrValues;
TObjArray fRegValues;
TSQLStatement* fRegStmt;
virtual ~TSqlRegistry()
{
fPool.DeleteValues();
fLongStrValues.Delete();
fRegValues.Delete();
f->SQLDeleteStatement(fRegStmt);
}
Long64_t GetNextObjId() { return ++fLastObjId; }
void AddSqlCmd(const char* query)
{
if (fCmds==0) fCmds = new TObjArray;
fCmds->Add(new TObjString(query));
}
TSqlCmdsBuffer* GetCmdsBuffer(TSQLClassInfo* sqlinfo)
{
if (sqlinfo==0) return 0;
TSqlCmdsBuffer* buf = (TSqlCmdsBuffer*) fPool.GetValue(sqlinfo);
if (buf==0) {
buf = new TSqlCmdsBuffer(f, sqlinfo);
fPool.Add(sqlinfo, buf);
}
return buf;
}
void ConvertSqlValues(TObjArray& values, const char* tablename)
{
if ((values.GetLast()<0) || (tablename==0)) return;
Bool_t canbelong = f->IsMySQL();
Int_t maxsize = 50000;
TString sqlcmd(maxsize), value, onecmd, cmdmask;
const char* quote = f->SQLIdentifierQuote();
TIter iter(&values);
TObject* cmd = 0;
while ((cmd = iter())!=0) {
if (sqlcmd.Length()==0)
sqlcmd.Form("INSERT INTO %s%s%s VALUES (%s)",
quote, tablename, quote, cmd->GetName());
else {
sqlcmd+=", (";
sqlcmd += cmd->GetName();
sqlcmd+=")";
}
if (!canbelong || (sqlcmd.Length()>maxsize*0.9)) {
AddSqlCmd(sqlcmd.Data());
sqlcmd = "";
}
}
if (sqlcmd.Length()>0) AddSqlCmd(sqlcmd.Data());
}
void ConvertPoolValues()
{
TSQLClassInfo* sqlinfo = 0;
TIter iter(&fPool);
while ((sqlinfo = (TSQLClassInfo*) iter())!=0) {
TSqlCmdsBuffer* buf = (TSqlCmdsBuffer*) fPool.GetValue(sqlinfo);
if (buf==0) continue;
ConvertSqlValues(buf->fNormCmds, sqlinfo->GetClassTableName());
if (buf->fBlobCmds.GetLast()>=0) f->CreateRawTable(sqlinfo);
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();
}
void AddRegCmd(Long64_t objid, TClass* cl)
{
Long64_t indx = objid-fFirstObjId;
if (indx<0) {
Error("AddRegCmd","Something wrong with objid = %lld", objid);
return;
}
if (f->IsOracle() || f->IsODBC()) {
if ((fRegStmt==0) && f->SQLCanStatement()) {
const char* quote = f->SQLIdentifierQuote();
TString sqlcmd;
const char* pars = f->IsOracle() ? ":1, :2, :3, :4" : "?, ?, ?, ?";
sqlcmd.Form("INSERT INTO %s%s%s VALUES (%s)",
quote, sqlio::ObjectsTable, quote, pars);
fRegStmt = f->SQLStatement(sqlcmd.Data(), 1000);
}
if (fRegStmt!=0) {
fRegStmt->NextIteration();
fRegStmt->SetLong64(0, fKeyId);
fRegStmt->SetLong64(1, objid);
fRegStmt->SetString(2, cl->GetName(), f->SQLSmallTextTypeLimit());
fRegStmt->SetInt(3, cl->GetClassVersion());
return;
}
}
const char* valuequote = f->SQLValueQuote();
TString cmd;
cmd.Form("%lld, %lld, %s%s%s, %d",
fKeyId, objid,
valuequote, cl->GetName(), valuequote,
cl->GetClassVersion());
fRegValues.AddAtAndExpand(new TObjString(cmd), indx);
}
Int_t AddLongString(const char* strvalue)
{
if (fLastLongStrId==0) f->VerifyLongStringTable();
Int_t strid = ++fLastLongStrId;
TString value = strvalue;
const char* valuequote = f->SQLValueQuote();
TSQLStructure::AddStrBrackets(value, valuequote);
TString cmd;
cmd.Form("%lld, %d, %s", fCurrentObjId, strid, value.Data());
fLongStrValues.Add(new TObjString(cmd));
return strid;
}
Bool_t InsertToNormalTableOracle(TSQLTableData* columns, TSQLClassInfo* sqlinfo)
{
TSqlCmdsBuffer* buf = GetCmdsBuffer(sqlinfo);
if (buf==0) return kFALSE;
TSQLStatement* stmt = buf->fNormStmt;
if (stmt==0) {
if (!f->SQLCanStatement()) return kFALSE;
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->GetNumColumns();n++) {
if (n>0) sqlcmd +=", ";
if (f->IsOracle()) {
sqlcmd += ":";
sqlcmd += (n+1);
} else
sqlcmd += "?";
}
sqlcmd += ")";
stmt = f->SQLStatement(sqlcmd.Data(), 1000);
if (stmt==0) return kFALSE;
buf->fNormStmt = stmt;
}
stmt->NextIteration();
Int_t sizelimit = f->SQLSmallTextTypeLimit();
for (Int_t ncol=0;ncol<columns->GetNumColumns();ncol++) {
const char* value = columns->GetColumn(ncol);
if (value==0) value = "";
stmt->SetString(ncol, value, sizelimit);
}
return kTRUE;
}
void InsertToNormalTable(TSQLTableData* columns, TSQLClassInfo* sqlinfo)
{
if (f->IsOracle() || f->IsODBC())
if (InsertToNormalTableOracle(columns, sqlinfo))
return;
const char* valuequote = f->SQLValueQuote();
TString values;
for (Int_t n=0;n<columns->GetNumColumns();n++) {
if (n>0) values+=", ";
if (columns->IsNumeric(n))
values+=columns->GetColumn(n);
else {
TString value = columns->GetColumn(n);
TSQLStructure::AddStrBrackets(value, valuequote);
values += value;
}
}
TSqlCmdsBuffer* buf = GetCmdsBuffer(sqlinfo);
if (buf!=0) buf->AddValues(kTRUE, values.Data());
}
};
class TSqlRawBuffer : public TObject {
public:
TSqlRawBuffer(TSqlRegistry* reg, TSQLClassInfo* sqlinfo) :
TObject(),
fFile(0),
fInfo(0),
fCmdBuf(0),
fObjId(0),
fRawId(0),
fValueMask(),
fValueQuote(0),
fMaxStrSize(255)
{
fFile = reg->f;
fInfo = sqlinfo;
fCmdBuf = reg->GetCmdsBuffer(sqlinfo);
fObjId = reg->fCurrentObjId;
fValueQuote = fFile->SQLValueQuote();
fValueMask.Form("%lld, %s, %s%s%s, %s", fObjId, "%d", fValueQuote, "%s", fValueQuote, "%s");
fMaxStrSize = reg->f->SQLSmallTextTypeLimit();
}
virtual ~TSqlRawBuffer()
{
TSQLStatement* stmt = fCmdBuf->fBlobStmt;
if ((stmt!=0) && fFile->IsOracle()) {
stmt->Process();
delete stmt;
fCmdBuf->fBlobStmt = 0;
}
}
Bool_t IsAnyData() const { return fRawId>0; }
void AddLine(const char* name, const char* value, const char* topname = 0, const char* ns = 0)
{
if (fCmdBuf==0) return;
if (fRawId==0) {
Bool_t maketmt = kFALSE;
if (fFile->IsOracle() || fFile->IsODBC())
maketmt = (fCmdBuf->fBlobStmt==0) && fFile->SQLCanStatement();
if (maketmt) {
fFile->CreateRawTable(fInfo);
const char* quote = fFile->SQLIdentifierQuote();
TString sqlcmd;
const char* params = fFile->IsOracle() ? ":1, :2, :3, :4" : "?, ?, ?, ?";
sqlcmd.Form("INSERT INTO %s%s%s VALUES (%s)",
quote, fInfo->GetRawTableName(), quote, params);
TSQLStatement* stmt = fFile->SQLStatement(sqlcmd.Data(), 2000);
fCmdBuf->fBlobStmt = stmt;
}
}
TString buf;
const char* fullname = name;
if ((topname!=0) && (ns!=0)) {
buf+=topname;
buf+=ns;
buf+=name;
fullname = buf.Data();
}
TSQLStatement* stmt = fCmdBuf->fBlobStmt;
if (stmt!=0) {
stmt->NextIteration();
stmt->SetLong64(0, fObjId);
stmt->SetInt(1, fRawId++);
stmt->SetString(2, fullname, fMaxStrSize);
stmt->SetString(3, value, fMaxStrSize);
} else {
TString valuebuf(value);
TSQLStructure::AddStrBrackets(valuebuf, fValueQuote);
TString cmd;
cmd.Form(fValueMask.Data(), fRawId++, fullname, valuebuf.Data());
fCmdBuf->AddValues(kFALSE, cmd.Data());
}
}
TSQLFile* fFile;
TSQLClassInfo* fInfo;
TSqlCmdsBuffer* fCmdBuf;
Long64_t fObjId;
Int_t fRawId;
TString fValueMask;
const char* fValueQuote;
TSQLStatement* fStmt;
Bool_t fUseStmt;
Int_t fMaxStrSize;
};
Long64_t TSQLStructure::FindMaxObjectId()
{
Long64_t max = DefineObjectId(kFALSE);
for (Int_t n=0;n<NumChilds();n++) {
Long64_t zn = GetChild(n)->FindMaxObjectId();
if (zn>max) max = zn;
}
return max;
}
Bool_t TSQLStructure::ConvertToTables(TSQLFile* file, Long64_t keyid, TObjArray* cmds)
{
if ((file==0) || (cmds==0)) return kFALSE;
TSqlRegistry reg;
reg.fCmds = cmds;
reg.f = file;
reg.fKeyId = keyid;
reg.fFirstObjId = DefineObjectId(kFALSE);
reg.fLastObjId = FindMaxObjectId();
Bool_t res = StoreObject(®, reg.fFirstObjId, GetObjectClass());
reg.ConvertPoolValues();
return res;
}
void TSQLStructure::PerformConversion(TSqlRegistry* reg, TSqlRawBuffer* blobs, const char* topname, Bool_t useblob)
{
TString sbuf;
const char* ns = reg->f->SQLNameSeparator();
switch (fType) {
case kSqlObject: {
if (!StoreObject(reg, DefineObjectId(kFALSE), GetObjectClass())) break;
blobs->AddLine(sqlio::ObjectRef, GetValue(), topname, ns);
break;
}
case kSqlPointer: {
blobs->AddLine(sqlio::ObjectPtr, fValue.Data(), topname,ns);
break;
}
case kSqlVersion: {
if (fPointer!=0)
topname = ((TClass*) fPointer)->GetName();
else
Error("PerformConversion","version without class");
blobs->AddLine(sqlio::Version, fValue.Data(), topname, ns);
break;
}
case kSqlStreamerInfo: {
TStreamerInfo* info = GetStreamerInfo();
if (info==0) return;
if (useblob) {
for(Int_t n=0;n<=fChilds.GetLast();n++) {
TSQLStructure* child = (TSQLStructure*) fChilds.At(n);
child->PerformConversion(reg, blobs, info->GetName(), useblob);
}
} else {
Long64_t objid = reg->GetNextObjId();
TString sobjid;
sobjid.Form("%lld",objid);
if (!StoreObject(reg, objid, info->GetClass(), kTRUE)) return;
blobs->AddLine(sqlio::ObjectInst, sobjid.Data(), topname, ns);
}
break;
}
case kSqlCustomElement:
case kSqlElement: {
const TStreamerElement* elem = (const TStreamerElement*) fPointer;
Int_t indx = 0;
while (indx<NumChilds()) {
TSQLStructure* child = GetChild(indx++);
child->PerformConversion(reg, blobs, elem->GetName(), useblob);
}
break;
}
case kSqlValue: {
const char* tname = (const char*) fPointer;
if (fArrayIndex>=0) {
if (fRepeatCnt>1)
sbuf.Form("%s%d%s%d%s%s%s", "[", fArrayIndex, sqlio::IndexSepar, fArrayIndex+fRepeatCnt-1, "]", ns, tname);
else
sbuf.Form("%s%d%s%s%s", "[", fArrayIndex, "]", ns, tname);
} else {
if (tname!=0) sbuf = tname;
else sbuf = "Value";
}
TString buf;
const char* value = fValue.Data();
if ((tname==sqlio::CharStar) && (value!=0)) {
Int_t size = strlen(value);
if (size > reg->f->SQLSmallTextTypeLimit()) {
Int_t strid = reg->AddLongString(value);
buf = reg->f->CodeLongString(reg->fCurrentObjId, strid);
value = buf.Data();
}
}
blobs->AddLine(sbuf.Data(), value, (fArrayIndex>=0) ? 0 : topname, ns);
break;
}
case kSqlArray: {
if (fValue.Length()>0)
blobs->AddLine(sqlio::Array, fValue.Data(), topname, ns);
for(Int_t n=0;n<=fChilds.GetLast();n++) {
TSQLStructure* child = (TSQLStructure*) fChilds.At(n);
child->PerformConversion(reg, blobs, topname, useblob);
}
break;
}
}
}
Bool_t TSQLStructure::StoreObject(TSqlRegistry* reg, Long64_t objid, TClass* cl, Bool_t registerobj)
{
if ((cl==0) || (objid<0)) return kFALSE;
if (gDebug>1) {
cout << "Store object " << objid <<" cl = " << cl->GetName() << endl;
if (GetStreamerInfo()) cout << "Info = " << GetStreamerInfo()->GetName() << endl; else
if (GetElement()) cout << "Element = " << GetElement()->GetName() << endl;
}
Long64_t oldid = reg->fCurrentObjId;
TClass* oldcl = reg->fCurrentObjClass;
reg->fCurrentObjId = objid;
reg->fCurrentObjClass = cl;
Bool_t normstore = kFALSE;
Bool_t res = kTRUE;
if (cl==TObject::Class())
normstore = StoreTObject(reg);
else
if (cl==TString::Class())
normstore = StoreTString(reg);
else
if (GetType()==kSqlStreamerInfo)
normstore = StoreClassInNormalForm(reg);
else
normstore = StoreObjectInNormalForm(reg);
if (gDebug>2)
cout << "Store object " << objid << " of class " << cl->GetName() << " normal = " << normstore << " sqltype = " << GetType() << endl;
if (!normstore) {
TSQLClassInfo* sqlinfo = reg->f->RequestSQLClassInfo(cl);
TSqlRawBuffer rawdata(reg, sqlinfo);
for(Int_t n=0;n<NumChilds();n++) {
TSQLStructure* child = GetChild(n);
child->PerformConversion(reg, &rawdata, 0 );
}
res = rawdata.IsAnyData();
}
if (registerobj)
reg->AddRegCmd(objid, cl);
reg->fCurrentObjId = oldid;
reg->fCurrentObjClass = oldcl;
return res;
}
Bool_t TSQLStructure::StoreObjectInNormalForm(TSqlRegistry* reg)
{
if (fChilds.GetLast()!=1) return kFALSE;
TSQLStructure* s_ver = GetChild(0);
TSQLStructure* s_info = GetChild(1);
if (!CheckNormalClassPair(s_ver, s_info)) return kFALSE;
return s_info->StoreClassInNormalForm(reg);
}
Bool_t TSQLStructure::StoreClassInNormalForm(TSqlRegistry* reg)
{
TClass* cl = 0;
Version_t version = 0;
if (!GetClassInfo(cl, version)) return kFALSE;
if (cl==0) return kFALSE;
TSQLClassInfo* sqlinfo = reg->f->RequestSQLClassInfo(cl->GetName(), version);
TSQLTableData columns(reg->f, sqlinfo);
Bool_t needblob = kFALSE;
TSqlRawBuffer rawdata(reg, sqlinfo);
columns.AddColumn(reg->f->SQLObjectIdColumn(), reg->fCurrentObjId);
for(Int_t n=0;n<=fChilds.GetLast();n++) {
TSQLStructure* child = (TSQLStructure*) fChilds.At(n);
TStreamerElement* elem = child->GetElement();
if (elem==0) {
Error("StoreClassInNormalForm", "CAN NOT BE");
continue;
}
if (child->StoreElementInNormalForm(reg, &columns)) continue;
Int_t columntyp = DefineElementColumnType(elem, reg->f);
if ((columntyp!=kColRawData) && (columntyp!=kColObjectArray)) {
Error("StoreClassInNormalForm","Element %s typ=%d has problem with normal store ", elem->GetName(), columntyp);
continue;
}
Bool_t doblobs = kTRUE;
Int_t blobid = rawdata.fRawId;
if (columntyp==kColObjectArray)
if (child->TryConvertObjectArray(reg, &rawdata))
doblobs = kFALSE;
if (doblobs)
child->PerformConversion(reg, &rawdata, elem->GetName(), kFALSE);
if (blobid==rawdata.fRawId)
blobid = -1;
else {
needblob = kTRUE;
}
TString blobname = elem->GetName();
if (reg->f->GetUseSuffixes())
blobname += sqlio::RawSuffix;
columns.AddColumn(blobname, blobid);
}
reg->f->CreateClassTable(sqlinfo, columns.TakeColInfos());
reg->InsertToNormalTable(&columns, sqlinfo);
return kTRUE;
}
TString TSQLStructure::MakeArrayIndex(TStreamerElement* elem, Int_t index)
{
TString res;
if ((elem==0) || (elem->GetArrayLength()==0)) return res;
for(Int_t ndim=elem->GetArrayDim()-1;ndim>=0;ndim--) {
Int_t ix = index % elem->GetMaxIndex(ndim);
index = index / elem->GetMaxIndex(ndim);
TString buf;
buf.Form("%s%d%s","[",ix,"]");
res = buf + res;
}
return res;
}
Bool_t TSQLStructure::StoreElementInNormalForm(TSqlRegistry* reg, TSQLTableData* columns)
{
TStreamerElement* elem = GetElement();
if (elem==0) return kFALSE;
Int_t typ = elem->GetType();
Int_t columntyp = DefineElementColumnType(elem, reg->f);
if (gDebug>4)
cout << "Element " << elem->GetName()
<< " type = " << typ
<< " column = " << columntyp << endl;
TString colname = DefineElementColumnName(elem, reg->f);
if (columntyp==kColTString) {
const char* value;
if (!RecognizeTString(value)) return kFALSE;
Int_t len = value ? strlen(value) : 0;
Int_t sizelimit = reg->f->SQLSmallTextTypeLimit();
const char* stype = reg->f->SQLSmallTextType();
if (len<=sizelimit)
columns->AddColumn(colname.Data(), stype, value, kFALSE);
else {
Int_t strid = reg->AddLongString(value);
TString buf = reg->f->CodeLongString(reg->fCurrentObjId, strid);
columns->AddColumn(colname.Data(), stype, buf.Data(), kFALSE);
}
return kTRUE;
}
if (columntyp==kColParent) {
Long64_t objid = reg->fCurrentObjId;
TClass* basecl = elem->GetClassPointer();
Int_t resversion = basecl->GetClassVersion();
if (!StoreObject(reg, objid, basecl, kFALSE))
resversion = -1;
columns->AddColumn(colname.Data(), resversion);
return kTRUE;
}
if (columntyp==kColObject) {
Long64_t objid = -1;
if (NumChilds()==1) {
TSQLStructure* child = GetChild(0);
if (child->GetType()==kSqlObject) {
objid = child->DefineObjectId(kFALSE);
if (!child->StoreObject(reg, objid, child->GetObjectClass())) return kFALSE;
} else
if (child->GetType()==kSqlPointer) {
TString sobjid = child->GetValue();
if (sobjid.Length()>0)
objid = sqlio::atol64(sobjid.Data());
}
}
if (objid<0) {
objid = reg->GetNextObjId();
if (!StoreObject(reg, objid, elem->GetClassPointer()))
objid = -1;
}
columns->AddColumn(colname.Data(), objid);
return kTRUE;
}
if (columntyp==kColNormObject) {
if (NumChilds()!=1) {
Error("kColNormObject","NumChilds()=%d", NumChilds());
PrintLevel(20);
return kFALSE;
}
TSQLStructure* child = GetChild(0);
if ((child->GetType()!=kSqlPointer) && (child->GetType()!=kSqlObject)) return kFALSE;
Bool_t normal = kTRUE;
Long64_t objid = -1;
if (child->GetType()==kSqlObject) {
objid = child->DefineObjectId(kFALSE);
normal = child->StoreObject(reg, objid, child->GetObjectClass());
} else {
objid = child->DefineObjectId(kFALSE);
}
if (!normal) {
Error("kColNormObject","child->StoreObject fails");
return kFALSE;
}
columns->AddColumn(colname.Data(), objid);
return kTRUE;
}
if (columntyp==kColNormObjectArray) {
if (elem->GetArrayLength()!=NumChilds()) return kFALSE;
for (Int_t index=0;index<NumChilds();index++) {
TSQLStructure* child = GetChild(index);
if ((child->GetType()!=kSqlPointer) &&
(child->GetType()!=kSqlObject)) return kFALSE;
Bool_t normal = kTRUE;
Long64_t objid = child->DefineObjectId(kFALSE);
if (child->GetType()==kSqlObject)
normal = child->StoreObject(reg, objid, child->GetObjectClass());
if (!normal) return kFALSE;
colname = DefineElementColumnName(elem, reg->f, index);
columns->AddColumn(colname.Data(), objid);
}
return kTRUE;
}
if (columntyp==kColObjectPtr) {
if (NumChilds()!=1) return kFALSE;
TSQLStructure* child = GetChild(0);
if ((child->GetType()!=kSqlPointer) && (child->GetType()!=kSqlObject)) return kFALSE;
Bool_t normal = kTRUE;
Long64_t objid = -1;
if (child->GetType()==kSqlObject) {
objid = child->DefineObjectId(kFALSE);
normal = child->StoreObject(reg, objid, child->GetObjectClass());
}
if (!normal) return kFALSE;
columns->AddColumn(colname.Data(), objid);
return kTRUE;
}
if (columntyp==kColSimple) {
if (NumChilds()!=1) {
Error("StoreElementInNormalForm","Enexpected number %d for simple element %s", NumChilds(), elem->GetName());
return kFALSE;
}
TSQLStructure* child = GetChild(0);
if (child->GetType()!=kSqlValue) return kFALSE;
const char* value = child->GetValue();
if (value==0) return kFALSE;
const char* sqltype = reg->f->SQLCompatibleType(typ);
columns->AddColumn(colname.Data(), sqltype, value, IsNumericType(typ));
return kTRUE;
}
if (columntyp==kColSimpleArray) {
if (NumChilds()!=1) {
Error("StoreElementInNormalForm","In fixed array %s only array node should be", elem->GetName());
return kFALSE;
}
TSQLStructure* arr = GetChild(0);
const char* sqltype = reg->f->SQLCompatibleType(typ % 20);
for(Int_t n=0;n<arr->NumChilds();n++) {
TSQLStructure* child = arr->GetChild(n);
if (child->GetType()!=kSqlValue) return kFALSE;
const char* value = child->GetValue();
if (value==0) return kFALSE;
Int_t index = child->GetArrayIndex();
Int_t last = index + child->GetRepeatCounter();
while (index<last) {
colname = DefineElementColumnName(elem, reg->f, index);
columns->AddColumn(colname.Data(), sqltype, value, kTRUE);
index++;
}
}
return kTRUE;
}
return kFALSE;
}
Bool_t TSQLStructure::TryConvertObjectArray(TSqlRegistry* reg, TSqlRawBuffer* blobs)
{
TStreamerElement* elem = GetElement();
if (elem==0) return kFALSE;
if (NumChilds() % 2 !=0) return kFALSE;
Int_t indx = 0;
while (indx<NumChilds()) {
TSQLStructure* s_ver = GetChild(indx++);
TSQLStructure* s_info = GetChild(indx++);
if (!CheckNormalClassPair(s_ver, s_info)) return kFALSE;
}
indx = 0;
const char* ns = reg->f->SQLNameSeparator();
while (indx<NumChilds()-1) {
indx++;
TSQLStructure* s_info = GetChild(indx++);
TClass* cl = 0;
Version_t version = 0;
if (!s_info->GetClassInfo(cl, version)) return kFALSE;
Long64_t objid = reg->GetNextObjId();
if (!s_info->StoreObject(reg, objid, cl))
objid = -1;
TString sobjid;
sobjid.Form("%lld", objid);
blobs->AddLine(sqlio::ObjectRef_Arr, sobjid.Data(), elem->GetName(), ns);
}
return kTRUE;
}
Bool_t TSQLStructure::CheckNormalClassPair(TSQLStructure* s_ver, TSQLStructure* s_info)
{
if ((s_ver==0) || (s_info==0) || (s_ver->GetType()!=kSqlVersion)) return kFALSE;
TClass* ver_cl = s_ver->GetVersionClass();
TClass* info_cl = 0;
Version_t info_ver = 0;
if (!s_info->GetClassInfo(info_cl, info_ver)) return kFALSE;
if ((ver_cl==0) || (info_cl==0) || (ver_cl!=info_cl) ||
(ver_cl->GetClassVersion()!=info_ver)) return kFALSE;
return kTRUE;
}
Bool_t TSQLStructure::StoreTObject(TSqlRegistry* reg)
{
if ((NumChilds()<3) || (NumChilds()>4)) return kFALSE;
TSQLStructure* str_ver = GetChild(0);
TSQLStructure* str_id = GetChild(1);
TSQLStructure* str_bits = GetChild(2);
TSQLStructure* str_prid = GetChild(3);
if (str_ver->GetType()!=kSqlVersion) return kFALSE;
if ((str_id->GetType()!=kSqlValue) ||
(str_id->GetValueType()!=sqlio::UInt)) return kFALSE;
if ((str_bits->GetType()!=kSqlValue) ||
(str_bits->GetValueType()!=sqlio::UInt)) return kFALSE;
if (str_prid!=0)
if ((str_prid->GetType()!=kSqlValue) ||
(str_prid->GetValueType()!=sqlio::UShort)) return kFALSE;
TSQLClassInfo* sqlinfo = reg->f->RequestSQLClassInfo(TObject::Class());
if (sqlinfo==0) return kFALSE;
TSQLTableData columns(reg->f, sqlinfo);
const char* uinttype = reg->f->SQLCompatibleType(TStreamerInfo::kUInt);
columns.AddColumn(reg->f->SQLObjectIdColumn(), reg->fCurrentObjId);
columns.AddColumn(sqlio::TObjectUniqueId, uinttype, str_id->GetValue(), kTRUE);
columns.AddColumn(sqlio::TObjectBits, uinttype, str_bits->GetValue(), kTRUE);
columns.AddColumn(sqlio::TObjectProcessId, "CHAR(3)", (str_prid ? str_prid->GetValue() : ""), kFALSE);
reg->f->CreateClassTable(sqlinfo, columns.TakeColInfos());
reg->InsertToNormalTable(&columns, sqlinfo);
return kTRUE;
}
Bool_t TSQLStructure::StoreTString(TSqlRegistry* reg)
{
const char* value = 0;
if (!RecognizeTString(value)) return kFALSE;
TSQLClassInfo* sqlinfo = reg->f->RequestSQLClassInfo(TString::Class());
if (sqlinfo==0) return kFALSE;
TSQLTableData columns(reg->f, sqlinfo);
columns.AddColumn(reg->f->SQLObjectIdColumn(), reg->fCurrentObjId);
columns.AddColumn(sqlio::TStringValue, reg->f->SQLBigTextType(), value, kFALSE);
reg->f->CreateClassTable(sqlinfo, columns.TakeColInfos());
reg->InsertToNormalTable(&columns, sqlinfo);
return kTRUE;
}
Bool_t TSQLStructure::RecognizeTString(const char* &value)
{
value = 0;
if ((NumChilds()==0) || (NumChilds()>3)) return kFALSE;
TSQLStructure *len=0, *lenbig=0, *chars=0;
for (Int_t n=0;n<NumChilds();n++) {
TSQLStructure* curr = GetChild(n);
if (curr->fType!=kSqlValue) return kFALSE;
if (curr->fPointer==sqlio::UChar) {
if (len==0) len=curr; else return kFALSE;
} else
if (curr->fPointer==sqlio::Int) {
if (lenbig==0) lenbig=curr; else return kFALSE;
} else
if (curr->fPointer==sqlio::CharStar) {
if (chars==0) chars=curr; else return kFALSE;
} else return kFALSE;
}
if (len==0) return kFALSE;
if ((lenbig!=0) && ((chars==0) || (len==0))) return kFALSE;
if (chars!=0)
value = chars->GetValue();
return kTRUE;
}
Int_t TSQLStructure::DefineElementColumnType(TStreamerElement* elem, TSQLFile* f)
{
if (elem==0) return kColUnknown;
Int_t typ = elem->GetType();
if (typ == TStreamerInfo::kMissing) return kColRawData;
if ((typ>0) && (typ<20) &&
(typ!=TStreamerInfo::kCharStar)) return kColSimple;
if ((typ>TStreamerInfo::kOffsetL) &&
(typ<TStreamerInfo::kOffsetP))
if ((f->GetArrayLimit()<0) ||
(elem->GetArrayLength()<=f->GetArrayLimit()))
return kColSimpleArray;
if (typ==TStreamerInfo::kTObject) {
if (elem->InheritsFrom(TStreamerBase::Class()))
return kColParent;
else
return kColObject;
}
if (typ==TStreamerInfo::kTNamed) {
if (elem->InheritsFrom(TStreamerBase::Class()))
return kColParent;
else
return kColObject;
}
if (typ==TStreamerInfo::kTString) return kColTString;
if (typ==TStreamerInfo::kBase) return kColParent;
if (typ==TStreamerInfo::kSTL)
if (elem->InheritsFrom(TStreamerBase::Class()))
return kColParent;
if ((typ==TStreamerInfo::kObject) ||
(typ==TStreamerInfo::kAny)) {
if (elem->GetArrayLength()==0)
return kColObject;
else
if (elem->GetStreamer()==0)
return kColObjectArray;
}
if ((typ==TStreamerInfo::kObject) ||
(typ==TStreamerInfo::kAny) ||
(typ==TStreamerInfo::kAnyp) ||
(typ==TStreamerInfo::kObjectp) ||
(typ==TStreamerInfo::kAnyP) ||
(typ==TStreamerInfo::kObjectP)) {
if ((elem->GetArrayLength()==0) ||
(elem->GetStreamer()!=0))
return kColNormObject;
else
return kColNormObjectArray;
}
if ((typ==TStreamerInfo::kObject + TStreamerInfo::kOffsetL) ||
(typ==TStreamerInfo::kAny + TStreamerInfo::kOffsetL) ||
(typ==TStreamerInfo::kAnyp + TStreamerInfo::kOffsetL) ||
(typ==TStreamerInfo::kObjectp + TStreamerInfo::kOffsetL) ||
(typ==TStreamerInfo::kAnyP + TStreamerInfo::kOffsetL) ||
(typ==TStreamerInfo::kObjectP + TStreamerInfo::kOffsetL)) {
if (elem->GetStreamer()!=0)
return kColNormObject;
else
return kColNormObjectArray;
}
if ((typ==TStreamerInfo::kObject) ||
(typ==TStreamerInfo::kAny) ||
(typ==TStreamerInfo::kAnyp) ||
(typ==TStreamerInfo::kObjectp) ||
(typ==TStreamerInfo::kSTL)) {
if (elem->GetArrayLength()==0)
return kColObject;
else
if (elem->GetStreamer()==0)
return kColObjectArray;
}
if (((typ==TStreamerInfo::kAnyP) ||
(typ==TStreamerInfo::kObjectP)) &&
(elem->GetArrayDim()==0)) return kColObjectPtr;
return kColRawData;
}
TString TSQLStructure::DefineElementColumnName(TStreamerElement* elem, TSQLFile* f, Int_t indx)
{
TString colname = "";
Int_t coltype = DefineElementColumnType(elem, f);
if (coltype==kColUnknown) return colname;
const char* elemname = elem->GetName();
switch (coltype) {
case kColSimple: {
colname = elemname;
if (f->GetUseSuffixes()) {
colname+=f->SQLNameSeparator();
colname+=GetSimpleTypeName(elem->GetType());
}
break;
}
case kColSimpleArray: {
colname = elemname;
colname+=MakeArrayIndex(elem, indx);
break;
}
case kColParent: {
colname = elemname;
if (f->GetUseSuffixes())
colname+=sqlio::ParentSuffix;
break;
}
case kColNormObject: {
colname = elemname;
if (f->GetUseSuffixes())
colname += sqlio::ObjectSuffix;
break;
}
case kColNormObjectArray: {
colname = elemname;
colname+=MakeArrayIndex(elem, indx);
if (f->GetUseSuffixes())
colname += sqlio::ObjectSuffix;
break;
}
case kColObject: {
colname = elemname;
if (f->GetUseSuffixes())
colname += sqlio::ObjectSuffix;
break;
}
case kColObjectPtr: {
colname = elemname;
if (f->GetUseSuffixes())
colname += sqlio::PointerSuffix;
break;
}
case kColTString: {
colname = elem->GetName();
if (f->GetUseSuffixes())
colname+=sqlio::StrSuffix;
break;
}
case kColRawData: {
colname = elemname;
if (f->GetUseSuffixes())
colname += sqlio::RawSuffix;
break;
}
case kColObjectArray: {
colname = elemname;
if (f->GetUseSuffixes())
colname += sqlio::RawSuffix;
break;
}
}
return colname;
}
Int_t TSQLStructure::LocateElementColumn(TSQLFile* f, TBufferSQL2* buf, TSQLObjectData* data)
{
TStreamerElement* elem = GetElement();
if ((elem==0) || (data==0)) return kColUnknown;
Int_t coltype = DefineElementColumnType(elem, f);
if (gDebug>4)
cout <<"TSQLStructure::LocateElementColumn " << elem->GetName() <<
" coltyp = " << coltype << " : " << elem->GetType() << " len = " << elem->GetArrayLength() << endl;
if (coltype==kColUnknown) return kColUnknown;
const char* elemname = elem->GetName();
Bool_t located = kFALSE;
TString colname = DefineElementColumnName(elem, f);
if (gDebug>4)
cout << " colname = " << colname << " in " <<
data->GetInfo()->GetClassTableName() << endl;
switch (coltype) {
case kColSimple: {
located = data->LocateColumn(colname.Data());
break;
}
case kColSimpleArray: {
located = data->LocateColumn(colname);
break;
}
case kColParent: {
located = data->LocateColumn(colname.Data());
if (located==kColUnknown) return kColUnknown;
Long64_t objid = DefineObjectId(kTRUE);
const char* clname = elemname;
Version_t version = atoi(data->GetValue());
if (version<0) break;
if (strcmp(clname,TObject::Class()->GetName())==0) {
UnpackTObject(f, buf, data, objid, version);
break;
}
TSQLClassInfo* sqlinfo = f->FindSQLClassInfo(clname, version);
if (sqlinfo==0) return kColUnknown;
if (sqlinfo->IsClassTableExist()) {
data->AddUnpackInt(sqlio::Version, version);
} else {
TSQLObjectData* objdata = buf->SqlObjectData(objid, sqlinfo);
if ((objdata==0) || !objdata->PrepareForRawData()) return kColUnknown;
AddObjectData(objdata);
}
break;
}
case kColObject: {
located = data->LocateColumn(colname.Data());
if (located==kColUnknown) return located;
const char* strobjid = data->GetValue();
if (strobjid==0) return kColUnknown;
Long64_t objid = sqlio::atol64(strobjid);
if (objid<0) break;
TString clname;
Version_t version;
if (!buf->SqlObjectInfo(objid, clname, version)) return kColUnknown;
if (clname==TObject::Class()->GetName()) {
UnpackTObject(f, buf, data, objid, version);
break;
}
TSQLClassInfo* sqlinfo = f->FindSQLClassInfo(clname.Data(), version);
if (sqlinfo==0) return kColUnknown;
if (sqlinfo->IsClassTableExist()) {
data->AddUnpackInt(sqlio::Version, version);
} else {
TSQLObjectData* objdata = buf->SqlObjectData(objid, sqlinfo);
if ((objdata==0) || !objdata->PrepareForRawData()) return kColUnknown;
AddObjectData(objdata);
}
fValue = strobjid;
break;
}
case kColObjectPtr: {
located = data->LocateColumn(colname.Data());
break;
}
case kColNormObject: {
located = data->LocateColumn(colname.Data());
break;
}
case kColNormObjectArray: {
located = data->LocateColumn(colname.Data());
break;
}
case kColTString: {
located = data->LocateColumn(colname);
if (located==kColUnknown) return located;
const char* value = data->GetValue();
Long64_t objid = DefineObjectId(kTRUE);
Int_t strid = f->IsLongStringCode(objid, value);
TString buf2;
if (strid>0)
if (f->GetLongString(objid, strid, buf2))
value = buf2.Data();
Int_t len = (value==0) ? 0 : strlen(value);
if (len<255) {
data->AddUnpackInt(sqlio::UChar, len);
} else {
data->AddUnpackInt(sqlio::UChar, 255);
data->AddUnpackInt(sqlio::Int, len);
}
if (len>0)
data->AddUnpack(sqlio::CharStar, value);
break;
}
case kColRawData: {
located = data->LocateColumn(colname.Data(), kTRUE);
break;
}
case kColObjectArray: {
located = data->LocateColumn(colname.Data(), kTRUE);
break;
}
}
if (!located) coltype = kColUnknown;
return coltype;
}
Bool_t TSQLStructure::UnpackTObject(TSQLFile* f, TBufferSQL2* buf, TSQLObjectData* data, Long64_t objid, Int_t clversion)
{
TSQLClassInfo* sqlinfo = f->FindSQLClassInfo(TObject::Class()->GetName(), clversion);
if (sqlinfo==0) return kFALSE;
TSQLObjectData* tobjdata = buf->SqlObjectData(objid, sqlinfo);
if (tobjdata==0) return kFALSE;
data->AddUnpackInt(sqlio::Version, clversion);
tobjdata->LocateColumn(sqlio::TObjectUniqueId);
data->AddUnpack(sqlio::UInt, tobjdata->GetValue());
tobjdata->ShiftToNextValue();
tobjdata->LocateColumn(sqlio::TObjectBits);
data->AddUnpack(sqlio::UInt, tobjdata->GetValue());
tobjdata->ShiftToNextValue();
tobjdata->LocateColumn(sqlio::TObjectProcessId);
const char* value = tobjdata->GetValue();
if ((value!=0) && (strlen(value)>0))
data->AddUnpack(sqlio::UShort, value);
delete tobjdata;
return kTRUE;
}
Bool_t TSQLStructure::UnpackTString(TSQLFile* f, TBufferSQL2* buf, TSQLObjectData* data, Long64_t objid, Int_t clversion)
{
TSQLClassInfo* sqlinfo = f->FindSQLClassInfo(TString::Class()->GetName(), clversion);
if (sqlinfo==0) return kFALSE;
TSQLObjectData* tstringdata = buf->SqlObjectData(objid, sqlinfo);
if (tstringdata==0) return kFALSE;
tstringdata->LocateColumn(sqlio::TStringValue);
const char* value = tstringdata->GetValue();
Int_t len = (value==0) ? 0 : strlen(value);
if (len<255) {
data->AddUnpackInt(sqlio::UChar, len);
} else {
data->AddUnpackInt(sqlio::UChar, 255);
data->AddUnpackInt(sqlio::Int, len);
}
if (len>0)
data->AddUnpack(sqlio::CharStar, value);
delete tstringdata;
return kTRUE;
}
void TSQLStructure::AddStrBrackets(TString &s, const char* quote)
{
if (strcmp(quote,"\"")==0) s.ReplaceAll("\"","\\\"");
else s.ReplaceAll("'","''");
s.Prepend(quote);
s.Append(quote);
}
Last change: Wed Jun 25 08:52:33 2008
Last generated: 2008-06-25 08:52
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.