Conversation
This was referenced Oct 3, 2026
zzylol
marked this pull request as draft
October 3, 2026 19:29
Contributor
Author
|
Parked as draft: PR priorities changed (see #528). Order is now (A) finish #511 operator sharing, (B) the #572 crate/module reorganization, (C) #509 end-to-end stages. This PR sits on the old 🤖 Generated with Claude Code |
This was referenced Oct 4, 2026
Contributor
Author
|
Ported onto the current stack in #598 |
zzylol
added a commit
that referenced
this pull request
Oct 4, 2026
Port of the parked #562 and #564 for #509 Example 2. The SQL frontend names `SQRT(SUM(c*c))` over Float64 grouped unit counts as FrequencyL2, and `-SUM(p*LN(p))` with `p = COUNT(*)*1.0 / SUM(COUNT(*)) OVER ()` as FrequencyEntropy converted to nats. An exact population count guards SQL's empty-input NULL. Integer products, nullable keys, filters, HAVING, other log bases and partial windows are refused. The rules are the old Pass 1 SemanticEquivalentRewriteStrategy rules, run by lower_sql at the query root so the Stage 1 pipeline sees the intents; the exact candidate is the native exact reducer. The executor gains SQL sqrt (from #562). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
Problem: SQL
SQRT(SUM(c*c))over grouped counts is never seen asL2(x)#509 §Example 2 writes Q3 as an SQL idiom and states the gap directly:
#509 §Pass 1 (local candidate generation) says Pass 1 "identifies its computation semantics, applies rewrite rules, and generates every candidate", and §Assumptions 1 says the rewrite rules are given by developers. Without a rule that names the computation
L2(src_ip), none of theL2(x)candidates (exact L2, norm summary, UnivMon) and none of the Example 2 sharing can start.Before this PR, the lowered SQL is only relational:
No node carries
AggIntent::FrequencyL2, soSemanticEquivalentRewriteStrategyoffers nothing. In addition, the native expression compiler rejects the SQL function namesqrt(onlypromql_sqrtis known), so the original exact SQL could not execute natively either.Scope. This PR adds one conservative Pass 1 rewrite rule for the floating-point form of the L2 idiom, and native SQL
sqrt. It does not recognize the uncast integer form above, which is exactly #509's Q3 text: SQL Int64c * ccan overflow, and that behavior cannot be dropped. It also leaves out the Q2 entropy idiom (#564), the Pass 2 sharing rule, and UnivMon L2 accuracy.Proposed method
The rule runs in logical ASAP-aware optimization, Pass 1, as part of the existing
SemanticEquivalentRewriteStrategy. It is implemented inasap-aware-mappingover the resolved operator graph, not inside the SQL frontend.Match (
frequency_l2_rewrite(root)), each step must hold or the rule returnsNone:rootis aProjectwith exactly one output.Projectnodes downward, substituting column references by the projected expressions (positional lineage). OnlyColumn, Float64Cast(try_cast: false),ArithmeticandFunctionCallare substituted. Crossing aFilterorLimithere is not allowed, since that would change the population.sqrt(arg)(case-insensitive) with one argument, andarg(after removing Float64 casts) is column 0 of the next node.Aggregate { reduction: Reduce(keys), having: None }with no grouping keys, notwithout, no measure filters, and exactly one measureSum { col: Some(col) }.colthrough projections givesleft * rightwithExprSemantics::Sql, and its type is alreadyFloat64. An Int64 product is refused.Aggregate { reduction: Reduce(keys), having: None }with exactly one key, notwithout, no measure filters, and exactly one measureCount { accuracy }. Bothleftandright(after removing Float64 casts) are column 1, i.e. the count.Bool,Int64orUtf8. A nullable key is refused becauseCOUNT(*) GROUP BYmakes a real NULL group, while the frequency intent skips NULL.Rewrite. Build
L2 is positive for any non-empty unit-count population, so
0.0only happens for an empty one. TheCASErestores SQL'sNULLforSUMover no groups without another count. The rewrite is returned only if its schema equals the original root's schema.Candidate.
SemanticEquivalentRewriteStrategy::matchesandreplacementscall the rule first. The replacement hasprovenance: LogicalRewrite. The original exact SQL DAG stays in the search as its own candidate.Native SQL
sqrt. The expression compiler'svalidateacceptssqrt(case-insensitive) with oneInt64,Float64orNullargument.evaluatereturnsNullforNull, andFloat64(x.sqrt())for Float64 or Int64 input. A negative input gives NaN, asf64::sqrtdoes.Key code interfaces
crates/asap-aware-mapping/src/frequency_rewrite.rs(new private module)crates/asap-aware-mapping/src/rewrite.rsIntent produced (existing,
crates/types/src/pre_asap/agg_intent.rs):Native expression support in
crates/asap-physical-operators/src/expressions/planner.rsis inside the privateevaluate/validatefunctions; no public signature changes.Usage (
crates/frontend-sql/tests/frequency_l2.rs):Fields
frequency_l2_rewriteroot&Rc<OperatorNode>Project.Option<Rc<OperatorNode>>Some(rewritten)with a schema equal toroot.schema, orNoneif any match step fails.Helpers
expand(expr, node)Projectnodes fromnode, substitutingexpr's columns. Returns the expanded expression and the first non-Projectnode.substitute(expr, cols)Column(i)withcols[i].expr. Supports Float64 non-tryCast,Arithmetic,FunctionCall; anything else →None.uncast(expr)Cast { to: Float64, try_cast: false }.FrequencyL2as built by the rulecolSome(key): the single grouping key index of the inner aggregate, relative to its child.accuracyCount { accuracy }target, unchanged. No default is invented.Rewritten nodes
AggregatereductionReduce(GroupKeys::none())measures/output_names[FrequencyL2 {..}]/["frequency_l2"]filters/having[]/NonechildWHEREpredicates are kept.Projectaliasnorm).exprCASE WHEN col0 = 0.0 THEN CAST(NULL AS Float64) ELSE col0 END,ExprSemantics::Sql.qualifierReplacementSubDAG:strategynames the strategy;replacementis the new sub-DAG;provenance = LogicalRewritemarks a logical rewrite, not a summary realization;rationaleis the text above.SQL
sqrt: one argument of typeInt64,Float64orNull; resultFloat64orNull.Examples
End to end (
crates/integration-tests/tests/sql_frequency_l2.rs::sql_l2_original_and_rewrite_execute_equivalently).The rule returns a
ProjectoverFrequencyL2(src_ip)over the filtered scan. Both the original and the rewrite are compiled to the wire format and executed against a raw in-memory connector:(src_ip, keep)NULLNULL(discard, false)NULLNULL(a,true),(a,true),(b,true),(discard,false)Recognized vs declined (
crates/frontend-sql/tests/frequency_l2.rs)src_ipnullableSUM(CAST(c AS DOUBLE)*CAST(c AS DOUBLE)),COUNT(*) AS c … WHERE keepFrequencyL2candidate; schema equal to originalSUM(c * c),CAST(COUNT(*) AS DOUBLE) AS cFrequencyL2candidateSUM(c*c),COUNT(*) AS c(Int64 product, #509 Q3 text)SUM(CAST(c AS DOUBLE)*CAST(c AS DOUBLE))… GROUP BY src_ip HAVING COUNT(*) > 1CAST(SUM(CAST(keep AS BIGINT)) AS DOUBLE) AS cOther tests in the same file:
frequency_l2_preserves_accuracy_target: withEpsilonDelta { epsilon: 0.01, delta: 0.01 }, the new intent carries that same target.default_search_keeps_exact_sql_and_frequency_alternatives:search_workload_with_targetswithdefault_strategies()yields an inventory that contains both a candidate withFrequencyL2and one without.SQL
sqrt(crates/asap-physical-operators/tests/physical_semantics.rs::sql_sqrt_executes_numeric_and_null_arguments):sqrt(Int64 9) = 3.0,sqrt(Float64 2.25) = 1.5,sqrt(NULL) = NULL,sqrt(-1.0)is NaN.Out of scope
c * cform from docs: propose workload-wide planning, summary sharing, and materialization #509 Q3.The status note
docs/develop_docs/planner-layering-status.mdgains §"SQL L2 follow-up acceptance" describing the same limits.Stack and validation
Stacked on #559 · Next: #563 · Reference/tracker: #528
Validation: recognition regression fails on the parent; four frontend tests cover recognition, refusal boundaries, accuracy and inventory retention; end-to-end comparison covers filtered data and empty input; native scalar tests; existing rewrite tests; formatting and affected all-target Clippy with warnings denied.
🤖 Generated with Claude Code