RollupColumnGenerator
Namespace: Meshmakers.Octo.Runtime.Contracts.StreamData
Derives the CkArchiveColumnSpec set a rollup archive must materialise to back its CkRollupAggregationSpec entries. Pure function, DB-neutral. The output is the same list a raw archive would carry in ArchiveSnapshot.Columns, so the existing DDL / query / insert paths can consume a rollup snapshot without branching on rollup-ness. Rollup-archives concept §4.
public static class RollupColumnGenerator
Inheritance Object → RollupColumnGenerator
Remarks:
CkRollupFunction.Avg materialises as two columns
({base}_sum + {base}_count) so chained rollups stay numerically correct — the
average is recomputed on read as sum / NULLIF(count, 0).
CkRollupFunction.TimeWeightedAvg follows the same pattern with
{base}_integral + {base}_duration (AB#4336); its default base name uses the short
token twavg, not the lower-cased enum name. The other functions map 1:1.
All generated columns are Indexed = true and Required = false: aggregations can
be null for empty buckets and the orchestrator's upsert is the only writer, so a missing
value never indicates user error.
Methods
Generate(IReadOnlyList<CkRollupAggregationSpec>)
Generates the column list for a rollup archive from its aggregation specs. The path field
of each emitted CkArchiveColumnSpec is the storage column name (already
resolved via the lower-cased {sourcePath}{function} / explicit
CkRollupAggregationSpec.TargetColumnName rule).
public static IReadOnlyList<CkArchiveColumnSpec> Generate(IReadOnlyList<CkRollupAggregationSpec> aggregations)
Parameters
aggregations IReadOnlyList<CkRollupAggregationSpec>
Returns
IReadOnlyList<CkArchiveColumnSpec>
Exceptions
ArgumentException
Thrown when two aggregations would produce the same target column name.
TargetColumnNamesFor(CkRollupAggregationSpec)
Returns the target column name(s) produced by one aggregation spec, in stable order. Single
name for MIN/MAX/SUM/COUNT, two names for AVG ({base}_sum, {base}_count).
Exposed so callers that need the same naming convention without instantiating
CkArchiveColumnSpec values (e.g. the DDL generator) can share the logic.
public static IEnumerable<string> TargetColumnNamesFor(CkRollupAggregationSpec spec)
Parameters
Returns
DefaultBaseNameFor(CkRollupAggregationSpec)
The column name this spec would generate if it did not pin one with
CkRollupAggregationSpec.TargetColumnName — {sanitised source path}_{function token}, the base that RollupColumnGenerator.TargetColumnNamesFor(CkRollupAggregationSpec) derives its one or two names
from.
public static string DefaultBaseNameFor(CkRollupAggregationSpec spec)
Parameters
Returns
Remarks:
This is the read-side identity of the aggregated quantity: it is determined by what the spec aggregates (path and function) and not by where it happens to store the result, so two specs with the same default base name aggregate the same thing. A pinned CkRollupAggregationSpec.TargetColumnName is a storage decision and is deliberately ignored here — the per-source resolver (AB#5157) uses this to recognise a physically-chained child rollup, and matching on the stored name instead would accept a child that aggregates a different attribute under a coincidental column name.
SanitisePath(String)
Lower-cases the path and strips dots so dotted attribute paths
(sensor.reading.value) collapse to a CrateDB-safe column name
(sensorreadingvalue). Kept here in Runtime.Contracts so the contract-level helper
and the CrateDB-side ColumnNameMapper.PathToColumnName stay in sync; the latter is
the canonical reference for the actual storage layer. Public because the engine's
per-source aggregation resolver (AB#5157) and the ladder chain walker compare logical
source paths through exactly this mapping; an already-sanitised name is returned unchanged.
public static string SanitisePath(string path)
Parameters
path String
A logical attribute path or an already-physical column name.
Returns
Exceptions
ArgumentNullException
path is null.