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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
The diff you're trying to view is too large. We only load the first 3000 changed files.
21 changes: 20 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@ go run ./cmd/next-test

This tool finds all tests with `todo: true` in their metadata and returns the one with the shortest `query.sql` file.

To find the next format roundtrip test to work on, run:

```bash
go run ./cmd/next-test -format
```

This finds tests with `todo_format: true` in their metadata.

## Workflow

1. Run `go run ./cmd/next-test` to find the next test to implement
Expand Down Expand Up @@ -42,6 +50,16 @@ go test ./parser/... -check-skipped -v 2>&1 | grep "PASSES NOW"

Tests that output `PASSES NOW` can have their `todo` flag removed from `metadata.json`. This helps identify when parser improvements fix multiple tests at once.

## Checking for Newly Passing Format Tests

After implementing format changes, run:

```bash
go test ./parser/... -check-format -v 2>&1 | grep "FORMAT PASSES NOW"
```

Tests that output `FORMAT PASSES NOW` can have their `todo_format` flag removed from `metadata.json`.

## Test Structure

Each test in `parser/testdata/` contains:
Expand All @@ -52,7 +70,8 @@ Each test in `parser/testdata/` contains:

### Metadata Options

- `todo: true` - Test is pending implementation
- `todo: true` - Test is pending parser/explain implementation
- `todo_format: true` - Format roundtrip test is pending implementation
- `skip: true` - Skip test entirely (e.g., causes infinite loop)
- `explain: false` - Skip test (e.g., ClickHouse couldn't parse it)
- `parse_error: true` - Query is intentionally invalid SQL
Expand Down
29 changes: 23 additions & 6 deletions cmd/next-test/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,18 @@ package main

import (
"encoding/json"
"flag"
"fmt"
"os"
"path/filepath"
"sort"
)

var formatFlag = flag.Bool("format", false, "Find tests with todo_format instead of todo")

type testMetadata struct {
Todo bool `json:"todo,omitempty"`
TodoFormat bool `json:"todo_format,omitempty"`
Explain *bool `json:"explain,omitempty"`
Skip bool `json:"skip,omitempty"`
ParseError bool `json:"parse_error,omitempty"`
Expand All @@ -21,6 +25,8 @@ type todoTest struct {
}

func main() {
flag.Parse()

testdataDir := "parser/testdata"
entries, err := os.ReadDir(testdataDir)
if err != nil {
Expand Down Expand Up @@ -49,9 +55,15 @@ func main() {
continue
}

// Only include tests marked as todo
if !metadata.Todo {
continue
// Check for todo or todo_format based on flag
if *formatFlag {
if !metadata.TodoFormat {
continue
}
} else {
if !metadata.Todo {
continue
}
}

// Skip tests with skip or explain=false or parse_error
Expand All @@ -72,8 +84,13 @@ func main() {
})
}

todoType := "todo"
if *formatFlag {
todoType = "todo_format"
}

if len(todoTests) == 0 {
fmt.Println("No todo tests found!")
fmt.Printf("No %s tests found!\n", todoType)
return
}

Expand All @@ -86,7 +103,7 @@ func main() {
next := todoTests[0]
testDir := filepath.Join(testdataDir, next.name)

fmt.Printf("Next test: %s\n\n", next.name)
fmt.Printf("Next %s test: %s\n\n", todoType, next.name)

// Print query.sql contents
queryPath := filepath.Join(testDir, "query.sql")
Expand All @@ -99,5 +116,5 @@ func main() {
fmt.Printf("\nExpected EXPLAIN output:\n%s\n", string(explainBytes))
}

fmt.Printf("\nRemaining todo tests: %d\n", len(todoTests))
fmt.Printf("\nRemaining %s tests: %d\n", todoType, len(todoTests))
}
6 changes: 6 additions & 0 deletions internal/format/statements.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import (

// formatSelectWithUnionQuery formats a SELECT with UNION query.
func formatSelectWithUnionQuery(sb *strings.Builder, q *ast.SelectWithUnionQuery) {
if q == nil {
return
}
for i, sel := range q.Selects {
if i > 0 {
sb.WriteString(" UNION ")
Expand All @@ -23,6 +26,9 @@ func formatSelectWithUnionQuery(sb *strings.Builder, q *ast.SelectWithUnionQuery

// formatSelectQuery formats a SELECT query.
func formatSelectQuery(sb *strings.Builder, q *ast.SelectQuery) {
if q == nil {
return
}
sb.WriteString("SELECT ")

if q.Distinct {
Expand Down
32 changes: 32 additions & 0 deletions parser/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,14 @@ import (
// Use with: go test ./parser -check-skipped -v
var checkSkipped = flag.Bool("check-skipped", false, "Run skipped todo tests to see which ones now pass")

// checkFormat runs skipped todo_format tests to see which ones now pass.
// Use with: go test ./parser -check-format -v
var checkFormat = flag.Bool("check-format", false, "Run skipped todo_format tests to see which ones now pass")

// testMetadata holds optional metadata for a test case
type testMetadata struct {
Todo bool `json:"todo,omitempty"`
TodoFormat bool `json:"todo_format,omitempty"` // true if format roundtrip test is pending
Source string `json:"source,omitempty"`
Explain *bool `json:"explain,omitempty"`
Skip bool `json:"skip,omitempty"`
Expand Down Expand Up @@ -170,6 +175,33 @@ func TestParser(t *testing.T) {
}
}

// Check Format output (roundtrip test)
// Skip if todo_format is true, unless -check-format flag is set
if !metadata.TodoFormat || *checkFormat {
formatted := parser.Format(stmts)
expected := strings.TrimSpace(query)
if formatted != expected {
if metadata.TodoFormat {
if *checkFormat {
t.Logf("FORMAT STILL FAILING:\nExpected:\n%s\n\nGot:\n%s", expected, formatted)
}
} else {
t.Errorf("Format output mismatch\nExpected:\n%s\n\nGot:\n%s", expected, formatted)
}
} else if metadata.TodoFormat && *checkFormat {
// Automatically remove the todo_format flag from metadata.json
metadata.TodoFormat = false
updatedBytes, err := json.Marshal(metadata)
if err != nil {
t.Errorf("Failed to marshal updated metadata: %v", err)
} else if err := os.WriteFile(metadataPath, append(updatedBytes, '\n'), 0644); err != nil {
t.Errorf("Failed to write updated metadata.json: %v", err)
} else {
t.Logf("FORMAT ENABLED - removed todo_format flag from: %s", entry.Name())
}
}
}

// If we get here with a todo test and -check-skipped is set, the test passes!
// Automatically remove the todo flag from metadata.json
if metadata.Todo && *checkSkipped {
Expand Down
2 changes: 1 addition & 1 deletion parser/testdata/00001_count_hits/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/00001_select_1/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/00002_count_visits/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/00002_system_numbers/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/00003_reinterpret_as_string/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/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/00005_filtering/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/00006_agregates/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/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/00008_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/00008_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/00009_uniq_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/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/00010_quantiles_segfault/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/00011_array_join_alias/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/00011_sorting/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/00012_array_join_alias_2/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/00012_sorting_distributed/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/00013_sorting_of_nested/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/00014_filtering_arrays/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}
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": true}
{"todo":true,"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/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}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{}
{"todo_format":true}
2 changes: 1 addition & 1 deletion parser/testdata/00020_sorting_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/00021_1_select_with_in/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/00021_2_select_with_in/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/00021_3_select_with_in/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/00021_sorting_arrays/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/00022_merge_prewhere/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/00023_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/00024_random_counters/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/00027_argMinMax/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/00027_distinct_and_order_by/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/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/00030_alter_table/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/00030_array_enumerate_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/00031_array_enumerate_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/00031_parser_number/metadata.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo": true}
{"todo":true,"todo_format":true}
2 changes: 1 addition & 1 deletion parser/testdata/00032_aggregate_key64/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/00032_fixed_string_to_string/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/00033_aggregate_key_string/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/00033_fixed_string_to_string/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/00034_fixed_string_to_number/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/00035_aggregate_keys128/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/00036_aggregate_hashed/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/00036_array_element/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/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/00037_uniq_state_merge1/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/00038_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/00038_uniq_state_merge2/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/00039_primary_key/metadata.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{}
{"todo_format":true}
Loading