libdballe 9.13
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
11namespace dballe {
12namespace db {
13namespace summary {
14
18struct VarEntry
19{
20 VarDesc var;
21
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
58inline const VarDesc& station_entry_get_value(const VarEntry& item)
59{
60 return item.var;
61}
62
68template <typename Station>
69struct StationEntry
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
136template <typename Station>
137inline const Station&
138station_entries_get_value(const StationEntry<Station>& item)
139{
140 return item.station;
141}
142
148template <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
210extern template class StationEntry<dballe::Station>;
211extern template class StationEntry<dballe::DBStation>;
212
213extern template class StationEntries<dballe::Station>;
214extern template void
215StationEntries<dballe::Station>::add(const StationEntries<dballe::DBStation>&);
216
217extern template class StationEntries<dballe::DBStation>;
218extern template void
219StationEntries<dballe::DBStation>::add(const StationEntries<dballe::Station>&);
220
221template <typename S1, typename S2> inline S1 convert_station(const S2& s)
222{
223 throw wreport::error_unimplemented("unsupported station conversion");
224}
225
226template <> inline Station convert_station<Station, Station>(const Station& s)
227{
228 return s;
229}
230template <>
231inline DBStation convert_station<DBStation, DBStation>(const DBStation& s)
232{
233 return s;
234}
235
236template <>
237inline Station convert_station<Station, DBStation>(const DBStation& station)
238{
239 Station res(station);
240 return res;
241}
242
243template <>
244inline 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
253struct StationFilterBase
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
293template <class Station> struct StationFilter;
294
295template <> struct StationFilter<dballe::Station> : public StationFilterBase
296{
297 using StationFilterBase::StationFilterBase;
298 bool matches_station(const Station& station)
299 {
300 return StationFilterBase::matches_station(station);
301 }
302};
303
304template <> struct StationFilter<dballe::DBStation> : public StationFilterBase
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
319template <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
399extern template class Cursor<dballe::Station>;
400extern 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:16
Query used to filter DB-All.e data.
Definition query.h:17
JSON serializer.
Definition json.h:30
High level objects for working with DB-All.e DB summaries.
Definition summary.h:71
Definition types.h:940
int id
Database ID of the station.
Definition types.h:946
Range of datetimes.
Definition types.h:297
void merge(const DatetimeRange &range)
Merge range into this one, resulting in the smallest range that contains both.
Vertical level or layer.
Definition types.h:625
Station information.
Definition types.h:879
Ident ident
Mobile station identifier.
Definition types.h:887
Coords coords
Station coordinates.
Definition types.h:884
Report report
Report name for this station.
Definition types.h:881
Information on how a value has been sampled or computed with regards to time.
Definition types.h:689
Standard dballe::Query implementation.
Definition core/query.h:36
static const Query & downcast(const dballe::Query &query)
Return a reference to query downcasted as core::Query.
Set structure optimized for a small number of items.
Definition smallset.h:21
Definition json.h:163
wreport::Varcode get_varcode() const override
Get the variable code.
Definition summary_utils.h:386
DBStation get_station() const override
Get the whole station data in a single call.
Definition summary_utils.h:379
int remaining() const override
Get the number of rows still to be fetched.
Definition summary_utils.h:335
bool has_value() const override
Check if the cursor points to a valid value.
Definition summary_utils.h:330
Level get_level() const override
Get the level.
Definition summary_utils.h:384
size_t get_count() const override
Get the count of elements.
Definition summary_utils.h:394
void discard() override
Discard the results that have not been read yet.
Definition summary_utils.h:365
DatetimeRange get_datetimerange() const override
Get the datetime range.
Definition summary_utils.h:390
bool next() override
Get a new item from the results of a query.
Definition summary_utils.h:337
Trange get_trange() const override
Get the time range.
Definition summary_utils.h:385
Index of all stations known to a summary.
Definition summary_utils.h:152
void add(const StationEntries< Station > &entry)
Merge the given entries.
void add(const StationEntry< Station > &entry)
Merge the given entry.
void add(const StationEntries< OStation > &entry)
Merge the given entries.
void add(const Station &station, const VarDesc &vd, const dballe::DatetimeRange &dtrange, size_t count)
Merge the given entry.
Information about a station, and statistics about its variables.
Definition summary_utils.h:71
Definition summary_utils.h:293
Description of a variable, independent of where and when it was measured.
Definition summary.h:18
Statistics about a variable.
Definition summary_utils.h:19
Cursor iterating over summary entries.
Definition core/cursor.h:73
Class passed to key-value accessors to set values in an invoker-defined way.
Definition core/enq.h:18
Common base types used by most of DB-All.e code.