diff --git a/CLAUDE.md b/CLAUDE.md index e9a5f38981..800f1d3877 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -12,13 +12,13 @@ This finds tests with `explain_todo` entries in their metadata. ## Running Tests -Always run parser tests with a 10 second timeout: +Always run parser tests with a 30 second timeout: ```bash -go test ./parser/... -timeout 10s +go test ./parser/... -timeout 30s ``` -The tests are very fast. If a test is timing out, it indicates a bug (likely an infinite loop in the parser). +The tests are fast but some test files have many statements. If a test is timing out, it may indicate a bug (likely an infinite loop in the parser). ## Checking for Newly Passing Explain Tests diff --git a/internal/explain/expressions.go b/internal/explain/expressions.go index 41f7595477..4816c581a2 100644 --- a/internal/explain/expressions.go +++ b/internal/explain/expressions.go @@ -412,21 +412,26 @@ func explainAliasedExpr(sb *strings.Builder, n *ast.AliasedExpr, depth int) { Node(sb, e.Right, depth+2) } case *ast.UnaryExpr: - // When inside a Subquery context, negated numeric literals should be output as Literal Int64_-N - // Otherwise, output as Function negate - if inSubqueryContext && e.Op == "-" { + // Handle negated numeric literals - output as Literal instead of Function negate + // For integers, only do this in subquery context (ClickHouse behavior) + // For floats (especially inf/nan), always do this + if e.Op == "-" { if lit, ok := e.Operand.(*ast.Literal); ok { switch lit.Type { case ast.LiteralInteger: - switch val := lit.Value.(type) { - case int64: - fmt.Fprintf(sb, "%sLiteral Int64_%d (alias %s)\n", indent, -val, n.Alias) - return - case uint64: - fmt.Fprintf(sb, "%sLiteral Int64_-%d (alias %s)\n", indent, val, n.Alias) - return + // Only convert to literal in subquery context + if inSubqueryContext { + switch val := lit.Value.(type) { + case int64: + fmt.Fprintf(sb, "%sLiteral Int64_%d (alias %s)\n", indent, -val, n.Alias) + return + case uint64: + fmt.Fprintf(sb, "%sLiteral Int64_-%d (alias %s)\n", indent, val, n.Alias) + return + } } case ast.LiteralFloat: + // Always convert negated floats to literals (especially for -inf, -nan) val := lit.Value.(float64) s := FormatFloat(-val) fmt.Fprintf(sb, "%sLiteral Float64_%s (alias %s)\n", indent, s, n.Alias)