EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
FairDbSqlValPacket.cxx
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file FairDbSqlValPacket.cxx
1 
2 #include <algorithm>
3 #include <memory>
4 using std::auto_ptr;
5 #include <sstream>
6 #include <vector>
7 
8 #include "FairDb.h"
9 #include "FairDbMultConnector.h"
10 #include "FairDbConfigSet.h"
11 #include "FairDbOutRowStream.h"
12 #include "FairDbResPtr.h"
13 #include "FairDbResult.h"
14 #include "FairDbSqlValPacket.h"
15 #include "FairDbStatement.h"
16 #include "FairDbTableProxy.h"
17 #include "FairDbTableRow.h"
19 #include "FairDbValidityRec.h"
20 #include "FairDbValRecSet.h"
21 #include "FairDbString.h"
22 #include "ValRange.h"
23 
25 
26 
27 
28 Bool_t FairDbSqlValPacket::fgLastMetaHadRowCounter = false;
29 
30 
31 
32 static bool compStringPtrs(const string* str1, const string* str2 )
33 {
34  return *str1 < *str2;
35 }
36 
37 
39  fNumErrors(0),
40  fSeqNo(0),
41  fSqlMySqlMetaMain(),
42  fSqlMySqlMetaVal(),
43  fSqlStmts(),
44  fNumStmts(0),
45  fTableName(),
46  fCreationDate()
47 {
48 }
49 
50 
51 
53  fNumErrors(0),
54  fSeqNo(0),
55  fSqlMySqlMetaMain(),
56  fSqlMySqlMetaVal(),
57  fSqlStmts(),
58  fNumStmts(0),
59  fTableName(),
60  fCreationDate()
61 {
62 
63  Fill(is);
64 
65 }
66 
67 
69  fNumErrors(0),
70  fSeqNo(vrec.GetSeqNo()),
71  fSqlMySqlMetaMain(),
72  fSqlMySqlMetaVal(),
73  fSqlStmts(),
74  fNumStmts(0),
75  fTableName(vrec.GetTableProxy()->GetTableName()),
76  fCreationDate(vrec.GetCreationDate())
77 {
78 
79  const FairDbTableProxy& tableProxy = *vrec.GetTableProxy();
80  Int_t seqNo = vrec.GetSeqNo();
81  UInt_t dbNo = vrec.GetDbNo();
82 
83  // Create the SQL for the FairDbValidityRec itself.
84  this->AddRow(tableProxy,0,vrec);
85 
86  // Create the SQL for the rows.
87 
88  const FairDbProxy& dbProxy = tableProxy.GetDBProxy();
89  FairDbResultSet* rset = dbProxy.QuerySeqNo(seqNo,dbNo);
90 
91 
92  for(; ! rset->IsExhausted(); rset->FetchRow()) {
93  string str;
94  rset->RowAsCsv(str);
95  this->AddRow(str);
96  }
97  delete rset;
98  rset = 0;
99 }
100 
101 //.....................................................................
102 
104 {
105 
106  Clear();
107 
108 }
109 
110 //.....................................................................
111 
113  const FairDbValidityRec* vrec,
114  const FairDbTableRow& row)
115 {
116 
117  if ( this->GetNumSqlStmts() == 0 ) {
118 
119  cout << "Cannot add data row - packet does not have a VAL row" << endl;
120  ++fNumErrors;
121  return kFALSE;
122  }
123 
124  return this->AddRow(tblProxy,vrec,row);
125 
126 }
127 
128 //.....................................................................
129 
130 void FairDbSqlValPacket::AddRow(const string& row)
131 {
132 
133  string sql("INSERT INTO ");
134  sql += this->GetTableName();
135  if ( this->GetNumSqlStmts() == 0 ) { sql += "VAL"; }
136  sql += " VALUES (" + row + ");";
137  ostringstream seqno;
138  seqno << this->GetSeqNo();
139  this->SetSeqNoOnRow(sql,seqno.str());
140  fSqlStmts.push_back(sql);
141  ++fNumStmts;
142 
143 }
144 
145 //.....................................................................
146 
148  const FairDbValidityRec* vrec,
149  const FairDbTableRow& row)
150 {
151 
152 
153 
154  bool isVal = this->GetNumSqlStmts() == 0;
155  const FairDbTableMetaData& meta = isVal ? tblProxy.GetMetaValid() : tblProxy.GetMetaData();
156  FairDbOutRowStream outRow(&meta);
157 
158 // Store dummy SEQNO, and, if necessary ROW_COUNTER, for data rows.
159  if ( ! isVal ) {
160  outRow << 0; // dummy SEQNO
161  if ( outRow.HasRowCounter() ) { outRow << fNumStmts; } // ROW_COUNTER
162  }
163  row.Store(outRow,vrec);
164  if ( ! outRow.HasGoodData() ) {
165  if ( ! outRow.IsComplete() ) {
166 
167  cout << "Incomplete data supplied for row " << this->GetNumSqlStmts()-1
168  << " of table "
169  << tblProxy.GetTableName() << endl;
170  }
171  ++fNumErrors;
172  return kFALSE;
173  }
174  this->AddRow(outRow.GetCSV());
175  return kTRUE;
176 }
177 //.....................................................................
178 
180  const FairDbSqlValPacket& that,
181  Bool_t log,
182  const Char_t* thisName,
183  const Char_t* thatName ) const
184 {
185 
186  if ( this->IsEqual(that,log,thisName,thatName ) ) { return kIdentical; }
187 
188  if ( fSeqNo != that.fSeqNo
189  || fTableName != that.fTableName ) { return kConflict; }
190 
191  std::vector<std::string> valuesThis = this->GetStmtValues(0);
192  std::vector<std::string> valuesThat = that.GetStmtValues(0);
193 
194  // Assume CreationDate is the 7th element (counting from 0).
195  int comp = valuesThis[7].compare(valuesThat[7]);
196 
197  if ( comp < 0 ) {
198  if ( log ) {
199  cout << " Difference classified as Update" << endl;
200  };
201  return kUpdate;
202  } else if ( comp > 0 ) {
203  if ( log ) {
204  cout << " Difference classified as OutOfDate" << endl;
205  }
206  return kOutOfDate;
207  }
208  return kConflict;
209 
210 }
211 
212 
213 //.....................................................................
214 
215 Bool_t FairDbSqlValPacket::CreateTable(UInt_t dbNo) const
216 {
217 
218  if ( ! CanBeStored() ) { return kFALSE; }
219 
220  // Locate required FairDbStatement.
221  auto_ptr<FairDbStatement> stmtDb(FairDbTableProxyRegistry::Instance()
222  .GetMultConnector()
223  .CreateStatement(dbNo));
224  if ( ! stmtDb.get() ) {
225 
226  cout << "Attempting to write to non-existant cascade entry " << dbNo
227  << endl;
228  return kFALSE;
229  }
230  if ( fSqlMySqlMetaMain == "" || fSqlMySqlMetaVal == "" ) {
231 
232  cout << "No SQL available to create table " << fTableName
233  << " in cascade entry: " << dbNo << endl;
234  return kFALSE;
235  }
236 
237  stmtDb->ExecuteUpdate(fSqlMySqlMetaVal.c_str());
238  if ( stmtDb->PrintExceptions() ) { return kFALSE; }
239  stmtDb->ExecuteUpdate(fSqlMySqlMetaMain.c_str());
240  if ( stmtDb->PrintExceptions() ) { return kFALSE; }
241 
243 
244  return kTRUE;
245 
246 }
247 
248 //.....................................................................
249 
250 Bool_t FairDbSqlValPacket::Fill(std::ifstream& is)
251 {
252 
253  enum { kLOOKING_FOR_HEADER,
254  kLOOKING_FOR_TRAILER
255  } state = kLOOKING_FOR_HEADER;
256 
258  kHEADER_TRAILER_MAX_LEN = kMAXTABLENAMELEN + 20
259  };
260 
261  string nameHead;
262  string nameTrail;
263  UInt_t seqNoHead = 0;
264  UInt_t seqNoTrail = 0;
265 
266  string line;
267  string msg;
268  string sql;
269  int lineNum = 0;
270 
271  this->Reset();
272  // Loop until EOF reading lines.
273 
274  while ( ! is.eof() ) {
275  getline(is,line);
276  ++lineNum;
277  // Skip null lines.
278  if (line.size() == 0 ) { continue; }
279 
280  // Look for header line
281  if ( state == kLOOKING_FOR_HEADER ) {
282  if ( line.substr(0,5) == ">>>>>" ) {
283  if ( line.size() >= kHEADER_TRAILER_MAX_LEN ) {
284  Report("Bad header",lineNum,line);
285  continue;
286  }
287 
288  // Look for optional metadata.
289  if ( line.find("Metadata") != string::npos ) {
291  ++lineNum;
293  // Record whether or not table has a ROW_COUNTER column.
295  fSqlMySqlMetaMain.find("ROW_COUNTER",fSqlMySqlMetaMain.find("(")) != string::npos;
296  ++lineNum;
297  getline(is,line);
298  ++lineNum;
299  if ( line.substr(0,5) != "<<<<<"
300  || line.find("Metadata") == string::npos ) {
301  Report("Bad metadata",lineNum,line);
302  continue;
303  }
304  getline(is,line);
305  ++lineNum;
306  if ( line.size() >= kHEADER_TRAILER_MAX_LEN ) {
307  Report("Bad header",lineNum,line);
308  continue;
309  }
310  }
311 
312  // Collect table name and SeqNo.
313  istringstream istr(line.substr(5));
314  istr.width(kMAXTABLENAMELEN);
315  istr >> nameHead >> seqNoHead;
316  if ( ! istr.eof() ) {
317  Report("Input error",lineNum,line);
318  continue;
319  }
320 
321  // Header looks good, start to collect SQL.
322  state = kLOOKING_FOR_TRAILER;
323  sql = "";
324  } else {
325  Report("Not header",lineNum,line);
326  }
327  }
328 
329  //Look for trailer line.
330 
331  else {
332  if ( line.substr(0,5) == "<<<<<" ) {
333  if ( line.size() >= kHEADER_TRAILER_MAX_LEN
334  ) { msg = "Bad trailer"; }
335 
336  else {
337 
338  // Collect table name and SeqNo.
339  istringstream istr(line.substr(5));
340  istr.width(kMAXTABLENAMELEN);
341  istr >> nameTrail >> seqNoTrail;
342  if ( ! istr.eof() ) { msg = "Input error"; }
343 
344  else if ( nameTrail != nameHead
345  || seqNoHead != seqNoTrail ) {
346  msg = "Header/Trailer mismatch: Header: ";
347  msg += istr.str();
348  } else if ( GetNumSqlStmts() == 0
349  ) { msg = "No SQL statements between Header/Trailer"; }
350  else {
351 
352  // Trailer looks good return with object filled.
353  fSeqNo = seqNoHead;
354  fTableName = nameHead;
355 
356  //Dig out the creation date from the first record.
357  string date = this->GetStmtValues(0)[7];
358  //Remove the quotes.
359  date.erase(0,1);
360  date.erase(date.size()-1,1);
362  // Temporary hack: set for Agg No = -1 for DBUSUBRUNSUMMARY
363  if ( fTableName == "DBUSUBRUNSUMMARY" ) {
364  std::vector<std::string> ls;
365  FairUtilString::StringTok(ls,*fSqlStmts.begin(),",");
366  // Agg. no is element 6.
367  if (ls.size() >= 7 && ls[6] != "-1") {
368  static bool warnOnce = true;
369  if ( warnOnce ) {
370 
371  cout << "Setting aggregate number for DBUSUBRUNSUMMARY = -1\n"
372  << " Expect this message once. DBUSUBRUNSUMMARY needs to be "
373  << " fixed!" << endl;
374  warnOnce = false;
375  }
376  ls[6] = "-1";
377  sql = ls[0];
378  for (unsigned i=1; i<ls.size(); ++i ) { sql += "," + ls[i]; }
379  fSqlStmts.pop_front();
380  fSqlStmts.push_front(sql);
381  }
382  }
383  return kTRUE;
384 
385  }
386  }
387 
388  // Trailer bad, start again!
389  Report(msg.c_str(),lineNum,line);
390  state = kLOOKING_FOR_HEADER;
391  }
392 
393  // Not a trailer line, must be SQL, collect and append lines
394  // until a trailing ; found.
395  else {
396  sql += line;
397  if ( sql[sql.size()-1] == ';') {
398  fSqlStmts.push_back(sql);
399  ++fNumStmts;
400  sql = "";
401  }
402  }
403  }
404 
405  }
406 
407  if ( state != kLOOKING_FOR_HEADER
408  ) { Report("Unexpected EOF",lineNum,"EOF"); }
409  this->Reset();
410  return kFALSE;
411 
412 }
413 //.....................................................................
414 
415 string FairDbSqlValPacket::GetStmt(UInt_t stmtNo) const
416 {
417 
418 
419  if ( stmtNo >= this->GetNumSqlStmts() ) { return ""; }
420 
421  // Locate statement
422  std::list<std::string>::const_iterator itr = fSqlStmts.begin();
423  while ( stmtNo ) { ++itr; --stmtNo; }
424 
425  return *itr;
426 
427 }
428 //.....................................................................
429 
430 std::vector<std::string> FairDbSqlValPacket::GetStmtValues(UInt_t stmtNo) const
431 {
432 
433  std::vector<std::string> vec;
434  if ( stmtNo >= this->GetNumSqlStmts() ) { return vec; }
435 
436  // Locate statement
437  std::string str = this->GetStmt(stmtNo);
438 
439  // Extract ...(list-of-values)... and parse it into tokens.
440  std::string::size_type pos = str.find('(');
441  ++pos;
442  std::string::size_type n = str.find(')') - pos;
443  FairUtilString::StringTok(vec,str.substr(pos,n),",");
444 
445  return vec;
446 
447 }
448 
449 //.....................................................................
450 
452  Bool_t log,
453  const Char_t* thisName,
454  const Char_t* thatName ) const
455 {
456 
457  if ( fSeqNo != that.fSeqNo
458  || fTableName != that.fTableName
459  || fNumStmts != that.fNumStmts ) {
460  if ( log ) cout << "Conflict found:"
461  << " for : " << thisName << " , " << thatName << " :-\n"
462  << " SeqNo " << fSeqNo << "," << that.fSeqNo
463  << "\n TableName " << fTableName << "," << that.fTableName
464  << "\n Size " << fNumStmts << ","
465  << that.fNumStmts << endl;
466  return kFALSE;
467  }
468 
469  list<string>::const_iterator itrThisBegin = fSqlStmts.begin();
470  list<string>::const_iterator itrThisEnd = fSqlStmts.end();
471  list<string>::const_iterator itrThatBegin = that.fSqlStmts.begin();
472  list<string>::const_iterator itrThatEnd = that.fSqlStmts.end();
473 
474  list<string>::const_iterator itrThis = itrThisBegin;
475  list<string>::const_iterator itrThat = itrThatBegin;
476 
477  Bool_t isEqual = kTRUE;
478 
479  // Strip off InsertDate from first statement (assume its
480  // the last parameter in list).
481 
482  string strThis = (*itrThis).substr(0,(*itrThis).rfind(','));
483  string strThat = (*itrThat).substr(0,(*itrThat).rfind(','));
484  if ( strThis != strThat ) {
485  if ( ! log ) { return kFALSE; }
486  isEqual = kFALSE;
487 
488  cout << "Difference on VAL record " << ":-\n"
489  << " " << thisName << ": " << strThis << endl
490  << " " << thatName << ": " << strThat << endl;
491  }
492 
493  // Rows can come in any order (after the first) so we have
494  // to sort before comparing. However, if we are lucky, they
495  // may be in the same order or inverse order so do a quick
496  // test to see if there are no conflicts assuming these
497  // relative orderings.
498 
499  ++itrThis;
500  ++itrThat;
501  while ( itrThis != itrThisEnd && (*itrThis) == (*itrThat) ) {
502 // cout << "Debug: trying forward compare ..." << *itrThis
503 // << "::" << *itrThat << endl;
504  ++itrThis;
505  ++itrThat;
506  }
507  if ( itrThis == itrThisEnd ) { return isEqual; }
508 
509  itrThis = itrThisBegin;
510  itrThat = itrThatEnd;
511  ++itrThis;
512  --itrThat;
513 
514  while ( itrThis != itrThisEnd && (*itrThis) == (*itrThat) ) {
515 // cout << "Debug: trying reverse compare ..." << *itrThis
516 // << "::" << *itrThat << endl;
517  ++itrThis;
518  --itrThat;
519  }
520  if ( itrThis == itrThisEnd ) { return isEqual; }
521 
522  // O.K., we are out of luck so set up pointers to both sets
523  // and sort these.
524 
525  typedef vector<const string*> shadow_list_t;
526  typedef shadow_list_t::iterator shadow_list_itr_t;
527 
528  shadow_list_t shadowThis;
529  shadow_list_t shadowThat;
530 
531  itrThis = itrThisBegin;
532  itrThat = itrThatBegin;
533  ++itrThis;
534  ++itrThat;
535 
536  while ( itrThis != itrThisEnd ) {
537  shadowThis.push_back(&(*itrThis));
538  shadowThat.push_back(&(*itrThat));
539  ++itrThis;
540  ++itrThat;
541  }
542 
543  shadow_list_itr_t shadowThisItr = shadowThis.begin();
544  shadow_list_itr_t shadowThisItrEnd = shadowThis.end();
545  shadow_list_itr_t shadowThatItr = shadowThat.begin();
546  shadow_list_itr_t shadowThatItrEnd = shadowThat.end();
547 
548  sort(shadowThisItr,shadowThisItrEnd,compStringPtrs);
549  sort(shadowThatItr,shadowThatItrEnd,compStringPtrs);
550 
551  while ( shadowThisItr != shadowThisItrEnd ) {
552  if ( (**shadowThisItr) != (**shadowThatItr) ) {
553  if ( ! log ) { return kFALSE; }
554  isEqual = kFALSE;
555  cout << "Difference on data record "
556  << ":-\n"
557  << " " << thisName << ": " << **shadowThisItr << endl
558  << " " << thatName << ": " << **shadowThatItr << endl;
559  }
560  ++shadowThisItr;
561  ++shadowThatItr;
562  }
563 
564  return isEqual;
565 
566 }
567 
568 //.....................................................................
569 
570 void FairDbSqlValPacket::Print(Option_t* /* option */) const
571 {
572 
573 
574  cout << "FairDbSQLValPacket:"
575  << " table \"" << fTableName << "\" "
576  << " SeqNo " << fSeqNo
577  << " NumErrors " << fNumErrors
578  << endl
579  << " CreationDate " << fCreationDate
580  << endl;
581 
582 
583  cout << " MySQL Main table creation: \"" << fSqlMySqlMetaMain << "\"" << endl;
584 
585 
586  cout << " MySQL VAL table creation: \"" << fSqlMySqlMetaVal << "\"" << endl;
587 
588  if ( GetNumSqlStmts() > 0 ) {
589  std::list<string>::const_iterator itr = fSqlStmts.begin();
590  std::list<string>::const_iterator itrEnd = fSqlStmts.end();
591  for (; itr != itrEnd; ++itr)
592 
593  {
594  cout << " SqlStmt \"" << *itr << "\"" << endl;
595  }
596  } else {
597  cout << " No SqlStmts." << endl;
598  }
599 
600 }
601 
602 
603 //.....................................................................
604 
605 void FairDbSqlValPacket::Recreate(const string& tableName,
606  const ValRange& vr,
607  Int_t aggNo,
608  FairDb::Task task, /* Default: 0 */
609  ValTimeStamp creationDate /* Default: now */
610  )
611 {
612 
613 
614  this->Clear();
615 
617  if ( ! tablePR.GetMultConnector().TableExists(tableName) ) {
618  cout << "Cannot create packet - table " << tableName
619  << " does not exist." << endl;
620  fNumErrors = 1;
621  return;
622  }
623 
624  fTableName = tableName;
625 
626 
627  // Create a FairDbValidityRec from the supplied data.
628  FairDbValidityRec vrec(vr,task,aggNo,0);
629 
630  // Create a FairDbOutRowStream that can serialise this validity record
631  FairDbConfigSet dummy; // For validity row any FairDbTableRow will do.
632  const FairDbTableMetaData& metaValid = tablePR.GetTableProxy(tableName,&dummy)
633  .GetMetaValid();
634  FairDbOutRowStream buff(&metaValid);
635 
636  vrec.Store(buff,0);
637  this->AddRow(buff.GetCSV());
638  this->SetCreationDate(creationDate);
639 
640 }
641 
642 //.....................................................................
643 
644 void FairDbSqlValPacket::Report(const char* msg,
645  UInt_t lineNum,
646  const string& line)
647 {
648  cout << msg << " on line " << lineNum
649  <<":- \n " << line << endl;
650  this->Reset();
651  ++fNumErrors;
652 
653 }
654 //.....................................................................
655 
657 {
658 
659 
660  fSeqNo = 0;
661  fSqlMySqlMetaMain = "";
662  fSqlMySqlMetaVal = "";
663  fSqlStmts.clear();
664  fNumStmts = 0;
665  fTableName = "";
666 
667 }
668 //.....................................................................
669 
671 {
672 
673  fCreationDate = ts;
674 
675  // Update the validity row assuming: "...,'creationdate',insertdate);"
676  if ( this->GetNumSqlStmts() == 0 ) { return; }
677 
678  string& vldRow = *fSqlStmts.begin();
679  string::size_type locEnd = vldRow.rfind(',');
680  if ( locEnd == string::npos ) { return; }
681  locEnd -=2;
682  string::size_type locStart = vldRow.rfind(',',locEnd);
683  if ( locStart == string::npos ) { return; }
684  locStart+=2;
685  vldRow.replace(locStart,locEnd-locStart+1,ts.AsString("s"));
686 
687 }
688 
689 //.....................................................................
690 
692 {
693 
695 
696  // Locate the table in the cascade.
697  FairDbMultConnector& cas = tbprxreg.GetMultConnector();
698  Int_t dbNo = cas.GetTableDbNo(this->GetTableName());
699  if ( dbNo < 0 ) { return; }
700 
701  // Any table proxy will do to get the meta-data so use the one for a
702  // FairDbConfigSet;
703  FairDbConfigSet dummy;
704  const FairDbTableMetaData& metaVal = tbprxreg.GetTableProxy(this->GetTableName(),&dummy)
705  .GetMetaValid();
706  const FairDbTableMetaData& metaMain = tbprxreg.GetTableProxy(this->GetTableName(),&dummy)
707  .GetMetaData();
708  fSqlMySqlMetaVal = metaVal.Sql();
709  fSqlMySqlMetaMain = metaMain.Sql();
710 
711 }
712 
713 //.....................................................................
714 
716 {
717 
718  fSeqNo = seqno;
719 
720  // Update all rows
721  if ( this->GetNumSqlStmts() == 0 ) { return; }
722 
723  ostringstream tmp;
724  tmp << seqno;
725  const string seqnoStr = tmp.str();
726 
727  std::list<string>::iterator itr = fSqlStmts.begin();
728  std::list<string>::iterator itrEnd = fSqlStmts.end();
729  for (; itr != itrEnd; ++itr) { SetSeqNoOnRow(*itr,seqnoStr); }
730 
731 }
732 
733 //.....................................................................
734 
735 void FairDbSqlValPacket::SetSeqNoOnRow(string& row,const string& seqno)
736 {
737 
738  string::size_type locStart = row.find('(');
739  if ( locStart == string::npos ) { return; }
740  ++locStart;
741  string::size_type locEnd = row.find(',',locStart);
742  if ( locEnd == string::npos ) { return; }
743  row.replace(locStart,locEnd-locStart,seqno);
744 
745 }
746 
747 //.....................................................................
748 
749 Bool_t FairDbSqlValPacket::Store(UInt_t dbNo, Bool_t replace) const
750 {
751 
752  if ( ! CanBeStored() ) { return kFALSE; }
753 
754  //Just use any old table row object just to get a FairDbDBProxy.
755  FairDbConfigSet pet;
757  .GetTableProxy(this->GetTableName(),&pet);
758  if ( replace ) {
759  const FairDbProxy& proxy = tp.GetDBProxy();
760  if ( ! proxy.RemoveSeqNo(this->GetSeqNo(),dbNo) ) { return kFALSE; }
761  }
762 
763  // Locate required FairDbStatement.
764  auto_ptr<FairDbStatement> stmtDb(FairDbTableProxyRegistry::Instance()
765  .GetMultConnector()
766  .CreateStatement(dbNo));
767  if ( ! stmtDb.get() ) {
768 
769  cout << "Attempting to write to non-existant cascade entry " << dbNo
770  << endl;
771  return kFALSE;
772  }
773 
774  // Decide if ROW_COUNTER column has to be removed i.e. Master
775  // DB exported with ROW_COUNTER but Slave still has old table form
776  // without ROW_COUNTER.
777 
778  bool removeRowCounter = fgLastMetaHadRowCounter
779  && ! tp.GetMetaData().HasRowCounter();
780 
781  // Loop processing all SQL statements
782  Bool_t first = kTRUE;
783  int combineInserts = 0;
784  // Cannot group ORACLE inserts.
785  int maxInserts = stmtDb->GetDBType() == FairDb::kOracle ? 1 : 20;
786  string sqlInserts;
787 
788  for (list<string>::const_iterator itr = fSqlStmts.begin();
789  itr != fSqlStmts.end();
790  ++itr) {
791  if ( first ) {
792 // On first statement replace InsertDate by current datetime.
793  string sql = *itr;
794  list<string>::size_type locDate = sql.rfind(",\'");
795  if ( locDate != string::npos ) {
796  ValTimeStamp now;
797  sql.replace(locDate+2,19,FairDb::MakeDateTimeString(now));
798  }
799  stmtDb->ExecuteUpdate(sql.c_str());
800  if ( stmtDb->PrintExceptions() ) { return kFALSE; }
801  first = kFALSE;
802  continue;
803  }
804 
805  string sql = *itr;
806 
807 // On other statements remove the second (ROW_COUNTER) column if required.
808  if (removeRowCounter) {
809  list<string>::size_type locStart = sql.find(',');
810  ++locStart;
811  list<string>::size_type locEnd = sql.find(',',locStart);
812  if ( locEnd != string::npos ) {
813  list<string>::size_type numChars = locEnd - locStart + 1;
814  sql.erase(locStart,numChars);
815  }
816  }
817 
818 // Reduce database I/O by combining groups of insert commands.
819 
820  string::size_type insertIndex = sql.find("VALUES (");
821  if ( insertIndex == string::npos) {
822  cout << "Unexpected SQL : " << sql
823  << "\n should be of form INSERT INTO ... VALUES (...);" << endl;
824  return kFALSE;
825  }
826  ++combineInserts;
827  if ( combineInserts == 1 ) { sqlInserts = sql; }
828  else {
829  sqlInserts[sqlInserts.size()-1] = ',';
830  sqlInserts += sql.substr(insertIndex+7);
831  }
832  if ( combineInserts >= maxInserts ) {
833  stmtDb->ExecuteUpdate(sqlInserts.c_str());
834  if ( stmtDb->PrintExceptions() ) { return kFALSE; }
835  combineInserts = 0;
836  }
837  }
838 
839 // Deal with last group of inserts.
840  if ( combineInserts ) {
841  stmtDb->ExecuteUpdate(sqlInserts.c_str());
842  combineInserts = 0;
843  if ( stmtDb->PrintExceptions() ) { return kFALSE; }
844  }
845 
846  return kTRUE;
847 
848 }
849 
850 Bool_t FairDbSqlValPacket::Write(std::ofstream& ios,
851  Bool_t addMetadata) const
852 {
853 
854 
855  if ( ! CanBeStored() ) { return kFALSE; }
856  if ( addMetadata ) {
857  if ( fSqlMySqlMetaMain.size() == 0 ) { this->SetMetaData(); }
858  if ( fSqlMySqlMetaMain.size() == 0 ) {
859 
860  cout<< "Cannot write metadata; no associated FairDbTableProxy "
861  << endl;
862  } else {
863 
864 
865  ios << ">>>>>" << GetTableName() << " Metadata [MySQL]" << endl;
866  ios << fSqlMySqlMetaVal << endl;
867  ios << fSqlMySqlMetaMain << endl;
868  ios << "<<<<<" << GetTableName() << " Metadata" << endl;
869  }
870  }
871 
872  ios << ">>>>>" << GetTableName() << " " << GetSeqNo() << endl;
873 
874  for ( list<string>::const_iterator itr = fSqlStmts.begin();
875  itr != fSqlStmts.end();
876  ++itr) { ios << (*itr) << endl; }
877 
878  ios << "<<<<<" << GetTableName() << " " << GetSeqNo() << endl;
879 
880  return kTRUE;
881 
882 }
883