Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 9 additions & 11 deletions internal/explain/expressions.go
Original file line number Diff line number Diff line change
Expand Up @@ -418,22 +418,20 @@ func explainAliasedExpr(sb *strings.Builder, n *ast.AliasedExpr, depth int) {
}
case *ast.UnaryExpr:
// Handle negated numeric literals - output as Literal instead of Function negate
// For integers, only do this in subquery context (ClickHouse behavior)
// For aliased expressions, ClickHouse always shows negated integers as Literal Int64_-N
// 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:
// 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, escapeAlias(n.Alias))
return
case uint64:
fmt.Fprintf(sb, "%sLiteral Int64_-%d (alias %s)\n", indent, val, escapeAlias(n.Alias))
return
}
// Always convert to literal for aliased expressions
switch val := lit.Value.(type) {
case int64:
fmt.Fprintf(sb, "%sLiteral Int64_%d (alias %s)\n", indent, -val, escapeAlias(n.Alias))
return
case uint64:
fmt.Fprintf(sb, "%sLiteral Int64_-%d (alias %s)\n", indent, val, escapeAlias(n.Alias))
return
}
case ast.LiteralFloat:
// Always convert negated floats to literals (especially for -inf, -nan)
Expand Down
42 changes: 42 additions & 0 deletions internal/explain/tables.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,53 @@ func formatSampleRatio(sb *strings.Builder, expr ast.Expression) {
formatSampleRatioOperand(sb, binExpr.Left)
sb.WriteString(" / ")
formatSampleRatioOperand(sb, binExpr.Right)
} else if lit, ok := expr.(*ast.Literal); ok && lit.Type == ast.LiteralFloat {
// Convert float to fraction if it's a simple ratio
if v, ok := lit.Value.(float64); ok {
num, den := floatToFraction(v)
if den > 1 {
fmt.Fprintf(sb, "%d / %d", num, den)
return
}
}
formatSampleRatioOperand(sb, expr)
} else {
formatSampleRatioOperand(sb, expr)
}
}

// floatToFraction converts a float to a simple fraction (numerator, denominator).
// Returns (num, 1) if no simple fraction representation is found.
func floatToFraction(f float64) (int64, int64) {
// Handle common sample ratios
// Try denominators from 2 to 1000
for den := int64(2); den <= 1000; den++ {
num := int64(f * float64(den))
// Check if this gives us back the original value (within floating point tolerance)
if float64(num)/float64(den) == f {
// Find GCD to simplify the fraction
g := gcd(num, den)
return num / g, den / g
}
}
// No simple fraction found, return as integer if possible
if f == float64(int64(f)) {
return int64(f), 1
}
return 0, 1
}

// gcd calculates the greatest common divisor of two integers
func gcd(a, b int64) int64 {
if a < 0 {
a = -a
}
for b != 0 {
a, b = b, a%b
}
return a
}

func formatSampleRatioOperand(sb *strings.Builder, expr ast.Expression) {
if lit, ok := expr.(*ast.Literal); ok {
switch v := lit.Value.(type) {
Expand Down
2 changes: 1 addition & 1 deletion parser/testdata/00056_view/metadata.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"explain_todo":{"stmt6":true}}
{}
4 changes: 1 addition & 3 deletions parser/testdata/00276_sample/metadata.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
{
"explain_todo": {
"stmt13": true,
"stmt14": true,
"stmt15": true,
"stmt16": true,
Expand All @@ -15,7 +14,6 @@
"stmt32": true,
"stmt33": true,
"stmt34": true,
"stmt39": true,
"stmt9": true
"stmt39": true
}
}
7 changes: 6 additions & 1 deletion parser/testdata/00578_merge_table_sampling/metadata.json
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
{"explain_todo":{"stmt10":true,"stmt5":true,"stmt8":true,"stmt9":true}}
{
"explain_todo": {
"stmt8": true,
"stmt9": true
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,9 @@
{
"explain_todo": {
"stmt11": true,
"stmt12": true,
"stmt13": true,
"stmt16": true,
"stmt17": true,
"stmt18": true,
"stmt19": true,
"stmt22": true,
"stmt25": true,
"stmt6": true,
"stmt7": true,
"stmt8": true
"stmt7": true
}
}