Repository navigation
feat(core): aggregation values and window statements read by type (SCHEMA-2b) - #454
Merged
Merged
Conversation
…HEMA-2b) Story SCHEMA-2b. Reviewed: r0:must-fix, r1:must-fix, r2:clean. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tions (SCHEMA-2b) GROUP BY key classes, aggregate types (UNION ALL, type conversion, SUM over no row), set-operation dates, window partitions, row projection, and the JDBC / Arrow column types, rewritten to what SCHEMA-2 and SCHEMA-2b measure. Story SCHEMA-2b. Reviewed: docs r0:must-fix, r1:must-fix, r2:must-fix (one clause, fixed as prescribed). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The no-matching-document paragraph still said SUM over no value is 0.0 on every column; it now follows the aggregate page: 0 over an integer column, 0.0 over a REAL or DOUBLE one. Story SCHEMA-2b. Reviewed: docs r3:clean. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fupelaqu
marked this pull request as ready for review
November 1, 2026 09:39
This was referenced Nov 3, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Slice 2 of 2 of the schema-aware result path in core (SCHEMA-2b, after #453). Every value core returns from an aggregation response (bucket keys, metrics,
top_hitsvalues, the global metrics beside hits) or from a window-enriched statement now has its declared column's class, read where it is first read. Both sides of a window's partition join read each partition column by one rule.Closes no issue: #418's remaining part (
_source: falsefor projections of computed columns only) and #421's JDBC and Arrow sides are later work.What changes
Aggregation readers (
AggregateReading, internal): one reader per bucket key, metric andtop_hitscolumn, built once per statement and carried with the statement's schema. A value a reader cannot read exactly stays as 0.24.0 read it (a fractional, NaN or out-of-range metric is kept, never truncated), and the empty-input rule runs first (ES 8's0.0over an empty group stays NULL).SUM width: SUM over a whole-number type is declared
BIGINT, SUM overREAL/DOUBLEDOUBLE, as DuckDB widens a sum. Every consumer of the declared type follows:describe, set-operation positions, arithmetic over a SUM, CTAS / materialized-view columns.Window statements: base rows are read by type, the rows of a statement without
*hold only the SELECT's columns, and one function per side builds the partition key. A whole-dayDATEkey is read exactly. Adatepartition column whose format core reads as stored text (a format with a zone name) is matched by its instant: the base request asks Elasticsearch for the column'sepoch_millisdoc value and pairs it with the bucket's millisecond key, selected or not; the displayed value stays the stored text.Docs: core pages that feat(core): declared ResultSchema and hit values read by type (SCHEMA-2) #453 and this PR had made stale now describe the measured behaviour: GROUP BY key classes, aggregate types (in a
UNION ALL, in type conversion, SUM over no row), set-operation dates, window partitions, row projection, and the JDBC / Arrow column types.Release notes
BOOLEANkeysBoolean(was the text"true"); date keysjava.timeatZ(were text or millis);BIGINTkeysLong,INTkeysInteger; MIN / MAX over integersInteger/Long(wasDouble); SUM over integersLong(wasDouble); COUNTLong(ES 8 answeredDouble);REALFloat;top_hitsvalues (FIRST_VALUE,LAST_VALUE,ARRAY_AGGelements) read by their column's type;AggregateApiboolean MIN / MAX answerBooleanValue. Values are unchanged.BIGINT:describeand set-operation positions report it; a new CTAS or materialized-view column built from it mapslong(existing indexes are untouched). AUNION ALLof such SUMs beyond 2^31 answered a wrappedIntegeron 0.24.0 (1705032704for 6,000,000,000); it answers theLong. Painless over a SUM moves a cast (((long) p.sum) + 1becomesp.sum + 1), with the same values.BOOLEAN,TIMESTAMPand whole-dayDATEpartitions are answered, and so is aBIGINTpartition holding epoch-millisecond-sized values (they answered NULL); a date partition read as stored text is matched by its instant and answered, selected or not, unless another window's partition column is not returned (NULL on 0.24.0); a window SUM over integers answers aLong; the rows of a window statement without*hold only the SELECT's columns.SELECT count(*)and reads the count only asInt/Long/String. On ES 8 that count was aDouble, read as 0, so the licence's cap on the number of materialized views was never reached there. It is now aLong: on ES 8, aCREATE MATERIALIZED VIEWbeyond the cap is refused, as it already was on ES 6.Acceptance evidence
describeequals the result's schema, no search issuedSchemaReadingSpecon ES 8.18.3SchemaReadingSpecon ES 8.18.3 and 6.8.23 (one-shot, async, scroll,_msearchlegs); canned pages per client form. Counted exclusions: FIRST / LAST on aggregation-only and GROUP BY rows (a map, as on 0.24.0), inexactDATEkeys, stats / percentile maps,ARRAY_AGG's column-level typeSchemaReadingSpecon ES 8.18.3 and 6.8.23SchemaReadingSpecon ES 8.18.3 and 6.8.23 over one-shot, async and scroll; the zone-name partition on ES 8 (6.8 cannot parse zone names)date_nanos, multi-valued partitions; SUM / MIN / MAX / COUNT, Painless over a SUM, empty groups, CTAS) on 0.24.0 and on the branch, ES 8.18.3, 322 lines: 90 differ, each a fix or a class change listed above; none refusedSELECT k, SUM(n) … GROUP BY kover anintegerfield, three values of 2,000,000,000, streamss: Int(64)=6000000000(Long). softclient4es-jdbc:getObjectLong6000000000 / 3,getLongthe same. softclient4es-extensions: a materialized view overSUM(f.n) AS t, SUM(f.n) + 1 AS sanswersLong6000000000 / 6000000001, columnsBIGINT,smappedlong. Each compiles with #453's consumer-shape edits onlyCost (warm JIT, setup split from the row loop, branch runs alternated with main runs on the same machine; medians of 5 pairs):
Three runs: a quiet one, then two at a machine load of 12 to 16. The window-row bound holds in the first and third runs; in the second (load 12) the branch was 1.13 to 1.24 × main on three of four warm pairs. The probe measures an internal overload that rebuilds the partition keys per row, which the real path builds once per statement, so its window figure is pessimistic.
Recorded, not fixed
Measured the same on 0.24.0 and on this branch:
PARTITION BYcolumn (CONCAT(pz, '') AS pz) is never computed: the column and the window values read NULL.nofSUM(n) OVER … AS s).*) makes every window of the statement read NULL, including another window whose partition would be answered alone, and nulls the window's operand column.OVER ()beside hits: the aliases read NULL and the values come back under internal keys (sum#s,value_count#c,max#m).date_nanospartition, a partition projected under another name, and a pattern or alias mixing date and keyword mappings for the column read NULL.SELECT *, <expr>rows carry a*key holding NULL (window and plain statements).HAVING SUM(n) > 3000000000fails in Painless ("Invalid int constant"); a scalar subquery value beyond the int range compared with anintegercolumn is refused by Elasticsearch.k IN (SELECT k … GROUP BY k)over a keyword holding"10:30"fails (read as a time),big IN (SELECT big … GROUP BY big)over a long is refused by Elasticsearch; inner statements keep 0.24.0's reading in this slice.CAST(SUM(n) AS INT)is refused at parse.Test plan
core/test(1,426 passed),sql/test(2,170 passed; one refusal text re-pinned fromINTtoBIGINTfor SUM, then 16 / 16),sbt "+ compile"(2.12 + 2.13)headerCheck scalafmtSbtCheck scalafmtCheck test:scalafmtCheck) on the committed bytes🤖 Generated with Claude Code