Package su.onno.ui
Class WidgetBuckets
java.lang.Object
su.onno.ui.WidgetBuckets
Builds the grouped-aggregate SQL behind the chart/stat/sparkline/gauge widgets (#199): a
GROUP BY groupBy[, seriesBy] computing one (or, for a dual-axis combo, two) aggregate
values per bucket, so a chart ships O(buckets) rows instead of the whole table. Date bucketing
maps to DATE_TRUNC (supported by both H2 and PostgreSQL).
Injection safety follows WidgetFilter/WidgetAggregate: every referenced
column must be one of the entity's known columns (or the small system allowlist) and match a
strict identifier pattern; values are always bound parameters. Unlike a filter typo (which
degrades to "no filter"), an unknown group/series/date column is an error — silently grouping
by nothing would draw a wrong chart, not an unfiltered one.
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic final recordThe rendered statement plus its bound parameters (the widget filter's bindings included).static final recordThe widget's aggregate request, straight from the query string. -
Field Summary
FieldsModifier and TypeFieldDescriptionSystem columns a widget may group/window on even though they aren't business attributes — per entity kind, because allowlisting a column the kind's table doesn't have (a catalog has no_date) would pass validation and then blow up in SQL.static final intMore x buckets than this is unreadable anyway; the query is capped and the rest dropped. -
Method Summary
Modifier and TypeMethodDescriptionstatic WidgetBuckets.Querybuild(WidgetBuckets.Request r, String table, Set<String> columns, WidgetFilter.Result filter) Render the bucket query.static WidgetBuckets.Queryspan(WidgetBuckets.Request r, String table, Set<String> columns, WidgetFilter.Result filter) The companion span query —MIN/MAXof the window column over the same filtered, windowed row set — so the client can auto-size the date granularity without ever fetching rows.
-
Field Details
-
CATALOG_SYSTEM_COLUMNS
System columns a widget may group/window on even though they aren't business attributes — per entity kind, because allowlisting a column the kind's table doesn't have (a catalog has no_date) would pass validation and then blow up in SQL. -
DOCUMENT_SYSTEM_COLUMNS
-
MAX_BUCKETS
public static final int MAX_BUCKETSMore x buckets than this is unreadable anyway; the query is capped and the rest dropped.- See Also:
-
-
Method Details
-
build
public static WidgetBuckets.Query build(WidgetBuckets.Request r, String table, Set<String> columns, WidgetFilter.Result filter) Render the bucket query. Result columns:_bucket(absent when un-grouped),_series(only withseriesBy),_value, and_value2(only for a combo). Ordered by bucket so date buckets come back chronological, capped atMAX_BUCKETS+ 1rows so the caller can detect truncation.- Throws:
IllegalArgumentException- on an unknown metric/column or date unit
-
span
public static WidgetBuckets.Query span(WidgetBuckets.Request r, String table, Set<String> columns, WidgetFilter.Result filter) The companion span query —MIN/MAXof the window column over the same filtered, windowed row set — so the client can auto-size the date granularity without ever fetching rows. Result columns:_min,_max.
-