DBFolder.cxx
Go to the documentation of this file.
1 #include "DBFolder.h"
2 #include "WebDBIConstants.h"
4 #include "WebError.h"
5 
6 #include <sstream>
7 #include <stdlib.h>
8 #include <cstring>
9 #include "wda.h"
10 #include "sqlite3.h"
11 #include "cetlib_except/exception.h"
12 #include "cetlib/search_path.h"
14 
15 namespace lariov {
16 
17  // Constructor.
18 
20  const std::string& tag, bool usesqlite, bool testmode)
21  {
22  fFolderName = name;
23  fURL = url;
24  fURL2 = url2;
25  fTag = tag;
26  fUseSQLite = usesqlite;
27  fTestMode = testmode;
28  if (fURL[fURL.length()-1] == '/') {
29  fURL = fURL.substr(0, fURL.length()-1);
30  }
31 
32  fCachedRowNumber = -1;
33  fCachedChannel = 0;
34 
35  fMaximumTimeout = 4*60; //4 minutes
36 
37  // If UsqSQLite is true, hunt for sqlite database file.
38  // It is an error if this file can't be found.
39 
40  //mf::LogInfo("DBFolder") << "DBFolder: Folder name = " << fFolderName << "\n";
41  if(fUseSQLite) {
42  std::string dbname = fFolderName + ".db";
43  cet::search_path sp("FW_SEARCH_PATH");
44  fSQLitePath = sp.find_file(dbname); // Throws exception if not found.
45  //mf::LogInfo("DBFolder") << "DBFolder: SQLite database path = " << fSQLitePath << "\n";
46  }
47  //else
48  // mf::LogInfo("DBFolder") << "DBFolder: database url = " << fURL << "\n";
49 
50  if(fTestMode && fURL2 != "") {
51  mf::LogInfo log("DBFolder");
52  log << "\nDBFolder test mode, will compare the following urls data." << "\n";
53  log << fURL << "\n";
54  log << fURL2 << "\n" << "\n";
55  }
56  if(fTestMode && fUseSQLite) {
57  mf::LogInfo log("DBFolder");
58  log << "\nDBFolder test mode, will compare the following url and sqlite data." << "\n";
59  log << fURL << "\n";
60  log << fSQLitePath << "\n" << "\n";
61  }
62  }
63 
64  // Destructor.
65 
67 
68  // Data accessors.
69 
71 
72  int err = 0;
73 
74  // Make sure cached row is valid.
75 
76  GetRow(channel);
77 
78  // Get column index.
79 
80  size_t col = GetColumn(name);
81 
82  // Get value.
83 
84  long value = fCachedRow.getLongData(col);
85  data = (value != 0);
86 
87  return err;
88  }
89 
91 
92  int err = 0;
93 
94  // Make sure cached row is valid.
95 
96  GetRow(channel);
97 
98  // Get column index.
99 
100  size_t col = GetColumn(name);
101 
102  // Get value.
103 
104  data = fCachedRow.getLongData(col);
105 
106  // Done.
107 
108  return err;
109  }
110 
112 
113  int err = 0;
114 
115  // Make sure cached row is valid.
116 
117  GetRow(channel);
118 
119  // Get column index.
120 
121  size_t col = GetColumn(name);
122 
123  // Get value.
124 
125  data = fCachedRow.getDoubleData(col);
126 
127  // Done.
128 
129  return err;
130  }
131 
133 
134  int err = 0;
135 
136  // Make sure cached row is valid.
137 
138  GetRow(channel);
139 
140  // Get column index.
141 
142  size_t col = GetColumn(name);
143 
144  // Get value.
145 
146  data = fCachedRow.getStringData(col);
147 
148  // Done.
149 
150  return err;
151  }
152 
153  // Not sure why the following accessor is included. Doesn't seem to be used.
154 
155  /*
156  int DBFolder::GetNamedChannelData(DBChannelID_t channel, const std::string& name, std::vector<double>& data) {
157 
158  data.clear();
159 
160  Tuple tup;
161  size_t col = this->GetRow(channel, name, tup);
162  int err=0;
163  double buf[kBUFFER_SIZE];
164 
165  DataRec *dataRec = (DataRec *)tup;
166  // for c2: col is an unsigned int and cannot be less than 0
167  // if (col < 0 || col >= dataRec->ncolumns) {
168  if (col >= dataRec->ncolumns) {
169  err=-1;
170  return err;
171  }
172 
173  char* sptr = dataRec->columns[col];
174  if ( *sptr == '[') sptr +=1; //expect an initial bracket and skip it
175  else {
176  err=-2;
177  return err;
178  }
179 
180  char* eptr;
181  double val;
182  unsigned int array_size=0;
183  for (unsigned int i=0; i < kBUFFER_SIZE; ++i) {
184  val = strtod(sptr, &eptr); //Try to convert
185  if (sptr==eptr) break; //conversion failed
186  if (*sptr=='\0') break; //end loop if buffer ends
187 
188  buf[array_size++] = val;
189 
190  if ( *eptr == ']') break; //found the closing bracket, we're done
191  else sptr = eptr+1; //point to the next value
192  }
193 
194  data.insert(data.begin(), buf, buf + array_size);
195  releaseTuple(tup);
196  return err;
197  }
198  */
199 
200  int DBFolder::GetChannelList( std::vector<DBChannelID_t>& channels ) const {
201 
202  channels = fCache.channels();
203  return 0;
204  }
205 
206  // Update cached row.
207 
209 
210  // Check if we need to update the cached row.
211 
212  if (fCachedChannel != channel ||
213  !fCachedRow.isValid() ||
215 
216  // Update cached row number (binary serach).
217 
218  int row = fCache.getRowNumber(channel);
219 
220  // Throw an exception if we didn't find a matching role.
221 
222  if(row < 0) {
223  std::string msg = "Channel " + std::to_string(channel) + " is not found in database!";
224  throw WebError(msg);
225  }
226 
227  // Update cached row.
228 
231  fCachedRow = fCache.getRow(row);
232  }
233  }
234 
235  // Find matching column.
236 
237  size_t DBFolder::GetColumn(const std::string& name) const
238  {
239  int col = fCache.getColNumber(name);
240 
241  // See if we found a matching column.
242 
243  if(col < 0) {
244  std::string msg = "Column " + name + " is not found in database!";
245  throw WebError(msg);
246  }
247 
248  // Done.
249 
250  return col;
251  }
252 
253  //returns true if an Update is performed, false if not
255 
256  //convert to IOVTimeStamp
258 
259  //check if cache is updated
260  if (IsValid(ts)) return false;
261 
262  //release cached data.
263  fCache = DBDataset();
265  fCachedRowNumber = -1;
266  fCachedChannel = 0;
267 
268  //get full url string
269  std::stringstream fullurl;
270  fullurl << fURL << "/data?f=" << fFolderName
271  << "&t=" << ts.DBStamp();
272  if (fTag.length() > 0) fullurl << "&tag=" << fTag;
273 
274  //mf::LogInfo log("DBFolder")
275  //log << "In DBFolder::UpdateData" << "\n";
276  //log << "t=" << raw_time/1000000000 << "\n";
277  //log << "Full url = " << fullurl.str() << "\n";
278 
279  //get new dataset
280  if(fSQLitePath != "" && !fTestMode) {
281  GetSQLiteData(raw_time/1000000000, fCache);
282  }
283  else {
284  if(fTestMode) {
285  mf::LogInfo log("DBFolder");
286  log << "Accessing primary calibration data from http conditions database server." << "\n";
287  log << "Folder = " << fFolderName << "\n";
288  }
289  int err = 0;
290  Dataset data = getDataWithTimeout(fullurl.str().c_str(), NULL, fMaximumTimeout, &err);
291  int status = getHTTPstatus(data);
292  if (status != 200) {
293  std::string msg = "HTTP error from " + fullurl.str()+": status: " + std::to_string(status) + ": " + std::string(getHTTPmessage(data));
294  throw WebError(msg);
295  }
296  fCache = DBDataset(data, true);
297  }
298  //DumpDataset(fCache);
299 
300 
301  // If test mode is selected, get comparison data.
302 
303  if(fTestMode) {
304  if(fSQLitePath != "") {
305  DBDataset compare1;
306  mf::LogInfo("DBFolder") << "Accessing comparison data from sqlite database " << fSQLitePath << "\n";
307  GetSQLiteData(raw_time/1000000000, compare1);
308  CompareDataset(fCache, compare1);
309  }
310  if(fURL2 != "") {
311  mf::LogInfo("DBFolder") <<"Accessing comparison data from second database url." << "\n";
312  std::stringstream fullurl2;
313  fullurl2 << fURL2 << "/data?f=" << fFolderName
314  << "&t=" << ts.DBStamp();
315  if (fTag.length() > 0) fullurl2 << "&tag=" << fTag;
316  mf::LogInfo("DBFolder") << "Full url = " << fullurl2.str() << "\n";
317  int err = 0;
318  Dataset data = getDataWithTimeout(fullurl2.str().c_str(), NULL, fMaximumTimeout, &err);
319  int status = getHTTPstatus(data);
320  if (status != 200) {
321  std::string msg = "HTTP error from " + fullurl2.str()+": status: " + std::to_string(status) + ": " + std::string(getHTTPmessage(data));
322  throw WebError(msg);
323  }
324  DBDataset compare2(data, true);
325  CompareDataset(fCache, compare2);
326  }
327  }
328  return true;
329  }
330 
331  // Query data from sqlite database.
332  // The return value of type Dataset (aka void*), is partially opaque type HttpResponse*
333  // (defined in wda.c and copied above).
334 
336  {
337  if(fSQLitePath == "")
338  return;
339 
340  // DBDataset data to be filled.
341 
342  IOVTimeStamp begin_ts(0, 0); // IOV begin time.
343  IOVTimeStamp end_ts(0, 0); // IOV end time.
344  std::vector<std::string> column_names; // Column names.
345  std::vector<std::string> column_types; // Column types.
346  std::vector<DBChannelID_t> channels; // Channels.
347  std::vector<DBDataset::value_type> values; // Calibration data (length nchan*ncols).
348 
349  //mf::LogInfo log("DBFolder")
350  //log << "DBFolder::GetSQLiteData" << "\n";
351  //log << "t=" << t << "\n";
352  //log << "sqlite path = " << fSQLitePath << "\n";
353 
354  // Open sqlite database.
355 
356  //mf::LogInfo("DBFolder") << "Opening sqlite database " << fSQLitePath << "\n";
357  sqlite3* db;
358  int rc = sqlite3_open(fSQLitePath.c_str(), &db);
359  if(rc != SQLITE_OK) {
360  mf::LogError("DBFolder") << "Failed to open sqlite database " << fSQLitePath << "\n";
361  throw cet::exception("DBFolder") << "Failed to open sqlite database " << fSQLitePath;
362  }
363 
364  // Query begin time of IOV.
365 
366  std::string table_iovs = fFolderName + "_iovs";
367  std::string table_tag_iovs = fFolderName + "_tag_iovs";
368  std::ostringstream sql;
369  sql << "SELECT " << table_iovs << ".iov_id," << table_iovs << ".begin_time"
370  << " FROM " << table_tag_iovs << "," << table_iovs
371  << " WHERE " << table_tag_iovs << ".tag='" << fTag << "'"
372  << " AND " << table_tag_iovs << ".iov_id=" << table_iovs << ".iov_id"
373  << " AND " << table_iovs << ".begin_time <= " << t
374  << " ORDER BY " << table_iovs << ".begin_time desc";
375  //mf::LogInfo("DBFolder") << "sql = " << sql.str() << "\n";
376 
377  // Prepare query.
378 
379  sqlite3_stmt* stmt;
380  rc = sqlite3_prepare_v2(db, sql.str().c_str(), -1, &stmt, 0);
381  if(rc != SQLITE_OK) {
382  mf::LogError log("DBFolder");
383  log << "sqlite3_prepare_v2 failed." << fSQLitePath << "\n";
384  log << "Failed sql = " << sql.str() << "\n";
385  throw cet::exception("DBFolder") << "sqlite3_prepare_v2 error.";
386  }
387 
388  // Execute query.
389  // Just retrieve first row.
390  // It is an error if we don't get at least one row.
391 
392  rc = sqlite3_step(stmt);
393  //int iov_id = 0;
394  int begin_time = 0;
395  if(rc == SQLITE_ROW) {
396  //iov_id = sqlite3_column_int(stmt, 0);
397  begin_time = sqlite3_column_int(stmt, 1);
398  //mf::LogInfo log("DBFolder")
399  //log << "iov_id = " << iov_id << "\n";
400  //log << "begin_time = " << begin_time << "\n";
401  }
402  else {
403  mf::LogError("DBFolder") << "sqlite3_step returned error result = " << rc << "\n";
404  throw cet::exception("DBFolder") << "sqlite3_step error.";
405  }
406 
407  // Delete query.
408 
409  sqlite3_finalize(stmt);
410 
411  // Query end time of IOV.
412 
413  sql.str("");
414  sql << "SELECT " << table_iovs << ".begin_time"
415  << " FROM " << table_tag_iovs << "," << table_iovs
416  << " WHERE " << table_tag_iovs << ".tag='" << fTag << "'"
417  << " AND " << table_tag_iovs << ".iov_id=" << table_iovs << ".iov_id"
418  << " AND " << table_iovs << ".begin_time > " << t
419  << " ORDER BY " << table_iovs << ".begin_time";
420  //mf::LogInfo("DBFolder") << "sql = " << sql.str() << "\n";
421 
422  // Prepare query.
423 
424  rc = sqlite3_prepare_v2(db, sql.str().c_str(), -1, &stmt, 0);
425  if(rc != SQLITE_OK) {
426  mf::LogError log("DBFolder");
427  log << "sqlite3_prepare_v2 failed." << fSQLitePath << "\n";
428  log << "Failed sql = " << sql.str() << "\n";
429  throw cet::exception("DBFolder") << "sqlite3_prepare_v2 error.";
430  }
431 
432  // Execute query.
433  // Just retrieve first row.
434  // If we don't get any rows, then end time is infinite.
435 
436  rc = sqlite3_step(stmt);
437  int end_time = 0;
438  if(rc == SQLITE_ROW) {
439  end_time = sqlite3_column_int(stmt, 0);
440  //mf::LogInfo("DBFolder") << "end_time = " << end_time << "\n";
441  }
442  else if(rc != SQLITE_DONE) {
443  mf::LogError("DBFolder") << "sqlite3_step returned error result = " << rc << "\n";
444  throw cet::exception("DBFolder") << "sqlite3_step error.";
445  }
446 
447  // Delete query.
448 
449  sqlite3_finalize(stmt);
450 
451  // Query count of channels.
452  // We do this so that we know how much memory to allocate.
453 
454  std::string table_data = fFolderName + "_data";
455  sql.str("");
456  sql << "SELECT COUNT(DISTINCT channel)"
457  << " FROM " << table_data << "," << table_iovs << "," << table_tag_iovs
458  << " WHERE " << table_tag_iovs << ".tag='" << fTag << "'"
459  << " AND " << table_iovs << ".iov_id=" << table_tag_iovs << ".iov_id"
460  << " AND " << table_data << ".__iov_id=" << table_tag_iovs << ".iov_id"
461  << " AND " << table_iovs << ".begin_time <= " << t;
462  //mf::LogInfo("DBFolder") << "sql = " << sql.str() << "\n";
463 
464  // Prepare query.
465 
466  rc = sqlite3_prepare_v2(db, sql.str().c_str(), -1, &stmt, 0);
467  if(rc != SQLITE_OK) {
468  mf::LogError log("DBFolder");
469  log << "sqlite3_prepare_v2 failed." << fSQLitePath << "\n";
470  log << "Failed sql = " << sql.str() << "\n";
471  throw cet::exception("DBFolder") << "sqlite3_prepare_v2 error.";
472  }
473 
474  // Execute query.
475  // Retrieve one row.
476  // It is an error if we don't get at least one row.
477 
478  rc = sqlite3_step(stmt);
479  unsigned int nrows = 0;
480  if(rc == SQLITE_ROW) {
481  nrows = sqlite3_column_int(stmt, 0);
482  //mf::LogInfo("DBFolder") << "Number of data rows = " << nrows << "\n";
483  }
484  else {
485  mf::LogError("DBFolder") << "sqlite3_step returned error result = " << rc << "\n";
486  throw cet::exception("DBFolder") << "sqlite3_step error.";
487  }
488 
489  // Reserve collections that depend on number of rows (only).
490 
491  channels.reserve(nrows);
492 
493  // Delete query.
494 
495  sqlite3_finalize(stmt);
496 
497  // Stash begin time.
498 
499  begin_ts = IOVTimeStamp(begin_time, 0);
500 
501  // Stash end time.
502 
503  if(end_time == 0)
504  end_ts = IOVTimeStamp::MaxTimeStamp();
505  else
506  end_ts = IOVTimeStamp(end_time, 0);
507 
508  // Main data query.
509 
510  sql.str("");
511  sql << "SELECT " << table_data << ".*,MAX(begin_time)"
512  << " FROM " << table_data << "," << table_iovs << "," << table_tag_iovs
513  << " WHERE " << table_tag_iovs << ".tag='" << fTag << "'"
514  << " AND " << table_iovs << ".iov_id=" << table_tag_iovs << ".iov_id"
515  << " AND " << table_data << ".__iov_id=" << table_tag_iovs << ".iov_id"
516  << " AND " << table_iovs << ".begin_time <= " << t
517  << " GROUP BY channel"
518  << " ORDER BY channel";
519  //mf::LogInfo("DBFolder") << "sql = " << sql.str() << "\n";
520 
521  // Prepare query.
522 
523  rc = sqlite3_prepare_v2(db, sql.str().c_str(), -1, &stmt, 0);
524  if(rc != SQLITE_OK) {
525  mf::LogError log("DBFolder");
526  log << "sqlite3_prepare_v2 failed." << fSQLitePath << "\n";
527  log << "Failed sql = " << sql.str() << "\n";
528  throw cet::exception("DBFolder") << "sqlite3_prepare_v2 error.";
529  }
530 
531  // Execute the query and retrieve one row.
532  // We do this to extract the number, names, and types of relevant columns.
533 
534  int ncols = sqlite3_column_count(stmt);
535  column_names.reserve(ncols);
536  column_types.reserve(ncols);
537 
538  rc = sqlite3_step(stmt);
539  if(rc == SQLITE_ROW) {
540 
541  // Loop over columns.
542 
543  for(int col = 0; col < ncols; ++col) {
544  std::string colname = sqlite3_column_name(stmt, col);
545 
546  // Ignore columns that begin with "_".
547  // Also ignore utility column MAX(begin_time).
548 
549  if(colname[0] != '_' && colname.substr(0,3) != "MAX") {
550  column_names.push_back(colname);
551  int dtype = sqlite3_column_type(stmt, col);
552  if(dtype == SQLITE_INTEGER)
553  column_types.push_back("integer");
554  else if(dtype == SQLITE_FLOAT)
555  column_types.push_back("real");
556  else if(dtype == SQLITE_TEXT)
557  column_types.push_back("text");
558  else if(dtype == SQLITE_NULL)
559  column_types.push_back("NULL");
560  else {
561  mf::LogError("DBFolder") << "Unknown type " << dtype << "\n";
562  throw cet::exception("DBFolder") << "Unknown type " << dtype;
563  }
564  //mf::LogInfo("DBFolder") << "Column " << col
565  // << ", name=" << column_names.back()
566  // << ", type=" << column_types.back() << "\n";
567  }
568  }
569  }
570  else {
571  mf::LogError("DBFolder") << "No data rows." << "\n";
572  throw cet::exception("DBFolder") << "No data rows.";
573  }
574 
575  // Remember the number of relevant columns.
576 
577  size_t nrelcols = column_names.size();
578  values.reserve(nrows * nrelcols);
579 
580  // Re-execute query.
581  // Retrieve all data rows and stash in result.
582 
583  rc = sqlite3_reset(stmt);
584  if(rc != SQLITE_OK) {
585  mf::LogError("DBFolder") << "sqlite3_reset failed." << "\n";
586  throw cet::exception("DBFolder") << "sqlite3_failed.";
587  }
588  size_t irow = 0;
589  while(rc != SQLITE_DONE) {
590  rc = sqlite3_step(stmt);
591  if(rc == SQLITE_ROW) {
592  ++irow;
593  //mf::LogInfo("DBFolder") << irow << " rows." << "\n";
594  if(irow > nrows) {
595  mf::LogError("DBFolder") << "Too many data rows " << irow << "\n";
596  throw cet::exception("DBFolder") << "Too many data rows " << irow;
597  }
598 
599  // Loop over columns.
600  // Remember that ncols is the number of columns returned by the query,
601  // not the number of columns that get stored (some columns are ignored).
602 
603  bool firstcol = true;
604  for(int col = 0; col < ncols; ++col) {
605  std::string colname = sqlite3_column_name(stmt, col);
606 
607  // Ignore columns that begin with "_".
608  // Also ignore utility column MAX(begin_time).
609 
610  if(colname[0] != '_' && colname.substr(0,3) != "MAX") {
611  int dtype = sqlite3_column_type(stmt, col);
612 
613  if(dtype == SQLITE_INTEGER) {
614  long value = sqlite3_column_int(stmt, col);
615  //mf::LogInfo("DBFolder") << "Value = " << value << "\n";
616  values.push_back(DBDataset::value_type(value));
617  if(firstcol)
618  channels.push_back(value);
619  }
620  else if(dtype == SQLITE_FLOAT) {
621  double value = sqlite3_column_double(stmt, col);
622  //mf::LogInfo("DBFolder") << "Value = " << value << "\n";
623  values.push_back(DBDataset::value_type(value));
624  if(firstcol) {
625  mf::LogError("DBFolder") << "First column has wrong type float." << "\n";
626  throw cet::exception("DBFolder") << "First column has wrong type float.";
627  }
628  }
629  else if(dtype == SQLITE_TEXT) {
630  const char* s = (const char*)sqlite3_column_text(stmt, col);
631  //mf::LogInfo("DBFolder") << "Value = " << s << "\n";
632  values.emplace_back(std::make_unique<std::string>(s));
633  if(firstcol) {
634  mf::LogError("DBFolder") << "First column has wrong type text." << "\n";
635  throw cet::exception("DBFolder") << "First column has wrong type text.";
636  }
637  }
638  else if(dtype == SQLITE_NULL) {
639  values.push_back(DBDataset::value_type());
640  //mf::LogInfo("DBFolder") << "Value = NULL" << "\n";
641  if(firstcol) {
642  mf::LogError("DBFolder") << "First column has wrong type null." << "\n";
643  throw cet::exception("DBFolder") << "First column has wrong type null.";
644  }
645  }
646  else {
647  mf::LogError("DBFolder") << "Unrecognized sqlite data type" << "\n";
648  throw cet::exception("DBFolder") << "Unrecognized sqlite data type.";
649  }
650  firstcol = false;
651  }
652  }
653  }
654  else if(rc != SQLITE_DONE) {
655  mf::LogError("DBFolder") << "sqlite3_step returned error result = " << rc << "\n";
656  throw cet::exception("DBFolder") << "sqlite3_step error.";
657  }
658  }
659  if(irow != nrows) {
660  mf::LogError("DBFolder") << "Wrong number of data rows " << irow << "," << nrows << "\n";
661  throw cet::exception("DBFolder") << "Wrong number of data rows " << irow << "," << nrows << "\n";
662  }
663  if(values.size() != nrows * nrelcols) {
664  mf::LogError("DBFolder") << "Wrong number of values "
665  << values.size() << "," << nrows << "," << nrelcols << "\n";
666  throw cet::exception("DBFolder") << "Wrong number of values "
667  << values.size() << "," << nrows << "," << nrelcols << "\n";
668  }
669 
670  // Delete statement.
671 
672  sqlite3_finalize(stmt);
673 
674  // Close database.
675 
676  sqlite3_close(db);
677 
678  // Fill result.
679 
680  data = DBDataset(begin_ts, end_ts,
681  std::move(column_names),
682  std::move(column_types),
683  std::move(channels),
684  std::move(values));
685 
686  // Done.
687 
688  return;
689  }
690 
691  // Dump dataset by rows.
692 
694  {
695  size_t nrows = data.nrows();
696  size_t ncols = data.ncols();
697  mf::LogInfo log("DBFolder");
698  log << "Dataset contains " << nrows << " rows and " << ncols << " columns." << "\n";
699 
700  // Begin time.
701 
702  log << "IOV start time = " << data.beginTime().DBStamp() << "\n";
703 
704  // End time.
705 
706  log << "IOV end time = " << data.endTime().DBStamp() << "\n";
707 
708  // Columnn names.
709 
710  const std::vector<std::string>& names = data.colNames();
711  for (size_t c=0; c<ncols; ++c)
712  log << "Column " << c << ", name = " << names[c] << "\n";
713 
714  // Row 3 - column types.
715 
716  const std::vector<std::string>& types = data.colTypes();
717  for (size_t c=0; c<ncols; ++c)
718  log << "Column " << c << ", type = " << types[c] << "\n";
719 
720  // Data rows.
721 
722  for(size_t row=0; row<nrows; ++row) {
723  log << "\nRow " << row << "\n";
724  DBDataset::DBRow dbrow = data.getRow(row);
725 
726  // Loop over columns.
727 
728  for(size_t col=0; col<ncols; ++col) {
729  if(types[col] == "bigint" || types[col] == "integer" || types[col] == "boolean") {
730  long value = dbrow.getLongData(col);
731  log << names[col] << " = " << value << "\n";
732  }
733  else if(types[col] == "real") {
734  double value = dbrow.getDoubleData(col);
735  log << names[col] << " = " << value << "\n";
736  }
737  else if(types[col] == "text" or types[col] == "boolean") {
738  std::string value = dbrow.getStringData(col);
739  log << names[col] << " = " << value << "\n";
740  }
741  else {
742  mf::LogError("DBFolder") << "Unknown type " << types[col] << "\n";
743  throw cet::exception("DBFolder") << "Unknown type.";
744  }
745  }
746  }
747  }
748 
749  bool DBFolder::CompareDataset(const DBDataset& data1, const DBDataset& data2) const
750  {
751  bool compare_ok = true;
752  mf::LogInfo("DBFolder") << "\nComparing datasets." << "\n";
753 
754  size_t nrows1 = data1.nrows();
755  size_t nrows2 = data2.nrows();
756  //mf::LogInfo log("DBFolder");
757  //log << "Dataset 1 contains " << nrows1 << " rows." << "\n";
758  //log << "Dataset 2 contains " << nrows2 << " rows." << "\n";
759  if(nrows1 != nrows2)
760  compare_ok = false;
761 
762  // Compare begin time.
763 
764  std::string begin1 = data1.beginTime().DBStamp();
765  std::string begin2 = data2.beginTime().DBStamp();
766  if(begin1 != begin2)
767  compare_ok = false;
768 
769  // Compare end time.
770 
771  std::string end1 = data1.beginTime().DBStamp();
772  std::string end2 = data2.beginTime().DBStamp();
773  if(end1 != end2)
774  compare_ok = false;
775 
776  // Compare column names.
777 
778  size_t ncols1 = data1.ncols();
779  size_t ncols2 = data2.ncols();
780  const std::vector<std::string>& names1 = data1.colNames();
781  const std::vector<std::string>& names2 = data2.colNames();
782  if(ncols1 != ncols2 || ncols1 != names1.size() || ncols2 != names2.size()) {
783  mf::LogWarning("DBFolder") << "Columns names size mismatch " << ncols1
784  << " vs. " << ncols2
785  << " vs. " << names1.size()
786  << " vs. " << names2.size()
787  << "\n";
788  compare_ok = false;
789  }
790  if(compare_ok) {
791  for (size_t c=0; c<ncols1; ++c) {
792  if(names1[c] != names2[c]) {
793  mf::LogWarning("DBFolder") << "Name mismatch " << names1[c] << " vs. " << names2[c] << "\n";
794  compare_ok = false;
795  }
796  }
797  }
798 
799  // Compare column types.
800 
801  const std::vector<std::string>& types1 = data1.colTypes();
802  const std::vector<std::string>& types2 = data2.colTypes();
803  if(ncols1 != ncols2 || ncols1 != types1.size() || ncols2 != types2.size()) {
804  mf::LogWarning("DBFolder") << "Column types ize mismatch " << ncols1
805  << " vs. " << ncols2
806  << " vs. " << types1.size()
807  << " vs. " << types2.size()
808  << "\n";
809  compare_ok = false;
810  }
811  if(compare_ok) {
812  for (size_t c=0; c<ncols2; ++c) {
813 
814  // Type "bigint" matches "integer."
815  // Type "boolean" matches "integer."
816 
817  std::string type1 = types1[c];
818  std::string type2 = types2[c];
819  if(type1 == "bigint" || type1 == "boolean")
820  type1 = "integer";
821  if(type2 == "bigint" || type2 == "boolean")
822  type2 = "integer";
823  if(type1 != type2) {
824  mf::LogWarning("DBFolder") << "Type mismatch " << type1 << " vs. " << type2 << "\n";
825  compare_ok = false;
826  }
827  }
828  }
829 
830  // Compare channels.
831 
832  const std::vector<DBChannelID_t>& channels1 = data1.channels();
833  const std::vector<DBChannelID_t>& channels2 = data2.channels();
834  if(nrows1 != nrows2 || nrows1 != channels1.size() || nrows2 != channels2.size()) {
835  mf::LogWarning("DBFolder") << "Channels size mismatch " << nrows1
836  << " vs. " << nrows2
837  << " vs. " << channels1.size()
838  << " vs. " << channels2.size()
839  << "\n";
840  compare_ok = false;
841  }
842  if(compare_ok) {
843  for (size_t r=0; r<nrows1; ++r) {
844  if(channels1[r] != channels2[r]) {
845  mf::LogWarning("DBFolder") << "Channel mismatch " << channels1[r] << " vs. " << channels2[r] << "\n";
846  compare_ok = false;
847  }
848  }
849  }
850 
851  // Compare number of values.
852 
853  if(data1.data().size() != data2.data().size()) {
854  mf::LogWarning("DBFolder") << "Values size mismatch " << data1.data().size()
855  << " vs. " << data2.data().size()
856  << "\n";
857  compare_ok = false;
858  }
859 
860  // Data rows.
861  if(compare_ok) {
862  for(size_t row=0; row<nrows1; ++row) {
863 
864  DBDataset::DBRow dbrow1 = data1.getRow(row);
865  DBDataset::DBRow dbrow2 = data2.getRow(row);
866  //mf::LogInfo("DBFolder") << "\nRow " << row << "\n";
867 
868  // Loop over columns.
869 
870  for(size_t col=0; col<ncols1; ++col) {
871  if(types1[col] == "integer" || types1[col] == "bigint" || types1[col] == "boolean") {
872  long value1 = dbrow1.getLongData(col);
873  long value2 = dbrow2.getLongData(col);
874  //mf::LogInfo log("DBFolder")
875  //log << names1[col] << " 1 = " << value1 << "\n";
876  //log << names2[col] << " 2 = " << value2 << "\n";
877  if(value1 != value2) {
878  mf::LogWarning("DBFolder") << "Value mismatch " << value1 << " vs. " << value2 << "\n";
879  compare_ok = false;
880  }
881  }
882  else if(types1[col] == "real") {
883  double value1 = dbrow1.getDoubleData( col);
884  double value2 = dbrow2.getDoubleData( col);
885  //mf::LogInfo log("DBFolder")
886  //log << names1[col] << " 1 = " << value1 << "\n";
887  //log << names2[col] << " 2 = " << value2 << "\n";
888  if(value1 != value2) {
889  mf::LogWarning("DBFolder") << "Value mismatch " << value1 << " vs. " << value2 << "\n";
890  compare_ok = false;
891  }
892  }
893  else if(types1[col] == "text") {
894  std::string value1 = dbrow2.getStringData(col);
895  std::string value2 = dbrow2.getStringData(col);
896  if(value1 != value2) {
897  mf::LogWarning("DBFolder") << "Value mismatch " << value1 << " vs. " << value2 << "\n";
898  compare_ok = false;
899  }
900  }
901  else {
902  mf::LogError("DBFolder") << "Unknown type " << types1[col] << "\n";
903  throw cet::exception("DBFolder") << "Unknown type.";
904  }
905  }
906  }
907  }
908 
909  if(compare_ok) {
910  mf::LogInfo("DBFolder") << "Comparison OK.\n" << "\n";
911  }
912  else{
913  mf::LogError("DBFolder") << "Comparison fail." << "\n";
914  throw cet::exception("DBFolder") << "Comparison fail.";
915  }
916  return compare_ok;
917  }
918 
919 }//end namespace lariov
static QCString name
Definition: declinfo.cpp:673
std::string fURL
Definition: DBFolder.h:56
std::variant< long, double, std::unique_ptr< std::string > > value_type
Definition: DBDataset.h:67
virtual ~DBFolder()
Definition: DBFolder.cxx:66
int GetNamedChannelData(DBChannelID_t channel, const std::string &name, bool &data)
Definition: DBFolder.cxx:70
DBDataset fCache
Definition: DBFolder.h:67
int fCachedRowNumber
Definition: DBFolder.h:71
void msg(const char *fmt,...)
Definition: message.cpp:107
double getDoubleData(size_t col) const
Definition: DBDataset.h:87
bool UpdateData(DBTimeStamp_t raw_time)
Definition: DBFolder.cxx:254
std::string string
Definition: nybbler.cc:12
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
std::uint32_t DBChannelID_t
void GetRow(DBChannelID_t channel)
Definition: DBFolder.cxx:208
size_t nrows() const
Definition: DBDataset.h:123
const std::vector< std::string > & colNames() const
Definition: DBDataset.h:125
DBDataset::DBRow fCachedRow
Definition: DBFolder.h:73
const std::string & DBStamp() const
Definition: IOVTimeStamp.h:39
const std::string & getStringData(size_t col) const
Definition: DBDataset.h:84
std::uint64_t DBTimeStamp_t
struct sqlite3_stmt sqlite3_stmt
DBRow getRow(size_t row) const
Definition: DBDataset.h:137
uint8_t channel
Definition: CRTFragment.hh:201
MaybeLogger_< ELseverityLevel::ELsev_error, false > LogError
int getRowNumber(DBChannelID_t ch) const
Definition: DBDataset.cxx:188
int GetChannelList(std::vector< DBChannelID_t > &channels) const
Definition: DBFolder.cxx:200
DBChannelID_t fCachedChannel
Definition: DBFolder.h:72
int fMaximumTimeout
Definition: DBFolder.h:63
const std::vector< value_type > & data() const
Definition: DBDataset.h:128
bool IsValid(const IOVTimeStamp &time) const
Definition: DBFolder.h:50
def move(depos, offset)
Definition: depos.py:107
std::string fURL2
Definition: DBFolder.h:57
const IOVTimeStamp & endTime() const
Definition: DBDataset.h:122
const std::vector< std::string > & colTypes() const
Definition: DBDataset.h:126
void DumpDataset(const DBDataset &data) const
Definition: DBFolder.cxx:693
bool CompareDataset(const DBDataset &data1, const DBDataset &data2) const
Definition: DBFolder.cxx:749
Q_UINT16 values[128]
const IOVTimeStamp & beginTime() const
Definition: DBDataset.h:121
std::string fFolderName
Definition: DBFolder.h:58
void err(const char *fmt,...)
Definition: message.cpp:226
struct sqlite3 sqlite3
std::string fTag
Definition: DBFolder.h:59
Filters for channels, events, etc.
const std::vector< DBChannelID_t > & channels() const
Definition: DBDataset.h:127
void * Dataset
Definition: DBFolder.h:12
static const char types[][NUM_HTML_LIST_TYPES]
bool isValid() const
Definition: DBDataset.h:82
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
long getLongData(size_t col) const
Definition: DBDataset.h:86
std::string find_file(std::string const &filename) const
Definition: search_path.cc:96
size_t GetColumn(const std::string &name) const
Definition: DBFolder.cxx:237
size_t ncols() const
Definition: DBDataset.h:124
int getColNumber(const std::string &name) const
Definition: DBDataset.cxx:228
static IOVTimeStamp MaxTimeStamp()
unsigned nrows(sqlite3 *db, std::string const &tablename)
Definition: helpers.cc:82
std::string fSQLitePath
Definition: DBFolder.h:62
static std::vector< std::string > const names
Definition: FragmentType.hh:8
DBFolder(const std::string &name, const std::string &url, const std::string &url2, const std::string &tag="", bool useqlite=false, bool testmode=false)
Definition: DBFolder.cxx:19
static IOVTimeStamp DecodeTimeStamp(DBTimeStamp_t ts)
Collection of exception classes for WebDBI.
std::string to_string(ModuleType const mt)
Definition: ModuleType.h:34
static QCString * s
Definition: config.cpp:1042
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
void GetSQLiteData(int t, DBDataset &data) const
Definition: DBFolder.cxx:335