LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
DBDataset.cxx
Go to the documentation of this file.
1 //=================================================================================
2 //
3 // Name: DBDataset.cpp
4 //
5 // Purpose: Implementation for class DBDataset.
6 //
7 // Created: 26-Oct-2020 - H. Greenlee
8 //
9 //=================================================================================
10 
11 #include "DBDataset.h"
12 #include "WebDBIConstants.h"
13 #include "cetlib_except/exception.h"
15 #include "wda.h"
16 #include <cstring>
17 
18 // Default constructor.
19 
20 lariov::DBDataset::DBDataset() : fBeginTime(0, 0), fEndTime(0, 0) {}
21 
22 // Libwda initializing constructor.
23 
24 lariov::DBDataset::DBDataset(void* dataset, bool release) : fBeginTime(0, 0), fEndTime(0, 0)
25 {
26  // Parse dataset and get number of rows.
27 
28  size_t nrows = getNtuples(dataset) - kNUMBER_HEADER_ROWS;
29  //mf::LogInfo("DBDataset") << "DBDataset: Number of rows = " << nrows << "\n";
30  fChannels.reserve(nrows);
31 
32  // Process header rows.
33 
34  int err = 0;
35  char buf[kBUFFER_SIZE];
36  Tuple tup;
37 
38  // Extract IOV begin time.
39 
40  tup = getTuple(dataset, 0);
41  getStringValue(tup, 0, buf, kBUFFER_SIZE, &err);
42  fBeginTime = IOVTimeStamp::GetFromString(std::string(buf));
43  //mf::LogInfo log("DBDataset");
44  //log << "DBDataset: Begin time stamp input = " << buf << "\n";
45  //log << "DBDataset: Begin time stamp = " << fBeginTime.DBStamp() << "\n";
46  releaseTuple(tup);
47 
48  // Extract IOV end time.
49 
50  tup = getTuple(dataset, 1);
51  getStringValue(tup, 0, buf, kBUFFER_SIZE, &err);
52  if (0 == strcmp(buf, "-"))
54  else
55  fEndTime = IOVTimeStamp::GetFromString(std::string(buf));
56  //mf::LogInfo log("DBDataset");
57  //log << "DBDataset: End time stamp input = " << buf << "\n";
58  //log << "DBDataset: End time stamp = " << fEndTime.DBStamp() << "\n";
59  releaseTuple(tup);
60 
61  // Extract column names.
62 
63  tup = getTuple(dataset, 2);
64  size_t ncols = getNfields(tup);
65  //mf::LogInfo("DBDataset") << "DBDataset: Number of columns = " << ncols << "\n";
66  fColNames.reserve(ncols);
67  for (size_t col = 0; col < ncols; ++col) {
68  getStringValue(tup, col, buf, kBUFFER_SIZE, &err);
69  //mf::LogInfo("DBDataset") << "DBDataset: Column name = " << buf << "\n";
70  fColNames.push_back(std::string(buf));
71  }
72  releaseTuple(tup);
73 
74  // Extract column types.
75 
76  tup = getTuple(dataset, 3);
77  fColTypes.reserve(ncols);
78  for (size_t col = 0; col < ncols; ++col) {
79  getStringValue(tup, col, buf, kBUFFER_SIZE, &err);
80  //mf::LogInfo("DBDataset") << "DBDataset: Column type = " << buf << "\n";
81  fColTypes.push_back(std::string(buf));
82  }
83  releaseTuple(tup);
84 
85  // Extract data. Loop over rows.
86 
87  fData.reserve(nrows * ncols);
88  for (size_t row = 0; row < nrows; ++row) {
89  //mf::LogInfo("DBDataset") << "\nRow " << row << "\n";
90  tup = getTuple(dataset, row + kNUMBER_HEADER_ROWS);
91 
92  // Loop over columns.
93 
94  for (size_t col = 0; col < ncols; ++col) {
95  getStringValue(tup, col, buf, kBUFFER_SIZE, &err);
96 
97  // Convert string value to DBDataset::value_type (std::variant).
98 
99  if (fColTypes[col] == "integer" || fColTypes[col] == "bigint") {
100  long value = strtol(buf, 0, 10);
101  fData.push_back(value_type(value));
102  //mf::LogInfo("DBDataset") << "DBDataset: row=" << row << ", column=" << col << ", value=" << fData.back()
103  // << "\n";
104  if (col == 0) {
105  fChannels.push_back(value);
106  //mf::LogInfo("DBDataset") << "DBDataset: channel=" << fChannels.back() << "\n";
107  }
108  }
109  else if (fColTypes[col] == "real") {
110  double value = strtod(buf, 0);
111  fData.push_back(value_type(value));
112  //mf::LogInfo("DBDataset") << "DBDataset: row=" << row << ", column=" << col << ", value=" << fData.back()
113  // << "\n";
114  if (col == 0) {
115  mf::LogError("DBDataset") << "First column has wrong type real."
116  << "\n";
117  throw cet::exception("DBDataset") << "First column has wrong type real.";
118  }
119  }
120  else if (fColTypes[col] == "text") {
121  fData.emplace_back(std::make_unique<std::string>(buf));
122  //mf::LogInfo("DBDataset") << "DBDataset: row=" << row << ", column=" << col << ", value=" << fData.back()
123  // << "\n";
124  if (col == 0) {
125  mf::LogError("DBDataset") << "First column has wrong type text."
126  << "\n";
127  throw cet::exception("DBDataset") << "First column has wrong type text.";
128  }
129  }
130  else if (fColTypes[col] == "boolean") {
131  long value = 0;
132  std::string s = std::string(buf);
133  if (s == "true" || s == "True" || s == "TRUE" || s == "1")
134  value = 1;
135  else if (s == "false" || s == "False" || s == "FALSE" || s == "0")
136  value = 0;
137  else {
138  mf::LogError("DBDataset") << "Unknown string representation of boolean " << s << "\n";
139  throw cet::exception("DBDataset")
140  << "Unknown string representation of boolean " << s << "\n";
141  }
142  fData.push_back(value_type(value));
143  //mf::LogInfo("DBDataset") << "DBDataset: row=" << row << ", column=" << col << ", value=" << fData.back()
144  // << "\n";
145  if (col == 0) {
146  mf::LogError("DBDataset") << "First column has wrong type boolean."
147  << "\n";
148  throw cet::exception("DBDataset") << "First column has wrong type boolean.";
149  }
150  }
151  else {
152  mf::LogError("DBDataset") << "Unknown datatype = " << fColTypes[col] << "\n";
153  throw cet::exception("DBDataset")
154  << "Unknown datatype = " << fColTypes[col] << ": " << buf << "\n";
155  }
156  }
157  releaseTuple(tup);
158  }
159 
160  // Maybe release dataset memory.
161 
162  if (release) releaseDataset(dataset);
163 }
164 
165 // SQLite initializing move constructor.
166 
167 lariov::DBDataset::DBDataset(const IOVTimeStamp& begin_time, // IOV begin time.
168  const IOVTimeStamp& end_time, // IOV end time.
169  std::vector<std::string>&& col_names, // Column names.
170  std::vector<std::string>&& col_types, // Column types.
171  std::vector<DBChannelID_t>&& channels, // Channels.
172  std::vector<value_type>&& data)
173  : // Calibration data.
174  fBeginTime(begin_time)
175  , fEndTime(end_time)
176  , fColNames(std::move(col_names))
177  , fColTypes(std::move(col_types))
178  , fChannels(std::move(channels))
179  , fData(std::move(data))
180 {}
181 
182 // Get row number by channel number.
183 // Return -1 if not found.
184 
185 int lariov::DBDataset::getRowNumber(DBChannelID_t ch) const
186 {
187  int result = -1;
188 
189  // Do a binary search on channel numbers.
190 
191  int low = 0;
192  int high = fChannels.size() - 1;
193  while (high - low > 1) {
194  int mid = (low + high) / 2;
195  if (fChannels[mid] < ch)
196  low = mid;
197  else if (fChannels[mid] > ch)
198  high = mid;
199  else {
200 
201  // Found an exact match. Break out of loop.
202 
203  result = mid;
204  break;
205  }
206  }
207 
208  // If we fell out of loop without finding a match...
209 
210  if (result < 0) {
211  if (fChannels[low] == ch)
212  result = low;
213  else if (fChannels[high] == ch)
214  result = high;
215  }
216 
217  // Done.
218 
219  return result;
220 }
221 
222 // Get column number by column name.
223 // Return -1 if not found.
224 
225 int lariov::DBDataset::getColNumber(const std::string& name) const
226 {
227  int result = -1;
228 
229  // Scan column names.
230 
231  for (size_t i = 0; i < fColNames.size(); ++i) {
232  if (fColNames[i] == name) {
233  result = i;
234  break;
235  }
236  }
237 
238  return result;
239 }
const unsigned int kNUMBER_HEADER_ROWS
std::variant< long, double, std::unique_ptr< std::string > > value_type
Definition: DBDataset.h:64
size_t nrows() const
Definition: DBDataset.h:117
STL namespace.
MaybeLogger_< ELseverityLevel::ELsev_error, false > LogError
std::vector< std::string > fColNames
Definition: DBDataset.h:138
void * Tuple
Definition: DBFolder.h:13
int getRowNumber(DBChannelID_t ch) const
Definition: DBDataset.cxx:185
const std::vector< value_type > & data() const
Definition: DBDataset.h:122
std::vector< std::string > fColTypes
Definition: DBDataset.h:139
IOVTimeStamp fBeginTime
Definition: DBDataset.h:136
Int_t col[ntarg]
Definition: Style.C:29
std::vector< value_type > fData
Definition: DBDataset.h:141
double value
Definition: spectrum.C:18
const unsigned int kBUFFER_SIZE
std::vector< DBChannelID_t > fChannels
Definition: DBDataset.h:140
const std::vector< DBChannelID_t > & channels() const
Definition: DBDataset.h:121
IOVTimeStamp fEndTime
Definition: DBDataset.h:137
size_t ncols() const
Definition: DBDataset.h:118
int getColNumber(const std::string &name) const
Definition: DBDataset.cxx:225
static IOVTimeStamp GetFromString(const std::string &ts)
static IOVTimeStamp MaxTimeStamp()
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33