Skip to content

Commit 47bf571

Browse files
authored
Fix 25 parser errors: multiple syntax improvements (#16)
1 parent 1a2bffb commit 47bf571

67 files changed

Lines changed: 871 additions & 235 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

TODO.md

Lines changed: 74 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,49 @@
22

33
## Current State
44

5-
- **Tests passing:** 6,006 (88.0%)
6-
- **Tests skipped:** 819 (12.0%)
7-
8-
## Recently Fixed (explain layer)
5+
- **Tests passing:** ~6,066 (88.9%)
6+
- **Tests skipped:** ~758 (11.1%)
7+
- **Parser errors:** 7 remaining
8+
9+
## Recently Fixed (Latest Session)
10+
11+
### Lexer Improvements
12+
- ✅ Dollar-quoted strings (`$$...$$`)
13+
- ✅ Hex P notation floats (`0x123p4`, `-0x1P1023`)
14+
- ✅ Backtick escaping (`` `ta``ble` ``)
15+
- ✅ BOM (byte order mark) character handling
16+
- ✅ Dollar signs in identifiers (`$alias$name$`)
17+
18+
### Parser Improvements
19+
- ✅ SYSTEM DROP FORMAT SCHEMA CACHE
20+
- ✅ EXPLAIN AST options (`EXPLAIN AST optimize=0 SELECT ...`)
21+
- ✅ WITH scalar expression without alias (`WITH 1 SELECT 1`)
22+
- ✅ DROP USER with @ hostname (`test_user@localhost`, `test_user@'192.168.23.15'`)
23+
- ✅ KEY keyword as implicit alias (`view(select 'foo.com' key)`)
24+
- ✅ Complex UNION with parentheses (`((SELECT 1) UNION ALL SELECT 2)`)
25+
26+
## Previously Fixed (parser layer)
27+
28+
- ✅ SELECT ALL syntax (`SELECT ALL 'a'`)
29+
- ✅ FILTER clause on aggregate functions (`argMax() FILTER(WHERE ...)`)
30+
- ✅ DROP SETTINGS PROFILE (`DROP SETTINGS PROFILE IF EXISTS ...`)
31+
- ✅ CREATE NAMED COLLECTION (`CREATE NAMED COLLECTION ... AS ...`)
32+
- ✅ WITH column AS alias syntax (`WITH number AS k SELECT k`)
33+
- ✅ SHOW TABLES NOT LIKE (`SHOW TABLES NOT LIKE '%'`)
34+
- ✅ SHOW CREATE QUOTA (`SHOW CREATE QUOTA default`)
35+
- ✅ LIMIT BY with second LIMIT (`LIMIT 1 BY * LIMIT 1`)
36+
- ✅ WITH TOTALS HAVING clause (`SELECT count() WITH TOTALS HAVING x != 0`)
37+
- ✅ COLLATE in column definitions (`varchar(255) COLLATE binary NOT NULL`)
38+
- ✅ SETTINGS with keyword assignments (`SETTINGS limit=5`)
39+
- ✅ TTL GROUP BY SET clause (`TTL d + interval 1 second GROUP BY x SET y = max(y)`)
40+
- ✅ DROP ROW POLICY ON wildcard (`DROP ROW POLICY ... ON default.*`)
41+
- ✅ INSERT FROM INFILE COMPRESSION (`FROM INFILE '...' COMPRESSION 'gz'`)
42+
- ✅ FROM before SELECT syntax (`FROM numbers(1) SELECT number`)
43+
- ✅ Parenthesized SELECT at statement level (`(SELECT 1)`)
44+
- ✅ EXISTS table syntax (`EXISTS db.table`)
45+
- ✅ DROP TABLE FORMAT (`DROP TABLE IF EXISTS t FORMAT Null`)
46+
47+
## Previously Fixed (explain layer)
948

1049
- ✅ TableJoin output - removed join type keywords
1150
- ✅ Table function aliases (e.g., `remote('127.1') AS t1`)
@@ -23,135 +62,78 @@
2362
- ✅ Empty tuple in ORDER BY (e.g., `ORDER BY ()``Function tuple` with empty `ExpressionList`)
2463
- ✅ String escape handling (lexer now unescapes `\'`, `\\`, `\n`, `\t`, `\0`, etc.)
2564

26-
## Parser Issues (High Priority)
65+
## Remaining Parser Issues (7 total)
66+
67+
### Multi-line SQL (Test Framework Limitation)
68+
These are valid SQL split across multiple lines. Our test framework only reads the first line:
69+
- Incomplete CASE expressions (`SELECT CASE number`, `SELECT CASE`, `SELECT "number", CASE "number"`)
70+
71+
### QUALIFY Clause with ^ Operator
72+
Window function filtering with caret operator:
73+
```sql
74+
SELECT '{}'::JSON x QUALIFY x.^c0 = 1;
75+
```
76+
77+
### Parenthesized ALTER
78+
Multiple ALTER operations in parentheses:
79+
```sql
80+
ALTER TABLE t22 (DELETE WHERE ...), (MODIFY SETTING ...), (UPDATE ... WHERE ...);
81+
```
82+
83+
### INSERT with JSON Data
84+
JSON data after FORMAT clause:
85+
```sql
86+
INSERT INTO FUNCTION null() SELECT * FROM input('x Int') ... FORMAT JSONEachRow {"x": 1};
87+
```
88+
89+
### EXCEPT in Nested Expressions
90+
`* EXCEPT` within nested function calls:
91+
```sql
92+
SELECT untuple((expr, * EXCEPT b));
93+
```
2794

28-
These require changes to `parser/parser.go`:
95+
## Parser Issues (High Priority)
2996

3097
### CREATE TABLE with INDEX Clause
31-
INDEX definitions in CREATE TABLE are not captured:
3298
```sql
3399
CREATE TABLE t (x Array(String), INDEX idx1 x TYPE bloom_filter(0.025)) ENGINE=MergeTree;
34100
```
35101

36102
### SETTINGS Inside Function Arguments
37-
SETTINGS clause within function calls is not parsed:
38103
```sql
39104
SELECT * FROM icebergS3(s3_conn, filename='test', SETTINGS key='value');
40-
-- The SETTINGS should become a Set child of the function
41105
```
42106

43107
### CREATE TABLE with Column TTL
44-
TTL expressions on columns are not captured:
45108
```sql
46109
CREATE TABLE t (c Int TTL expr()) ENGINE=MergeTree;
47-
-- Expected: ColumnDeclaration with 2 children (type + TTL function)
48110
```
49111

50112
## Parser Issues (Medium Priority)
51113

52114
### CREATE DICTIONARY
53-
Dictionary definitions are not supported:
54115
```sql
55116
CREATE DICTIONARY d0 (c1 UInt64) PRIMARY KEY c1 LAYOUT(FLAT()) SOURCE(...);
56117
```
57118

58-
### CREATE USER / CREATE FUNCTION
59-
User and function definitions are not supported:
60-
```sql
61-
CREATE USER test_user GRANTEES ...;
62-
CREATE OR REPLACE FUNCTION myFunc AS ...;
63-
```
64-
65119
### QUALIFY Clause
66-
Window function filtering clause:
67120
```sql
68121
SELECT x QUALIFY row_number() OVER () = 1;
69122
```
70123

71-
### INTO OUTFILE with TRUNCATE
72-
Extended INTO OUTFILE syntax:
73-
```sql
74-
SELECT 1, 2 INTO OUTFILE '/dev/null' TRUNCATE FORMAT Npy;
75-
```
76-
77124
### GROUPING SETS
78-
Advanced grouping syntax:
79125
```sql
80126
SELECT ... GROUP BY GROUPING SETS ((a), (b));
81127
```
82128

83-
### view() Table Function
84-
The view() table function in FROM:
85-
```sql
86-
SELECT * FROM view(SELECT 1 as id);
87-
```
88-
89129
### CREATE TABLE ... AS SELECT
90-
CREATE TABLE with inline SELECT:
91130
```sql
92131
CREATE TABLE src ENGINE=Memory AS SELECT 1;
93132
```
94133

95-
### Variant() Type with PRIMARY KEY
96-
Complex column definitions:
97-
```sql
98-
CREATE TABLE t (c Variant() PRIMARY KEY) ENGINE=Redis(...);
99-
```
100-
101-
## Parser Issues (Lower Priority)
102-
103-
### INTERVAL with Dynamic Type
104-
INTERVAL with type cast:
105-
```sql
106-
SELECT INTERVAL 1 MINUTE AS c0, INTERVAL c0::Dynamic DAY;
107-
```
108-
109-
### ALTER TABLE with Multiple Operations
110-
Multiple ALTER operations in parentheses:
111-
```sql
112-
ALTER TABLE t (DELETE WHERE ...), (MODIFY SETTING ...), (UPDATE ... WHERE ...);
113-
```
114-
115-
### Tuple Type in Column with Subfield Access
116-
Tuple type with engine using subfield:
117-
```sql
118-
CREATE TABLE t (t Tuple(a Int32)) ENGINE=EmbeddedRocksDB() PRIMARY KEY (t.a);
119-
```
120-
121-
### insert() Function with input()
122-
INSERT using input() function:
123-
```sql
124-
INSERT INTO FUNCTION null() SELECT * FROM input('x Int') ...;
125-
```
126-
127-
## Explain Issues (Remaining)
128-
129-
### Scientific Notation for Floats
130-
Very small/large floats should use scientific notation:
131-
```sql
132-
SELECT 2.2250738585072014e-308;
133-
-- Expected: Float64_2.2250738585072014e-308
134-
-- Got: Float64_0.0000...22250738585072014
135-
```
136-
137-
### Array Literals with Negative Numbers
138-
Arrays with negative integers may still expand to Function instead of Literal in some cases:
139-
```sql
140-
SELECT [-10000, 5750];
141-
-- Some cases now work correctly with Literal Int64_-10000
142-
-- Complex nested arrays may still require additional work
143-
```
144-
145-
### WithElement for CTE Subqueries
146-
Some CTE subqueries should use WithElement wrapper:
147-
```sql
148-
WITH sub AS (SELECT ...) SELECT ...;
149-
-- Expected: WithElement (children 1) > Subquery > SelectWithUnionQuery
150-
```
151-
152134
## Testing Notes
153135

154-
Run tests with timeout to catch infinite loops:
136+
Run tests with timeout:
155137
```bash
156138
go test ./parser -timeout 5s -v
157139
```
@@ -161,11 +143,6 @@ Count test results:
161143
go test ./parser -v 2>&1 | grep -E 'PASS:|SKIP:' | wc -l
162144
```
163145

164-
View explain mismatches:
165-
```bash
166-
go test ./parser -v 2>&1 | grep -A 30 "TODO: Explain output mismatch" | head -100
167-
```
168-
169146
View parser failures:
170147
```bash
171148
go test ./parser -v 2>&1 | grep "TODO: Parser does not yet support" | head -20

ast/ast.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,8 +403,20 @@ type AlterCommand struct {
403403
FromTable string `json:"from_table,omitempty"`
404404
TTL *TTLClause `json:"ttl,omitempty"`
405405
Settings []*SettingExpr `json:"settings,omitempty"`
406+
Where Expression `json:"where,omitempty"` // For DELETE WHERE
407+
Assignments []*Assignment `json:"assignments,omitempty"` // For UPDATE
406408
}
407409

410+
// Assignment represents a column assignment in UPDATE.
411+
type Assignment struct {
412+
Position token.Position `json:"-"`
413+
Column string `json:"column"`
414+
Value Expression `json:"value"`
415+
}
416+
417+
func (a *Assignment) Pos() token.Position { return a.Position }
418+
func (a *Assignment) End() token.Position { return a.Position }
419+
408420
func (a *AlterCommand) Pos() token.Position { return a.Position }
409421
func (a *AlterCommand) End() token.Position { return a.Position }
410422

@@ -432,6 +444,8 @@ const (
432444
AlterReplacePartition AlterCommandType = "REPLACE_PARTITION"
433445
AlterFreezePartition AlterCommandType = "FREEZE_PARTITION"
434446
AlterFreeze AlterCommandType = "FREEZE"
447+
AlterDeleteWhere AlterCommandType = "DELETE_WHERE"
448+
AlterUpdate AlterCommandType = "UPDATE"
435449
)
436450

437451
// TruncateQuery represents a TRUNCATE statement.
@@ -594,6 +608,17 @@ func (e *ExchangeQuery) Pos() token.Position { return e.Position }
594608
func (e *ExchangeQuery) End() token.Position { return e.Position }
595609
func (e *ExchangeQuery) statementNode() {}
596610

611+
// ExistsQuery represents an EXISTS table_name statement (check if table exists).
612+
type ExistsQuery struct {
613+
Position token.Position `json:"-"`
614+
Database string `json:"database,omitempty"`
615+
Table string `json:"table"`
616+
}
617+
618+
func (e *ExistsQuery) Pos() token.Position { return e.Position }
619+
func (e *ExistsQuery) End() token.Position { return e.Position }
620+
func (e *ExistsQuery) statementNode() {}
621+
597622
// -----------------------------------------------------------------------------
598623
// Expressions
599624

0 commit comments

Comments
 (0)