libdballe  9.11
summary_utils.h
1 #ifndef DBALLE_DB_SUMMARY_UTILS_H
2 #define DBALLE_DB_SUMMARY_UTILS_H
3 
4 #include <dballe/core/smallset.h>
5 #include <dballe/core/query.h>
6 #include <dballe/core/cursor.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, size_t count)
28  : var(var), dtrange(dtrange), count(count)
29  {
30  }
31 
32  VarEntry(const VarEntry&) = default;
33 
34  bool operator==(const VarEntry& o) const { return std::tie(var, dtrange, count) == std::tie(o.var, o.dtrange, o.count); }
35  bool operator!=(const VarEntry& o) const { return std::tie(var, dtrange, count) != std::tie(o.var, o.dtrange, o.count); }
36 
37  void merge(const dballe::DatetimeRange& dtrange, size_t count)
38  {
39  this->dtrange.merge(dtrange);
40  this->count += count;
41  }
42 
43  void to_json(core::JSONWriter& writer) const;
44  static VarEntry from_json(core::json::Stream& in);
45 
46  DBALLE_TEST_ONLY void dump(FILE* out) const;
47 };
48 
49 
50 inline const VarDesc& station_entry_get_value(const VarEntry& item) { return item.var; }
51 
57 template<typename Station>
58 struct StationEntry : protected core::SmallSet<VarEntry, VarDesc, station_entry_get_value>
59 {
60  using SmallSet::iterator;
61  using SmallSet::const_iterator;
62  using SmallSet::reverse_iterator;
63  using SmallSet::const_reverse_iterator;
64  using SmallSet::begin;
65  using SmallSet::end;
66  using SmallSet::rbegin;
67  using SmallSet::rend;
68  using SmallSet::size;
69  using SmallSet::empty;
70  using SmallSet::add;
71  bool operator==(const StationEntry& o) const { return SmallSet::operator==(o); }
72  bool operator!=(const StationEntry& o) const { return SmallSet::operator!=(o); }
73 
74  Station station;
75 
76  StationEntry() = default;
77 
78  template<typename OStation>
79  StationEntry(const Station& station, const StationEntry<OStation>& entry)
80  : station(station)
81  {
82  for (const auto& item: entry)
83  this->add(item);
84  }
85 
86  StationEntry(const Station& station, const VarDesc& vd, const dballe::DatetimeRange& dtrange, size_t count)
87  : station(station)
88  {
89  add(vd, dtrange, count);
90  }
91 
92  StationEntry(const StationEntry& entries, const dballe::Query& query)
93  : station(entries.station)
94  {
95  add_filtered(entries, query);
96  }
97 
98  StationEntry(const StationEntry&) = default;
99 
100  void add(const VarDesc& vd, const dballe::DatetimeRange& dtrange, size_t count);
101  template<typename OStation>
102  void add(const StationEntry<OStation>& entries);
103  void add_filtered(const StationEntry& entries, const dballe::Query& query);
104  bool iter_filtered(const dballe::Query& query, std::function<bool(const Station&, const summary::VarDesc&, const DatetimeRange& dtrange, size_t count)> dest) const;
105 
106  void to_json(core::JSONWriter& writer) const;
107  static StationEntry from_json(core::json::Stream& in);
108 
109  DBALLE_TEST_ONLY void dump(FILE* out) const;
110 };
111 
112 
113 template<typename Station>
114 inline const Station& station_entries_get_value(const StationEntry<Station>& item) { return item.station; }
115 
121 template<typename Station>
122 struct StationEntries : protected core::SmallSet<StationEntry<Station>, Station, station_entries_get_value<Station>>
123 {
124  typedef core::SmallSet<StationEntry<Station>, Station, station_entries_get_value<Station>> Parent;
125  typedef typename Parent::iterator iterator;
126  typedef typename Parent::const_iterator const_iterator;
127  typedef typename Parent::reverse_iterator reverse_iterator;
128  typedef typename Parent::const_reverse_iterator const_reverse_iterator;
129  using Parent::begin;
130  using Parent::end;
131  using Parent::rbegin;
132  using Parent::rend;
133  using Parent::size;
134  using Parent::empty;
135  bool operator==(const StationEntries<Station>& o) const { return Parent::operator==(o); }
136  bool operator!=(const StationEntries<Station>& o) const { return Parent::operator!=(o); }
137 
139  void add(const Station& station, const VarDesc& vd, const dballe::DatetimeRange& dtrange, size_t count);
140 
142  template<typename OStation>
143  void add(const StationEntries<OStation>& entry);
144 
146  void add(const StationEntries<Station>& entry);
147 
149  void add(const StationEntry<Station>& entry);
150 
151  void add_filtered(const StationEntries& entry, const dballe::Query& query);
152 
153  bool has(const Station& station) const { return this->find(station) != this->end(); }
154 
155  const StationEntries& sorted() const { if (this->dirty) this->rearrange_dirty(); return *this; }
156 
157  bool iter_filtered(const dballe::Query& query, std::function<bool(const Station&, const summary::VarDesc&, const DatetimeRange& dtrange, size_t count)> dest) const;
158 };
159 
160 
161 extern template class StationEntry<dballe::Station>;
162 extern template class StationEntry<dballe::DBStation>;
163 
164 extern template class StationEntries<dballe::Station>;
166 
167 extern template class StationEntries<dballe::DBStation>;
169 
170 
171 template<typename S1, typename S2>
172 inline S1 convert_station(const S2& s)
173 {
174  throw wreport::error_unimplemented("unsupported station conversion");
175 }
176 
177 template<> inline Station convert_station<Station, Station>(const Station& s) { return s; }
178 template<> inline DBStation convert_station<DBStation, DBStation>(const DBStation& s) { return s; }
179 
180 template<>
181 inline Station convert_station<Station, DBStation>(const DBStation& station)
182 {
183  Station res(station);
184  return res;
185 }
186 
187 template<>
188 inline DBStation convert_station<DBStation, Station>(const Station& station)
189 {
190  DBStation res;
191  res.report = station.report;
192  res.coords = station.coords;
193  res.ident = station.ident;
194  return res;
195 }
196 
197 
199 {
200  const core::Query& q;
201  bool has_flt_rep_memo;
202  bool has_flt_ident;
203  bool has_flt_area;
204  bool has_flt_station;
205 
206  StationFilterBase(const dballe::Query& query)
207  : q(core::Query::downcast(query))
208  {
209  // Scan the filter building a todo list of things to match
210 
211  // If there is any filtering on the station, build a whitelist of matching stations
212  has_flt_rep_memo = !q.report.empty();
213  has_flt_ident = !q.ident.is_missing();
214  has_flt_area = !q.latrange.is_missing() || !q.lonrange.is_missing();
215  has_flt_station = has_flt_rep_memo || has_flt_area || has_flt_ident;
216  }
217 
218  template<typename Station>
219  bool matches_station(const Station& station)
220  {
221  if (has_flt_area)
222  {
223  if (!q.latrange.contains(station.coords.lat) ||
224  !q.lonrange.contains(station.coords.lon))
225  return false;
226  }
227 
228  if (has_flt_rep_memo && q.report != station.report)
229  return false;
230 
231  if (has_flt_ident && q.ident != station.ident)
232  return false;
233 
234  return true;
235  }
236 };
237 
238 template<class Station>
240 
241 template<>
243 {
244  using StationFilterBase::StationFilterBase;
245  bool matches_station(const Station& station)
246  {
247  return StationFilterBase::matches_station(station);
248  }
249 };
250 
251 template<>
253 {
254  StationFilter(const dballe::Query& query)
255  : StationFilterBase(query)
256  {
257  has_flt_station |= (q.ana_id != MISSING_INT);
258  }
259 
260  bool matches_station(const DBStation& station)
261  {
262  if (q.ana_id != MISSING_INT and station.id != q.ana_id)
263  return false;
264  return StationFilterBase::matches_station(station);
265  }
266 };
267 
268 template<typename Station>
270 {
272  typename summary::StationEntries<Station>::const_iterator station_entry;
273  typename summary::StationEntry<Station>::const_iterator var_entry;
274  bool at_start = true;
275  int _remaining = 0;
276 
277  Cursor(const BaseSummary<Station>& summary, const Query& query);
278  Cursor(const summary::StationEntries<Station>& entries, const Query& query);
279 
280  bool has_value() const override { return !at_start && station_entry != results.end(); }
281 
282  int remaining() const override
283  {
284  return _remaining;
285  }
286 
287  bool next() override
288  {
289  if (at_start)
290  {
291  station_entry = results.begin();
292  if (station_entry != results.end())
293  var_entry = station_entry->begin();
294  at_start = false;
295  } else if (station_entry == results.end())
296  return false;
297  else {
298  if (var_entry != station_entry->end())
299  ++var_entry;
300  if (var_entry == station_entry->end())
301  {
302  ++station_entry;
303  if (station_entry != results.end())
304  {
305  var_entry = station_entry->begin();
306  --_remaining;
307  }
308  }
309  }
310  return station_entry != results.end();
311  }
312 
313  void discard() override
314  {
315  station_entry = results.end();
316  }
317 
318  static DBStation _get_dbstation(const DBStation& s) { return s; }
319  static DBStation _get_dbstation(const dballe::Station& station)
320  {
321  DBStation res;
322  res.report = station.report;
323  res.coords = station.coords;
324  res.ident = station.ident;
325  return res;
326  }
327  static int _get_station_id(const DBStation& s) { return s.id; }
328  static int _get_station_id(const dballe::Station& s) { return MISSING_INT; }
329 
330  DBStation get_station() const override
331  {
332  return _get_dbstation(station_entry->station);
333  }
334 
335  Level get_level() const override { return var_entry->var.level; }
336  Trange get_trange() const override { return var_entry->var.trange; }
337  wreport::Varcode get_varcode() const override { return var_entry->var.varcode; }
338  DatetimeRange get_datetimerange() const override { return var_entry->dtrange; }
339  size_t get_count() const override { return var_entry->count; }
340 
341  void enq(impl::Enq& enq) const override;
342 };
343 
344 extern template class Cursor<dballe::Station>;
345 extern template class Cursor<dballe::DBStation>;
346 
347 }
348 }
349 }
350 
351 #endif
Base class for cursors that iterate over DB query results.
Definition: cursor.h:15
Definition: summary_utils.h:198
Common base types used by most of DB-All.e code.
Ident ident
Mobile station identifier.
Definition: types.h:802
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:165
Station information.
Definition: types.h:793
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:335
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:58
Coords coords
Station coordinates.
Definition: types.h:799
Information on how a value has been sampled or computed with regards to time.
Definition: types.h:686
Trange get_trange() const override
Get the time range.
Definition: summary_utils.h:336
Definition: summary_utils.h:239
Standard dballe::Query implementation.
Definition: core/query.h:34
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:282
uint16_t Varcode
Range of datetimes.
Definition: types.h:294
Definition: summary_utils.h:269
Set structure optimized for a small number of items.
Definition: smallset.h:16
std::string report
Report name for this station.
Definition: types.h:796
bool next() override
Get a new item from the results of a query.
Definition: summary_utils.h:287
int id
Database ID of the station.
Definition: types.h:857
wreport::Varcode get_varcode() const override
Get the variable code.
Definition: summary_utils.h:337
High level objects for working with DB-All.e DB summaries.
Definition: summary.h:44
Statistics about a variable.
Definition: summary_utils.h:18
JSON serializer.
Definition: json.h:29
Cursor iterating over summary entries.
Definition: core/cursor.h:66
void discard() override
Discard the results that have not been read yet.
Definition: summary_utils.h:313
Definition: types.h:850
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:122
DBStation get_station() const override
Get the whole station data in a single call.
Definition: summary_utils.h:330
DatetimeRange get_datetimerange() const override
Get the datetime range.
Definition: summary_utils.h:338
Query used to filter DB-All.e data.
Definition: query.h:14
size_t get_count() const override
Get the count of elements.
Definition: summary_utils.h:339
bool has_value() const override
Check if the cursor points to a valid value.
Definition: summary_utils.h:280