#include "TList.h"
#include "TParameter.h"
#include "TEnv.h"
#include "TObjString.h"
#include "TSQLMonitoring.h"
#include "TSQLServer.h"
#include "TSQLResult.h"
TSQLMonitoringWriter::TSQLMonitoringWriter(const char *serv, const char *user,
const char *pass, const char *table)
: TVirtualMonitoringWriter("SQL", 0.0), fTable(table), fVerbose(kFALSE)
{
fDB = TSQLServer::Connect(serv, user, pass);
if (!fDB || fDB->IsZombie()) {
SafeDelete(fDB);
MakeZombie();
}
fMaxBulkSize = 16 * 1024 * 1024;
TString smx = gEnv->GetValue("SQLMonitoringWriter.MaxBulkSize", "16M");
if (!smx.IsDigit()) {
if (smx.EndsWith("K", TString::kIgnoreCase)) {
smx.Remove(smx.Length()-1);
if (smx.IsDigit()) fMaxBulkSize = smx.Atoi() * 1024;
} else if (smx.EndsWith("M", TString::kIgnoreCase)) {
smx.Remove(smx.Length()-1);
if (smx.IsDigit()) fMaxBulkSize = smx.Atoi() * 1024 * 1024;
} else if (smx.EndsWith("G", TString::kIgnoreCase)) {
smx.Remove(smx.Length()-1);
if (smx.IsDigit()) fMaxBulkSize = smx.Atoi() * 1024 * 1024 * 1024;
}
} else {
fMaxBulkSize = smx.Atoi();
}
}
TSQLMonitoringWriter::~TSQLMonitoringWriter()
{
SafeDelete(fDB);
}
Bool_t TSQLMonitoringWriter::SendParameters(TList *values, const char *opt)
{
if (!fDB) {
return kFALSE;
}
if (!values || (values && values->GetSize() < 1))
return kFALSE;
TString table(fTable), op, ops(opt);
Ssiz_t from = 0;
Bool_t bulk = kFALSE;
while (ops.Tokenize(op, from, ",")) {
if (op == "bulk") {
bulk = kTRUE;
} else if (op.BeginsWith("table=")) {
op.ReplaceAll("table=", "");
if (!op.IsNull()) {
Ssiz_t idot = table.Index('.');
if (idot != kNPOS && op.Index('.') == kNPOS) {
table.Remove(idot+1);
table += op;
} else {
table = op;
}
}
}
}
TIter nxi(values);
TObject *o = 0;
TString sql = TString::Format("INSERT INTO %s", table.Data());
TSQLResult *res = 0;
if (!bulk) {
char c = '(';
TString cols, vals;
while ((o = nxi())) {
if (!strncmp(o->ClassName(), "TNamed", 6)) {
cols += TString::Format("%c%s", c, ((TNamed *)o)->GetName());
vals += TString::Format("%c'%s'", c, ((TNamed *)o)->GetTitle());
} else if (!strcmp(o->ClassName(), "TParameter<Long64_t>")) {
cols += TString::Format("%c%s", c, ((TParameter<Long64_t> *)o)->GetName());
vals += TString::Format("%c%lld", c, ((TParameter<Long64_t> *)o)->GetVal());
} else if (!strcmp(o->ClassName(), "TParameter<double>")) {
cols += TString::Format("%c%s", c, ((TParameter<double> *)o)->GetName());
vals += TString::Format("%c%f", c, ((TParameter<double> *)o)->GetVal());
} else if (!strcmp(o->ClassName(), "TParameter<float>")) {
cols += TString::Format("%c%s", c, ((TParameter<float> *)o)->GetName());
vals += TString::Format("%c%f", c, ((TParameter<float> *)o)->GetVal());
} else if (!strcmp(o->ClassName(), "TParameter<int>")) {
cols += TString::Format("%c%s", c, ((TParameter<int> *)o)->GetName());
vals += TString::Format("%c%d", c, ((TParameter<int> *)o)->GetVal());
} else if (!strcmp(o->ClassName(), "TParameter<long>")) {
cols += TString::Format("%c%s", c, ((TParameter<long> *)o)->GetName());
vals += TString::Format("%c%ld", c, ((TParameter<long> *)o)->GetVal());
}
c = ',';
}
cols += ")";
vals += ")";
sql += TString::Format(" %s VALUES %s", cols.Data(), vals.Data());
if (fVerbose) Info("SendParameters", "sending: '%s'", sql.Data());
if (!(res = fDB->Query(sql))) {
Error("SendParameters", "insert into %s failed", table.Data());
if (sql.Length() > 1024) {
TString head(sql(0,508)), tail(sql(sql.Length()-512,512));
Printf("%s...%s", head.Data(), tail.Data());
} else {
Printf("%s", sql.Data());
}
return kFALSE;
}
delete res;
} else {
o = nxi();
TObjString *os = dynamic_cast<TObjString *>(o);
if (!os) {
Error("SendParameters", "bulk insert: first entry in list is not 'TObjString' but '%s'", o->ClassName() );
return kFALSE;
}
sql += TString::Format(" (%s) VALUES ", os->GetName());
TString head = sql;
if (fVerbose) Info("SendParameters", "sending: '%s' (bulk of %d nplets)", head.Data(), values->GetSize() - 1);
char c = ' ';
while ((o = nxi())) {
if ((os = dynamic_cast<TObjString *>(o))) {
sql += TString::Format("%c(%s)", c, os->GetName());
c = ',';
} else {
Warning("SendParameters", "bulk insert: ignoring not 'TObjString' entry ('%s')", o->ClassName() );
}
if (sql.Length() > 0.9 * fMaxBulkSize) {
if (!(res = fDB->Query(sql))) {
Error("SendParameters", "bulk insert into %s failed", table.Data());
if (sql.Length() > 1024) {
TString hd(sql(0,508)), tl(sql(sql.Length()-512,512));
Printf("%s...%s", hd.Data(), tl.Data());
} else {
Printf("%s", sql.Data());
}
return kFALSE;
}
delete res;
sql = head;
c = ' ';
}
}
if (sql.Length() > head.Length()) {
if (!(res = fDB->Query(sql))) {
Error("SendParameters", "bulk insert into %s failed", table.Data());
if (sql.Length() > 1024) {
TString hd(sql(0,508)), tl(sql(sql.Length()-512,512));
Printf("%s...%s", hd.Data(), tl.Data());
} else {
Printf("%s", sql.Data());
}
return kFALSE;
}
delete res;
}
}
return kTRUE;
}