libdballe 9.6
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
11namespace dballe {
12namespace db {
13namespace summary {
14
19{
20 VarDesc var;
21
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
50inline const VarDesc& station_entry_get_value(const VarEntry& item) { return item.var; }
51
57template<typename Station>
58struct 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
113template<typename Station>
114inline const Station& station_entries_get_value(const StationEntry<Station>& item) { return item.station; }
115
121template<typename Station>
122struct 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
161extern template class StationEntry<dballe::Station>;
162extern template class StationEntry<dballe::DBStation>;
163
164extern template class StationEntries<dballe::Station>;
165extern template void StationEntries<dballe::Station>::add(const StationEntries<dballe::DBStation>&);
166
167extern template class StationEntries<dballe::DBStation>;
168extern template void StationEntries<dballe::DBStation>::add(const StationEntries<dballe::Station>&);
169
170
171template<typename S1, typename S2>
172inline S1 convert_station(const S2& s)
173{
174 throw wreport::error_unimplemented("unsupported station conversion");
175}
176
177template<> inline Station convert_station<Station, Station>(const Station& s) { return s; }
178template<> inline DBStation convert_station<DBStation, DBStation>(const DBStation& s) { return s; }
179
180template<>
181inline Station convert_station<Station, DBStation>(const DBStation& station)
182{
183 Station res(station);
184 return res;
185}
186
187template<>
188inline 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
238template<class Station>
240
241template<>
243{
244 using StationFilterBase::StationFilterBase;
245 bool matches_station(const Station& station)
246 {
247 return StationFilterBase::matches_station(station);
248 }
249};
250
251template<>
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
268template<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 { 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;
342};
343
344extern template class Cursor<dballe::Station>;
345extern 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:16
bool is_missing() const
Check if the Ident is set to the missing value.
Query used to filter DB-All.e data.
Definition: query.h:15
JSON serializer.
Definition: json.h:30
High level objects for working with DB-All.e DB summaries.
Definition: summary.h:45
uint16_t Varcode
Definition: types.h:851
int id
Database ID of the station.
Definition: types.h:857
Range of datetimes.
Definition: types.h:295
void merge(const DatetimeRange &range)
Merge range into this one, resulting in the smallest range that contains both.
bool contains(int lat) const
Check if a point is inside this range (extremes included)
bool is_missing() const
Return true if the LatRange matches any latitude.
Vertical level or layer.
Definition: types.h:625
bool is_missing() const
Return true if the LonRange matches any longitude.
bool contains(int lon) const
Check if a point is inside this range (extremes included)
Station information.
Definition: types.h:794
Ident ident
Mobile station identifier.
Definition: types.h:802
Coords coords
Station coordinates.
Definition: types.h:799
std::string report
Report name for this station.
Definition: types.h:796
Information on how a value has been sampled or computed with regards to time.
Definition: types.h:687
Standard dballe::Query implementation.
Definition: core/query.h:35
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:17
Definition: json.h:166
Definition: summary_utils.h:270
wreport::Varcode get_varcode() const override
Get the variable code.
Definition: summary_utils.h:337
DBStation get_station() const override
Get the whole station data in a single call.
Definition: summary_utils.h:330
int remaining() const override
Get the number of rows still to be fetched.
Definition: summary_utils.h:282
bool has_value() const
Check if the cursor points to a valid value.
Definition: summary_utils.h:280
Level get_level() const override
Get the level.
Definition: summary_utils.h:335
size_t get_count() const override
Get the count of elements.
Definition: summary_utils.h:339
void discard() override
Discard the results that have not been read yet.
Definition: summary_utils.h:313
DatetimeRange get_datetimerange() const override
Get the datetime range.
Definition: summary_utils.h:338
bool next() override
Get a new item from the results of a query.
Definition: summary_utils.h:287
Trange get_trange() const override
Get the time range.
Definition: summary_utils.h:336
Index of all stations known to a summary.
Definition: summary_utils.h:123
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:59
Definition: summary_utils.h:199
Definition: summary_utils.h:239
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:67
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.