libdballe  9.14
summary_utils.h
1 #ifndef DBALLE_DB_SUMMARY_UTILS_H
2 #define DBALLE_DB_SUMMARY_UTILS_H
3 
4 #include <dballe/core/cursor.h>
5 #include <dballe/core/query.h>
6 #include <dballe/core/smallset.h>
7 #include <dballe/db/summary.h>
8 #include <dballe/types.h>
9 #include <wreport/error.h>
10 
11 namespace dballe {
12 namespace db {
13 namespace summary {
14 
18 struct VarEntry
19 {
20  VarDesc var;
21 
22  dballe::DatetimeRange dtrange;
23  size_t count = 0;
24 
25  VarEntry() = default;
26 
27  VarEntry(const VarDesc& var, const dballe::DatetimeRange& dtrange,
28  size_t count)
29  : var(var), dtrange(dtrange), count(count)
30  {
31  }
32 
33  VarEntry(const VarEntry&) = default;
34 
35  bool operator==(const VarEntry& o) const
36  {
37  return std::tie(var, dtrange, count) ==
38  std::tie(o.var, o.dtrange, o.count);
39  }
40  bool operator!=(const VarEntry& o) const
41  {
42  return std::tie(var, dtrange, count) !=
43  std::tie(o.var, o.dtrange, o.count);
44  }
45 
46  void merge(const dballe::DatetimeRange& dtrange, size_t count)
47  {
48  this->dtrange.merge(dtrange);
49  this->count += count;
50  }
51 
52  void to_json(core::JSONWriter& writer) const;
53  static VarEntry from_json(core::json::Stream& in);
54 
55  DBALLE_TEST_ONLY void dump(FILE* out) const;
56 };
57 
58 inline const VarDesc& station_entry_get_value(const VarEntry& item)
59 {
60  return item.var;
61 }
62 
68 template <typename Station>
70  : protected core::SmallSet<VarEntry, VarDesc, station_entry_get_value>
71 {
72  using SmallSet::add;
73  using SmallSet::begin;
74  using SmallSet::const_iterator;
75  using SmallSet::const_reverse_iterator;
76  using SmallSet::empty;
77  using SmallSet::end;
78  using SmallSet::iterator;
79  using SmallSet::rbegin;
80  using SmallSet::rend;
81  using SmallSet::reverse_iterator;
82  using SmallSet::size;
83  bool operator==(const StationEntry& o) const
84  {
85  return SmallSet::operator==(o);
86  }
87  bool operator!=(const StationEntry& o) const
88  {
89  return SmallSet::operator!=(o);
90  }
91 
92  Station station;
93 
94  StationEntry() = default;
95 
96  template <typename OStation>
97  StationEntry(const Station& station, const StationEntry<OStation>& entry)
98  : station(station)
99  {
100  for (const auto& item : entry)
101  this->add(item);
102  }
103 
104  StationEntry(const Station& station, const VarDesc& vd,
105  const dballe::DatetimeRange& dtrange, size_t count)
106  : station(station)
107  {
108  add(vd, dtrange, count);
109  }
110 
111  StationEntry(const StationEntry& entries, const dballe::Query& query)
112  : station(entries.station)
113  {
114  add_filtered(entries, query);
115  }
116 
117  StationEntry(const StationEntry&) = default;
118 
119  void add(const VarDesc& vd, const dballe::DatetimeRange& dtrange,
120  size_t count);
121  template <typename OStation>
122  void add(const StationEntry<OStation>& entries);
123  void add_filtered(const StationEntry& entries, const dballe::Query& query);
124  bool iter_filtered(
125  const dballe::Query& query,
126  std::function<bool(const Station&, const summary::VarDesc&,
127  const DatetimeRange& dtrange, size_t count)>
128  dest) const;
129 
130  void to_json(core::JSONWriter& writer) const;
131  static StationEntry from_json(core::json::Stream& in);
132 
133  DBALLE_TEST_ONLY void dump(FILE* out) const;
134 };
135 
136 template <typename Station>
137 inline const Station&
138 station_entries_get_value(const StationEntry<Station>& item)
139 {
140  return item.station;
141 }
142 
148 template <typename Station>
150  : protected core::SmallSet<StationEntry<Station>, Station,
151  station_entries_get_value<Station>>
152 {
154  station_entries_get_value<Station>>
155  Parent;
156  typedef typename Parent::iterator iterator;
157  typedef typename Parent::const_iterator const_iterator;
158  typedef typename Parent::reverse_iterator reverse_iterator;
159  typedef typename Parent::const_reverse_iterator const_reverse_iterator;
160  using Parent::begin;
161  using Parent::empty;
162  using Parent::end;
163  using Parent::rbegin;
164  using Parent::rend;
165  using Parent::size;
166  bool operator==(const StationEntries<Station>& o) const
167  {
168  return Parent::operator==(o);
169  }
170  bool operator!=(const StationEntries<Station>& o) const
171  {
172  return Parent::operator!=(o);
173  }
174 
176  void add(const Station& station, const VarDesc& vd,
177  const dballe::DatetimeRange& dtrange, size_t count);
178 
180  template <typename OStation>
181  void add(const StationEntries<OStation>& entry);
182 
184  void add(const StationEntries<Station>& entry);
185 
187  void add(const StationEntry<Station>& entry);
188 
189  void add_filtered(const StationEntries& entry, const dballe::Query& query);
190 
191  bool has(const Station& station) const
192  {
193  return this->find(station) != this->end();
194  }
195 
196  const StationEntries& sorted() const
197  {
198  if (this->dirty)
199  this->rearrange_dirty();
200  return *this;
201  }
202 
203  bool iter_filtered(
204  const dballe::Query& query,
205  std::function<bool(const Station&, const summary::VarDesc&,
206  const DatetimeRange& dtrange, size_t count)>
207  dest) const;
208 };
209 
210 extern template class StationEntry<dballe::Station>;
211 extern template class StationEntry<dballe::DBStation>;
212 
213 extern template class StationEntries<dballe::Station>;
214 extern template void
216 
217 extern template class StationEntries<dballe::DBStation>;
218 extern template void
220 
221 template <typename S1, typename S2> inline S1 convert_station(const S2& s)
222 {
223  throw wreport::error_unimplemented("unsupported station conversion");
224 }
225 
226 template <> inline Station convert_station<Station, Station>(const Station& s)
227 {
228  return s;
229 }
230 template <>
231 inline DBStation convert_station<DBStation, DBStation>(const DBStation& s)
232 {
233  return s;
234 }
235 
236 template <>
237 inline Station convert_station<Station, DBStation>(const DBStation& station)
238 {
239  Station res(station);
240  return res;
241 }
242 
243 template <>
244 inline DBStation convert_station<DBStation, Station>(const Station& station)
245 {
246  DBStation res;
247  res.report = station.report;
248  res.coords = station.coords;
249  res.ident = station.ident;
250  return res;
251 }
252 
254 {
255  const core::Query& q;
256  bool has_flt_rep_memo;
257  bool has_flt_ident;
258  bool has_flt_area;
259  bool has_flt_station;
260 
261  StationFilterBase(const dballe::Query& query)
262  : q(core::Query::downcast(query))
263  {
264  // Scan the filter building a todo list of things to match
265 
266  // If there is any filtering on the station, build a whitelist of
267  // matching stations
268  has_flt_rep_memo = !q.report.empty();
269  has_flt_ident = !q.ident.is_missing();
270  has_flt_area = !q.latrange.is_missing() || !q.lonrange.is_missing();
271  has_flt_station = has_flt_rep_memo || has_flt_area || has_flt_ident;
272  }
273 
274  template <typename Station> bool matches_station(const Station& station)
275  {
276  if (has_flt_area)
277  {
278  if (!q.latrange.contains(station.coords.lat) ||
279  !q.lonrange.contains(station.coords.lon))
280  return false;
281  }
282 
283  if (has_flt_rep_memo && q.report != station.report)
284  return false;
285 
286  if (has_flt_ident && q.ident != station.ident)
287  return false;
288 
289  return true;
290  }
291 };
292 
293 template <class Station> struct StationFilter;
294 
296 {
297  using StationFilterBase::StationFilterBase;
298  bool matches_station(const Station& station)
299  {
300  return StationFilterBase::matches_station(station);
301  }
302 };
303 
305 {
306  StationFilter(const dballe::Query& query) : StationFilterBase(query)
307  {
308  has_flt_station |= (q.ana_id != MISSING_INT);
309  }
310 
311  bool matches_station(const DBStation& station)
312  {
313  if (q.ana_id != MISSING_INT and station.id != q.ana_id)
314  return false;
315  return StationFilterBase::matches_station(station);
316  }
317 };
318 
319 template <typename Station> struct Cursor : public impl::CursorSummary
320 {
322  typename summary::StationEntries<Station>::const_iterator station_entry;
323  typename summary::StationEntry<Station>::const_iterator var_entry;
324  bool at_start = true;
325  int _remaining = 0;
326 
327  Cursor(const BaseSummary<Station>& summary, const Query& query);
328  Cursor(const summary::StationEntries<Station>& entries, const Query& query);
329 
330  bool has_value() const override
331  {
332  return !at_start && station_entry != results.end();
333  }
334 
335  int remaining() const override { return _remaining; }
336 
337  bool next() override
338  {
339  if (at_start)
340  {
341  station_entry = results.begin();
342  if (station_entry != results.end())
343  var_entry = station_entry->begin();
344  at_start = false;
345  }
346  else if (station_entry == results.end())
347  return false;
348  else
349  {
350  if (var_entry != station_entry->end())
351  ++var_entry;
352  if (var_entry == station_entry->end())
353  {
354  ++station_entry;
355  if (station_entry != results.end())
356  {
357  var_entry = station_entry->begin();
358  --_remaining;
359  }
360  }
361  }
362  return station_entry != results.end();
363  }
364 
365  void discard() override { station_entry = results.end(); }
366 
367  static DBStation _get_dbstation(const DBStation& s) { return s; }
368  static DBStation _get_dbstation(const dballe::Station& station)
369  {
370  DBStation res;
371  res.report = station.report;
372  res.coords = station.coords;
373  res.ident = station.ident;
374  return res;
375  }
376  static int _get_station_id(const DBStation& s) { return s.id; }
377  static int _get_station_id(const dballe::Station& s) { return MISSING_INT; }
378 
379  DBStation get_station() const override
380  {
381  return _get_dbstation(station_entry->station);
382  }
383 
384  Level get_level() const override { return var_entry->var.level; }
385  Trange get_trange() const override { return var_entry->var.trange; }
386  wreport::Varcode get_varcode() const override
387  {
388  return var_entry->var.varcode;
389  }
391  {
392  return var_entry->dtrange;
393  }
394  size_t get_count() const override { return var_entry->count; }
395 
396  void enq(impl::Enq& enq) const override;
397 };
398 
399 extern template class Cursor<dballe::Station>;
400 extern template class Cursor<dballe::DBStation>;
401 
402 } // namespace summary
403 } // namespace db
404 } // namespace dballe
405 
406 #endif
Base class for cursors that iterate over DB query results.
Definition: cursor.h:15
Definition: summary_utils.h:253
Common base types used by most of DB-All.e code.
Ident ident
Mobile station identifier.
Definition: types.h:887
Class passed to key-value accessors to set values in an invoker-defined way.
Definition: core/enq.h:17
bool contains(int lat) const
Check if a point is inside this range (extremes included)
Definition: json.h:162
Station information.
Definition: types.h:878
bool is_missing() const
Check if the Ident is set to the missing value.
Level get_level() const override
Get the level.
Definition: summary_utils.h:384
Description of a variable, independent of where and when it was measured.
Definition: summary.h:17
bool is_missing() const
Return true if the LatRange matches any latitude.
Information about a station, and statistics about its variables.
Definition: summary_utils.h:69
Report report
Report name for this station.
Definition: types.h:881
Coords coords
Station coordinates.
Definition: types.h:884
Information on how a value has been sampled or computed with regards to time.
Definition: types.h:688
Trange get_trange() const override
Get the time range.
Definition: summary_utils.h:385
Definition: summary_utils.h:293
Standard dballe::Query implementation.
Definition: core/query.h:35
void add(const Station &station, const VarDesc &vd, const dballe::DatetimeRange &dtrange, size_t count)
Merge the given entry.
Definition: cmdline.h:18
static const Query & downcast(const dballe::Query &query)
Return a reference to query downcasted as core::Query.
bool contains(int lon) const
Check if a point is inside this range (extremes included)
Vertical level or layer.
Definition: types.h:624
bool is_missing() const
Return true if the LonRange matches any longitude.
int remaining() const override
Get the number of rows still to be fetched.
Definition: summary_utils.h:335
Range of datetimes.
Definition: types.h:296
Definition: summary_utils.h:319
Set structure optimized for a small number of items.
Definition: smallset.h:20
bool next() override
Get a new item from the results of a query.
Definition: summary_utils.h:337
int id
Database ID of the station.
Definition: types.h:946
wreport::Varcode get_varcode() const override
Get the variable code.
Definition: summary_utils.h:386
High level objects for working with DB-All.e DB summaries.
Definition: summary.h:70
Statistics about a variable.
Definition: summary_utils.h:18
JSON serializer.
Definition: json.h:29
Cursor iterating over summary entries.
Definition: core/cursor.h:72
void discard() override
Discard the results that have not been read yet.
Definition: summary_utils.h:365
Definition: types.h:939
void merge(const DatetimeRange &range)
Merge range into this one, resulting in the smallest range that contains both.
Index of all stations known to a summary.
Definition: summary_utils.h:149
DBStation get_station() const override
Get the whole station data in a single call.
Definition: summary_utils.h:379
DatetimeRange get_datetimerange() const override
Get the datetime range.
Definition: summary_utils.h:390
Query used to filter DB-All.e data.
Definition: query.h:16
size_t get_count() const override
Get the count of elements.
Definition: summary_utils.h:394
bool has_value() const override
Check if the cursor points to a valid value.
Definition: summary_utils.h:330