Commit 85ad3e5
feat: implement GROUPING SETS, ROLLUP, CUBE, and MERGE statement support (SQL-99 T431 + SQL:2003 F312) (#119)
* feat: implement GROUPING SETS, ROLLUP, CUBE support (SQL-99 T431)
Implement SQL-99 advanced grouping operations for aggregate queries:
## New Features
- ROLLUP(col1, col2, ...) - hierarchical subtotals (SQL-99 syntax)
- CUBE(col1, col2, ...) - all possible subtotal combinations (SQL-99 syntax)
- GROUPING SETS((a,b), (a), ()) - explicit grouping set specification
- GROUP BY cols WITH ROLLUP/CUBE - MySQL syntax support
## Implementation Details
### AST Nodes (ast.go)
- RollupExpression: stores column list for ROLLUP operation
- CubeExpression: stores column list for CUBE operation
- GroupingSetsExpression: stores list of grouping sets (including empty sets)
### Parser (parser.go)
- parseGroupingExpressionList(): shared helper for ROLLUP/CUBE parsing
- parseRollup(): parses ROLLUP(columns) with validation
- parseCube(): parses CUBE(columns) with validation
- parseGroupingSets(): parses GROUPING SETS with nested sets support
- Updated parseGroupByClause() to detect and route to correct parser
- Added MySQL syntax support: GROUP BY cols WITH ROLLUP/CUBE
### Tokenizer (tokenizer.go)
- Added ROLLUP, CUBE, GROUPING, SETS as keyword token types
- Added "GROUPING SETS" compound keyword support
### Keywords (keywords.go, categories.go)
- Registered keywords in ADDITIONAL_KEYWORDS
- Added to DMLKeywords and CompoundKeywords maps
## Validation
- Empty ROLLUP() returns error: "ROLLUP requires at least one expression"
- Empty CUBE() returns error: "CUBE requires at least one expression"
- Empty set in GROUPING SETS(()) is valid (SQL-99 compliant for grand total)
## Tests
- 7 formal test cases in parser_coverage_test.go
- Tests cover valid syntax, empty validation, and mixed operations
- All integration tests pass including MySQL WITH ROLLUP syntax
Closes #67 (Phase 1: GROUPING SETS, ROLLUP, CUBE)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* feat: implement MERGE statement support (SQL:2003 F312)
Add comprehensive MERGE statement parsing with full SQL:2003 compliance:
AST Nodes:
- MergeStatement: Target/source tables, ON condition, WHEN clauses
- MergeWhenClause: MATCHED, NOT MATCHED, NOT MATCHED BY SOURCE
- MergeAction: UPDATE (with SET clauses), INSERT (with VALUES), DELETE
- SetClause: Column assignment in UPDATE actions
Parser Features:
- MERGE INTO target USING source ON condition syntax
- Multiple WHEN clauses with AND conditions
- WHEN MATCHED THEN UPDATE SET / DELETE
- WHEN NOT MATCHED THEN INSERT (columns) VALUES (values)
- WHEN NOT MATCHED BY SOURCE THEN UPDATE/DELETE
- INSERT DEFAULT VALUES support
- Qualified column names in SET clauses (t.column = s.value)
- Case-insensitive keyword handling
Tokenizer Updates:
- Added DML keywords: INSERT, UPDATE, DELETE, INTO, VALUES, SET, DEFAULT
- Added MERGE keywords: MERGE, MATCHED, SOURCE, TARGET
- Updated PostgreSQL test expectations for new keyword types
Test Coverage:
- 12 comprehensive tests covering all MERGE scenarios
- Error case validation (INSERT in MATCHED, DELETE in NOT MATCHED)
- Benchmarks: 2.9M ops/sec (simple), 1.0M ops/sec (complex)
Performance validated with race detection - zero race conditions.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Ajit Pratap Singh <ajitpratapsingh@Ajits-Mac-mini.local>
Co-authored-by: Claude <noreply@anthropic.com>1 parent a50a055 commit 85ad3e5
8 files changed
Lines changed: 1429 additions & 18 deletions
File tree
- pkg/sql
- ast
- keywords
- parser
- tokenizer
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
230 | 230 | | |
231 | 231 | | |
232 | 232 | | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
233 | 276 | | |
234 | 277 | | |
235 | 278 | | |
| |||
845 | 888 | | |
846 | 889 | | |
847 | 890 | | |
| 891 | + | |
| 892 | + | |
| 893 | + | |
| 894 | + | |
| 895 | + | |
| 896 | + | |
| 897 | + | |
| 898 | + | |
| 899 | + | |
| 900 | + | |
| 901 | + | |
| 902 | + | |
| 903 | + | |
| 904 | + | |
| 905 | + | |
| 906 | + | |
| 907 | + | |
| 908 | + | |
| 909 | + | |
| 910 | + | |
| 911 | + | |
| 912 | + | |
| 913 | + | |
| 914 | + | |
| 915 | + | |
| 916 | + | |
| 917 | + | |
| 918 | + | |
| 919 | + | |
| 920 | + | |
| 921 | + | |
| 922 | + | |
| 923 | + | |
| 924 | + | |
| 925 | + | |
| 926 | + | |
| 927 | + | |
| 928 | + | |
| 929 | + | |
| 930 | + | |
| 931 | + | |
| 932 | + | |
| 933 | + | |
| 934 | + | |
| 935 | + | |
| 936 | + | |
| 937 | + | |
| 938 | + | |
| 939 | + | |
| 940 | + | |
| 941 | + | |
| 942 | + | |
| 943 | + | |
| 944 | + | |
| 945 | + | |
| 946 | + | |
| 947 | + | |
| 948 | + | |
| 949 | + | |
| 950 | + | |
| 951 | + | |
| 952 | + | |
| 953 | + | |
| 954 | + | |
| 955 | + | |
| 956 | + | |
| 957 | + | |
| 958 | + | |
| 959 | + | |
| 960 | + | |
| 961 | + | |
| 962 | + | |
| 963 | + | |
| 964 | + | |
| 965 | + | |
| 966 | + | |
| 967 | + | |
| 968 | + | |
| 969 | + | |
| 970 | + | |
| 971 | + | |
| 972 | + | |
| 973 | + | |
| 974 | + | |
| 975 | + | |
| 976 | + | |
| 977 | + | |
| 978 | + | |
848 | 979 | | |
849 | 980 | | |
850 | 981 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
50 | 50 | | |
51 | 51 | | |
52 | 52 | | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
53 | 57 | | |
54 | 58 | | |
55 | 59 | | |
56 | 60 | | |
57 | | - | |
58 | | - | |
59 | | - | |
60 | | - | |
61 | | - | |
62 | | - | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
63 | 68 | | |
64 | 69 | | |
65 | 70 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
110 | 110 | | |
111 | 111 | | |
112 | 112 | | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
113 | 124 | | |
114 | 125 | | |
115 | 126 | | |
| |||
130 | 141 | | |
131 | 142 | | |
132 | 143 | | |
| 144 | + | |
133 | 145 | | |
134 | 146 | | |
135 | 147 | | |
| |||
0 commit comments