Skip to content
Merged
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
123 changes: 123 additions & 0 deletions internal/format/expressions.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,17 @@ func formatTableIdentifier(sb *strings.Builder, t *ast.TableIdentifier) {
// formatFunctionCall formats a function call.
func formatFunctionCall(sb *strings.Builder, fn *ast.FunctionCall) {
sb.WriteString(fn.Name)
// Handle parametric functions like quantile(0.9)(x)
if len(fn.Parameters) > 0 {
sb.WriteString("(")
for i, p := range fn.Parameters {
if i > 0 {
sb.WriteString(", ")
}
Expression(sb, p)
}
sb.WriteString(")")
}
sb.WriteString("(")
if fn.Distinct {
sb.WriteString("DISTINCT ")
Expand All @@ -170,8 +181,98 @@ func formatFunctionCall(sb *strings.Builder, fn *ast.FunctionCall) {
Expression(sb, arg)
}
sb.WriteString(")")
// Handle SETTINGS for table functions
if len(fn.Settings) > 0 {
sb.WriteString(" SETTINGS ")
for i, s := range fn.Settings {
if i > 0 {
sb.WriteString(", ")
}
sb.WriteString(s.Name)
sb.WriteString(" = ")
Expression(sb, s.Value)
}
}
// Handle window functions (OVER clause)
if fn.Over != nil {
sb.WriteString(" OVER ")
formatWindowSpec(sb, fn.Over)
}
// Handle alias
if fn.Alias != "" {
sb.WriteString(" AS ")
sb.WriteString(fn.Alias)
}
}

// formatWindowSpec formats a window specification.
func formatWindowSpec(sb *strings.Builder, w *ast.WindowSpec) {
if w.Name != "" {
sb.WriteString(w.Name)
return
}
sb.WriteString("(")
if len(w.PartitionBy) > 0 {
sb.WriteString("PARTITION BY ")
for i, expr := range w.PartitionBy {
if i > 0 {
sb.WriteString(", ")
}
Expression(sb, expr)
}
}
if len(w.OrderBy) > 0 {
if len(w.PartitionBy) > 0 {
sb.WriteString(" ")
}
sb.WriteString("ORDER BY ")
for i, elem := range w.OrderBy {
if i > 0 {
sb.WriteString(", ")
}
formatOrderByElement(sb, elem)
}
}
if w.Frame != nil {
sb.WriteString(" ")
formatWindowFrame(sb, w.Frame)
}
sb.WriteString(")")
}

// formatWindowFrame formats a window frame.
func formatWindowFrame(sb *strings.Builder, f *ast.WindowFrame) {
sb.WriteString(string(f.Type))
sb.WriteString(" ")
if f.EndBound != nil {
sb.WriteString("BETWEEN ")
formatFrameBound(sb, f.StartBound)
sb.WriteString(" AND ")
formatFrameBound(sb, f.EndBound)
} else {
formatFrameBound(sb, f.StartBound)
}
}

// formatFrameBound formats a frame bound.
func formatFrameBound(sb *strings.Builder, b *ast.FrameBound) {
switch b.Type {
case ast.BoundCurrentRow:
sb.WriteString("CURRENT ROW")
case ast.BoundUnboundedPre:
sb.WriteString("UNBOUNDED PRECEDING")
case ast.BoundUnboundedFol:
sb.WriteString("UNBOUNDED FOLLOWING")
case ast.BoundPreceding:
Expression(sb, b.Offset)
sb.WriteString(" PRECEDING")
case ast.BoundFollowing:
Expression(sb, b.Offset)
sb.WriteString(" FOLLOWING")
}
}


// formatBinaryExpr formats a binary expression.
func formatBinaryExpr(sb *strings.Builder, expr *ast.BinaryExpr) {
Expression(sb, expr.Left)
Expand All @@ -194,6 +295,28 @@ func formatAsterisk(sb *strings.Builder, a *ast.Asterisk) {
sb.WriteString(".")
}
sb.WriteString("*")
if len(a.Except) > 0 {
sb.WriteString(" EXCEPT (")
for i, col := range a.Except {
if i > 0 {
sb.WriteString(", ")
}
sb.WriteString(col)
}
sb.WriteString(")")
}
if len(a.Replace) > 0 {
sb.WriteString(" REPLACE (")
for i, r := range a.Replace {
if i > 0 {
sb.WriteString(", ")
}
Expression(sb, r.Expr)
sb.WriteString(" AS ")
sb.WriteString(r.Name)
}
sb.WriteString(")")
}
}

// formatAliasedExpr formats an aliased expression.
Expand Down
47 changes: 47 additions & 0 deletions internal/format/statements.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,13 @@ func formatSelectQuery(sb *strings.Builder, q *ast.SelectQuery) {
sb.WriteString("DISTINCT ")
}

// Format TOP clause
if q.Top != nil {
sb.WriteString("TOP ")
Expression(sb, q.Top)
sb.WriteString(" ")
}

// Format columns
for i, col := range q.Columns {
if i > 0 {
Expand Down Expand Up @@ -105,6 +112,25 @@ func formatSelectQuery(sb *strings.Builder, q *ast.SelectQuery) {
Expression(sb, q.Having)
}

// Format QUALIFY clause
if q.Qualify != nil {
sb.WriteString(" QUALIFY ")
Expression(sb, q.Qualify)
}

// Format WINDOW clause
if len(q.Window) > 0 {
sb.WriteString(" WINDOW ")
for i, w := range q.Window {
if i > 0 {
sb.WriteString(", ")
}
sb.WriteString(w.Name)
sb.WriteString(" AS ")
formatWindowSpec(sb, w.Spec)
}
}

// Format ORDER BY clause
if len(q.OrderBy) > 0 {
sb.WriteString(" ORDER BY ")
Expand All @@ -126,6 +152,17 @@ func formatSelectQuery(sb *strings.Builder, q *ast.SelectQuery) {
Expression(sb, q.Offset)
}

// Format LIMIT BY clause
if len(q.LimitBy) > 0 {
sb.WriteString(" BY ")
for i, expr := range q.LimitBy {
if i > 0 {
sb.WriteString(", ")
}
Expression(sb, expr)
}
}

// Format SETTINGS clause
if len(q.Settings) > 0 {
sb.WriteString(" SETTINGS ")
Expand All @@ -139,6 +176,16 @@ func formatSelectQuery(sb *strings.Builder, q *ast.SelectQuery) {
}
}

// Format INTO OUTFILE clause
if q.IntoOutfile != nil {
sb.WriteString(" INTO OUTFILE '")
sb.WriteString(q.IntoOutfile.Filename)
sb.WriteString("'")
if q.IntoOutfile.Truncate {
sb.WriteString(" TRUNCATE")
}
}

// Format FORMAT clause
if q.Format != nil {
sb.WriteString(" FORMAT ")
Expand Down
2 changes: 1 addition & 1 deletion parser/testdata/00004_top_counters/metadata.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
2 changes: 1 addition & 1 deletion parser/testdata/00007_uniq/metadata.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
2 changes: 1 addition & 1 deletion parser/testdata/00009_array_join_subquery/metadata.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
2 changes: 1 addition & 1 deletion parser/testdata/00010_big_array_join/metadata.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
2 changes: 1 addition & 1 deletion parser/testdata/00018_distinct_in_subquery/metadata.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
2 changes: 1 addition & 1 deletion parser/testdata/00027_simple_argMinArray/metadata.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
2 changes: 1 addition & 1 deletion parser/testdata/00037_totals_limit/metadata.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
2 changes: 1 addition & 1 deletion parser/testdata/00040_array_enumerate_uniq/metadata.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
2 changes: 1 addition & 1 deletion parser/testdata/00045_uniq_upto/metadata.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
2 changes: 1 addition & 1 deletion parser/testdata/00046_uniq_upto_distributed/metadata.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
2 changes: 1 addition & 1 deletion parser/testdata/00056_view/metadata.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
2 changes: 1 addition & 1 deletion parser/testdata/00064_negate_bug/metadata.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
2 changes: 1 addition & 1 deletion parser/testdata/00067_replicate_segfault/metadata.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
2 changes: 1 addition & 1 deletion parser/testdata/00084_external_aggregation/metadata.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
2 changes: 1 addition & 1 deletion parser/testdata/00086_array_reduce/metadata.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
2 changes: 1 addition & 1 deletion parser/testdata/00096_aggregation_min_if/metadata.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
2 changes: 1 addition & 1 deletion parser/testdata/00107_totals_after_having/metadata.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
2 changes: 1 addition & 1 deletion parser/testdata/00127_group_by_concat/metadata.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
2 changes: 1 addition & 1 deletion parser/testdata/00141_transform/metadata.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
2 changes: 1 addition & 1 deletion parser/testdata/00150_with_totals_and_join/metadata.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
2 changes: 1 addition & 1 deletion parser/testdata/00153_transform/metadata.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
2 changes: 1 addition & 1 deletion parser/testdata/00160_decode_xml_component/metadata.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
2 changes: 1 addition & 1 deletion parser/testdata/00167_settings_inside_query/metadata.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
2 changes: 1 addition & 1 deletion parser/testdata/00194_identity/metadata.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
2 changes: 1 addition & 1 deletion parser/testdata/00198_group_by_empty_arrays/metadata.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
2 changes: 1 addition & 1 deletion parser/testdata/00201_array_uniq/metadata.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
2 changes: 1 addition & 1 deletion parser/testdata/00208_agg_state_merge/metadata.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
2 changes: 1 addition & 1 deletion parser/testdata/00240_replace_substring_loop/metadata.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
2 changes: 1 addition & 1 deletion parser/testdata/00259_hashing_tuples/metadata.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
2 changes: 1 addition & 1 deletion parser/testdata/00271_agg_state_and_totals/metadata.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
2 changes: 1 addition & 1 deletion parser/testdata/00277_array_filter/metadata.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
2 changes: 1 addition & 1 deletion parser/testdata/00315_quantile_off_by_one/metadata.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
2 changes: 1 addition & 1 deletion parser/testdata/00323_quantiles_timing_bug/metadata.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
2 changes: 1 addition & 1 deletion parser/testdata/00347_has_tuple/metadata.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo_format":true}
{}
Loading