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
  •  
  •  
  •  
49 changes: 13 additions & 36 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,67 +2,44 @@

## Next Steps

To continue implementing parser support for skipped tests, consult:
To find the next test to work on, run:

```
skipped_tests_by_size.txt
```bash
go run ./cmd/next-test
```

This file lists all skipped tests ordered by query file size (smallest first). Smaller tests are generally simpler to implement.
This tool finds all tests with `todo: true` in their metadata and returns the one with the shortest `query.sql` file.

## Workflow

1. Pick tests from `skipped_tests_by_size.txt` starting from the top
1. Run `go run ./cmd/next-test` to find the next test to implement
2. Check the test's `query.sql` to understand what SQL needs parsing
3. Check the test's `ast.json` to understand the expected output format
4. Implement the necessary AST types in `ast/`
5. Add parser logic in `parser/parser.go`
6. Add JSON marshaling functions in `parser/parser.go`
7. Enable the test by setting `{"skip": false}` in its `metadata.json`
7. Enable the test by removing `todo: true` from its `metadata.json` (set it to `{}`)
8. Run `go test ./parser/...` to verify
9. **Check if other skipped tests now pass** (see below)
10. **Update `skipped_tests_by_size.txt`** after enabling tests
9. **Check if other todo tests now pass** (see below)

## Checking for Newly Passing Skipped Tests
## Checking for Newly Passing Todo Tests

After implementing parser changes, run:

```bash
go test ./parser/... -only-skipped -v 2>&1 | grep "PASS:"
go test ./parser/... -only-todo -v 2>&1 | grep "PASS:"
```

This shows any skipped tests that now pass. Enable those tests by setting `{"skip": false}` in their `metadata.json`.
This shows any todo tests that now pass. Enable those tests by removing `todo: true` from their `metadata.json`.

Available test flags:
- `-only-skipped` - Run only skipped tests (find newly passing tests)
- `-run-skipped` - Run skipped tests along with normal tests

## Updating skipped_tests_by_size.txt

After enabling tests, regenerate the file. The script only includes tests that:
- Have `"skip": true` in metadata.json
- Do NOT have `"invalid_syntax"` in metadata.json (these can't be implemented)
- Have an `ast.json` file (tests without it are unparseable)

```bash
cd parser/testdata
ls -d */ | while read dir; do
dir="${dir%/}"
if [ -f "$dir/metadata.json" ] && [ -f "$dir/ast.json" ] && [ -f "$dir/query.sql" ]; then
if grep -q '"skip": true' "$dir/metadata.json" 2>/dev/null; then
if grep -qv '"invalid_syntax"' "$dir/metadata.json" 2>/dev/null; then
size=$(wc -c < "$dir/query.sql")
echo "$size $dir"
fi
fi
fi
done | sort -n > ../../skipped_tests_by_size.txt
```
- `-only-todo` - Run only todo/invalid_syntax tests (find newly passing tests)
- `-run-todo` - Run todo/invalid_syntax tests along with normal tests

## Test Structure

Each test in `parser/testdata/` contains:
- `metadata.json` - `{"skip": true}` or `{"skip": false}`
- `metadata.json` - `{}` for enabled tests, `{"todo": true}` for pending tests, or `{"invalid_syntax": true}` for tests with invalid SQL
- `query.sql` - T-SQL to parse
- `ast.json` - Expected AST output

Expand Down
75 changes: 75 additions & 0 deletions cmd/next-test/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package main

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

type testMetadata struct {
Todo bool `json:"todo"`
}

type testInfo struct {
Name string
QueryLen int64
}

func main() {
testdataDir := "parser/testdata"
entries, err := os.ReadDir(testdataDir)
if err != nil {
fmt.Fprintf(os.Stderr, "Error reading testdata directory: %v\n", err)
os.Exit(1)
}

var todoTests []testInfo

for _, entry := range entries {
if !entry.IsDir() {
continue
}

testDir := filepath.Join(testdataDir, entry.Name())
metadataPath := filepath.Join(testDir, "metadata.json")

metadataData, err := os.ReadFile(metadataPath)
if err != nil {
continue
}

var metadata testMetadata
if err := json.Unmarshal(metadataData, &metadata); err != nil {
continue
}

if !metadata.Todo {
continue
}

queryPath := filepath.Join(testDir, "query.sql")
info, err := os.Stat(queryPath)
if err != nil {
continue
}

todoTests = append(todoTests, testInfo{
Name: entry.Name(),
QueryLen: info.Size(),
})
}

if len(todoTests) == 0 {
fmt.Println("No todo tests found!")
return
}

sort.Slice(todoTests, func(i, j int) bool {
return todoTests[i].QueryLen < todoTests[j].QueryLen
})

next := todoTests[0]
fmt.Printf("%s (%d bytes)\n", next.Name, next.QueryLen)
}
25 changes: 14 additions & 11 deletions parser/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,15 @@ import (
)

type testMetadata struct {
Skip bool `json:"skip"`
Todo bool `json:"todo"`
InvalidSyntax bool `json:"invalid_syntax"`
}

// Test flags for running skipped tests
// Usage: go test ./parser/... -run-skipped # run all tests including skipped
// Usage: go test ./parser/... -only-skipped # run only skipped tests (find newly passing tests)
var runSkippedTests = flag.Bool("run-skipped", false, "run skipped tests along with normal tests")
var onlySkippedTests = flag.Bool("only-skipped", false, "run only skipped tests (useful to find tests that now pass)")
// Test flags for running todo/invalid_syntax tests
// Usage: go test ./parser/... -run-todo # run all tests including todo tests
// Usage: go test ./parser/... -only-todo # run only todo tests (find newly passing tests)
var runTodoTests = flag.Bool("run-todo", false, "run todo tests along with normal tests")
var onlyTodoTests = flag.Bool("only-todo", false, "run only todo tests (useful to find tests that now pass)")

func TestParse(t *testing.T) {
entries, err := os.ReadDir("testdata")
Expand All @@ -35,7 +36,7 @@ func TestParse(t *testing.T) {
t.Run(testName, func(t *testing.T) {
testDir := filepath.Join("testdata", testName)

// Check metadata.json for skip flag
// Check metadata.json for todo/invalid_syntax flags
metadataPath := filepath.Join(testDir, "metadata.json")
metadataData, err := os.ReadFile(metadataPath)
if err != nil {
Expand All @@ -47,11 +48,13 @@ func TestParse(t *testing.T) {
t.Fatalf("failed to parse metadata.json: %v", err)
}

if metadata.Skip && !*runSkippedTests && !*onlySkippedTests {
t.Skip("skipped via metadata.json")
// Skip tests marked with todo or invalid_syntax unless running with -run-todo or -only-todo
shouldSkip := metadata.Todo || metadata.InvalidSyntax
if shouldSkip && !*runTodoTests && !*onlyTodoTests {
t.Skip("skipped via metadata.json (todo or invalid_syntax)")
}
if !metadata.Skip && *onlySkippedTests {
t.Skip("not a skipped test")
if !shouldSkip && *onlyTodoTests {
t.Skip("not a todo/invalid_syntax test")
}

// Read the test SQL file
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"skip": false}
{}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"skip": true}
{"todo": true}
6 changes: 1 addition & 5 deletions parser/testdata/AiGenerateChunksTests170/metadata.json
Original file line number Diff line number Diff line change
@@ -1,5 +1 @@
{
"skip": true,
"invalid_syntax": true,
"parser_error": "Line 2, Column 33: Incorrect syntax near '='.;Line 5, Column 33: Incorrect syntax near '='.;Line 8, Column 33: Incorrect syntax near '='.;Line 11, Column 33: Incorrect syntax near '='.;Line 14, Column 33: Incorrect syntax near '='.;Line 17, Column 33: Incorrect syntax near '='.;Line 20, Column 33: Incorrect syntax near '='.;Line 23, Column 48: Incorrect syntax near '='.;Line 26, Column 48: Incorrect syntax near '='.;Line 29, Column 48: Incorrect syntax near '='.;Line 32, Column 33: Incorrect syntax near '='.;Line 35, Column 33: Incorrect syntax near '='.;Line 38, Column 33: Incorrect syntax near '='.;Line 56, Column 48: Incorrect syntax near '='.;Line 63, Column 37: Incorrect syntax near '='.;"
}
{"invalid_syntax": true, "parser_error": "Line 2, Column 33: Incorrect syntax near '='.;Line 5, Column 33: Incorrect syntax near '='.;Line 8, Column 33: Incorrect syntax near '='.;Line 11, Column 33: Incorrect syntax near '='.;Line 14, Column 33: Incorrect syntax near '='.;Line 17, Column 33: Incorrect syntax near '='.;Line 20, Column 33: Incorrect syntax near '='.;Line 23, Column 48: Incorrect syntax near '='.;Line 26, Column 48: Incorrect syntax near '='.;Line 29, Column 48: Incorrect syntax near '='.;Line 32, Column 33: Incorrect syntax near '='.;Line 35, Column 33: Incorrect syntax near '='.;Line 38, Column 33: Incorrect syntax near '='.;Line 56, Column 48: Incorrect syntax near '='.;Line 63, Column 37: Incorrect syntax near '='.;"}
6 changes: 1 addition & 5 deletions parser/testdata/AiGenerateEmbeddingsTests170/metadata.json
Original file line number Diff line number Diff line change
@@ -1,5 +1 @@
{
"skip": true,
"invalid_syntax": true,
"parser_error": "Line 1, Column 55: Incorrect syntax near 'USE'.;Line 2, Column 56: Incorrect syntax near 'USE'.;Line 3, Column 55: Incorrect syntax near 'USE'.;Line 4, Column 55: Incorrect syntax near 'USE'.;Line 5, Column 55: Incorrect syntax near 'USE'.;Line 6, Column 55: Incorrect syntax near 'USE'.;Line 7, Column 34: Incorrect syntax near 'USE'.;Line 35, Column 52: Incorrect syntax near 'USE'.;Line 40, Column 45: Incorrect syntax near 'USE'.;Line 45, Column 88: Incorrect syntax near 'USE'.;Line 53, Column 71: Incorrect syntax near 'USE'.;"
}
{"invalid_syntax": true, "parser_error": "Line 1, Column 55: Incorrect syntax near 'USE'.;Line 2, Column 56: Incorrect syntax near 'USE'.;Line 3, Column 55: Incorrect syntax near 'USE'.;Line 4, Column 55: Incorrect syntax near 'USE'.;Line 5, Column 55: Incorrect syntax near 'USE'.;Line 6, Column 55: Incorrect syntax near 'USE'.;Line 7, Column 34: Incorrect syntax near 'USE'.;Line 35, Column 52: Incorrect syntax near 'USE'.;Line 40, Column 45: Incorrect syntax near 'USE'.;Line 45, Column 88: Incorrect syntax near 'USE'.;Line 53, Column 71: Incorrect syntax near 'USE'.;"}
2 changes: 1 addition & 1 deletion parser/testdata/AlterAssemblyStatementTests/metadata.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"skip": true}
{"todo": true}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"skip": true}
{"todo": true}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"skip": false}
{}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"skip": false}
{}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"skip": true}
{"todo": true}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"skip": true}
{"todo": true}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"skip": true}
{"todo": true}
Original file line number Diff line number Diff line change
@@ -1,5 +1 @@
{
"skip": true,
"invalid_syntax": true,
"parser_error": "Line 1, Column 18: Incorrect syntax near 'error'.;"
}
{"invalid_syntax": true, "parser_error": "Line 1, Column 18: Incorrect syntax near 'error'.;"}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"skip": true}
{"todo": true}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"skip": true}
{"todo": true}
Original file line number Diff line number Diff line change
@@ -1,5 +1 @@
{
"skip": true,
"invalid_syntax": true,
"parser_error": "Line 2, Column 52: Incorrect syntax near 'MANUAL_CUTOVER'.;Line 5, Column 42: Incorrect syntax near 'MANUAL_CUTOVER'.;Line 8, Column 70: Incorrect syntax near 'MANUAL_CUTOVER'.;Line 10, Column 19: Incorrect syntax near 'PERFORM_CUTOVER'.;"
}
{"invalid_syntax": true, "parser_error": "Line 2, Column 52: Incorrect syntax near 'MANUAL_CUTOVER'.;Line 5, Column 42: Incorrect syntax near 'MANUAL_CUTOVER'.;Line 8, Column 70: Incorrect syntax near 'MANUAL_CUTOVER'.;Line 10, Column 19: Incorrect syntax near 'PERFORM_CUTOVER'.;"}
2 changes: 1 addition & 1 deletion parser/testdata/AlterDatabaseOptionsTests/metadata.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"skip": true}
{"todo": true}
2 changes: 1 addition & 1 deletion parser/testdata/AlterDatabaseOptionsTests100/metadata.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"skip": true}
{"todo": true}
2 changes: 1 addition & 1 deletion parser/testdata/AlterDatabaseOptionsTests120/metadata.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"skip": false}
{}
2 changes: 1 addition & 1 deletion parser/testdata/AlterDatabaseOptionsTests130/metadata.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"skip": true}
{"todo": true}
2 changes: 1 addition & 1 deletion parser/testdata/AlterDatabaseOptionsTests140/metadata.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"skip": true}
{"todo": true}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"skip": false}
{}
2 changes: 1 addition & 1 deletion parser/testdata/AlterDatabaseOptionsTests90/metadata.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"skip": true}
{"todo": true}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"skip": false}
{}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"skip": false}
{}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"skip": true}
{"todo": true}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"skip": false}
{}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"skip": true}
{"todo": true}
2 changes: 1 addition & 1 deletion parser/testdata/AlterDatabaseStatementTests/metadata.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"skip": true}
{"todo": true}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"skip": false}
{}
2 changes: 1 addition & 1 deletion parser/testdata/AlterEndpointStatementTests/metadata.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"skip": true}
{"todo": true}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"skip": true}
{"todo": true}
2 changes: 1 addition & 1 deletion parser/testdata/AlterExternalLanguage150/metadata.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"skip": true}
{"todo": true}
2 changes: 1 addition & 1 deletion parser/testdata/AlterExternalLibrary140/metadata.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"skip": true}
{"todo": true}
2 changes: 1 addition & 1 deletion parser/testdata/AlterExternalLibrary150/metadata.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"skip": true}
{"todo": true}
Original file line number Diff line number Diff line change
@@ -1,5 +1 @@
{
"skip": true,
"invalid_syntax": true,
"parser_error": "Line 1, Column 16: Incorrect syntax near 'MODEL'.;Line 9, Column 16: Incorrect syntax near 'MODEL'.;Line 13, Column 16: Incorrect syntax near 'MODEL'.;Line 17, Column 16: Incorrect syntax near 'MODEL'.;Line 23, Column 16: Incorrect syntax near 'MODEL'.;"
}
{"invalid_syntax": true, "parser_error": "Line 1, Column 16: Incorrect syntax near 'MODEL'.;Line 9, Column 16: Incorrect syntax near 'MODEL'.;Line 13, Column 16: Incorrect syntax near 'MODEL'.;Line 17, Column 16: Incorrect syntax near 'MODEL'.;Line 23, Column 16: Incorrect syntax near 'MODEL'.;"}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"skip": true}
{"todo": true}
Loading
Loading