sql-cli 1.66.0

SQL query tool for CSV/JSON with both interactive TUI and non-interactive CLI modes - perfect for exploration and automation
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
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
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
# SQL CLI Project - AI Context Guide

Vim-like terminal SQL editor with in-memory query engine for ultra-fast navigation and data exploration. Built in Rust using ratatui.

## 🚀 QUICK START - Essential Commands

```bash
# Run all tests (Rust + Python + Examples)
./run_all_tests.sh                                  # Complete test suite

# When in doubt about available functions:
./target/release/sql-cli --list-functions           # List all SQL functions
./target/release/sql-cli --function-help CONVERT    # Get help for specific function

# Test SQL queries quickly:
./target/release/sql-cli -q "SELECT CONVERT(100, 'km', 'miles')" -o csv
./target/release/sql-cli data/test.csv -q "SELECT * FROM test WHERE id > 5" -o csv

# Test examples:
uv run python tests/integration/test_examples.py    # Run all examples (formal + smoke tests)
uv run python tests/integration/test_examples.py physics_astronomy_showcase  # Run specific
uv run python tests/integration/test_examples.py --capture qualified_names   # Capture expectations
```

## 🏗️ CORE ARCHITECTURE - Key Files

### Entry Points & CLI
- `src/main.rs` - CLI entry point, argument parsing, mode selection (TUI vs non-interactive)
- `src/non_interactive.rs` - Handles `-q` queries, script execution, output formatting

### SQL Parsing & Execution Pipeline
1. **Parser**: `src/sql/recursive_parser.rs` - Recursive descent parser, builds AST
   - Parses SELECT, WHERE, GROUP BY, ORDER BY, functions, expressions
   - Returns `SelectStatement` AST structure

2. **Evaluator**: `src/data/arithmetic_evaluator.rs` - Evaluates expressions against data
   - Handles arithmetic, comparisons, function calls
   - **IMPORTANT**: Do NOT add function implementations here - use function registry

3. **Query Executor**: `src/data/query_executor.rs` - Orchestrates query execution
   - Applies WHERE filters, GROUP BY, ORDER BY, LIMIT

### Function System (CRITICAL)
- **Registry**: `src/sql/functions/mod.rs` - Central function registry
  - ALL new functions must be registered here
  - Categories: Mathematical, String, Date, Conversion, etc.
  
- **Adding New Functions**:
  1. Create implementation in `src/sql/functions/<category>.rs`
  2. Implement `SqlFunction` trait
  3. Register in `mod.rs` under appropriate category
  4. Function automatically available in CLI and help

- **Example Function Modules**:
  - `src/sql/functions/math.rs` - Mathematical functions
  - `src/sql/functions/string_methods.rs` - String manipulation
  - `src/sql/functions/convert.rs` - Unit conversions (CONVERT function)
  - `src/sql/functions/astronomy.rs` - Astronomical constants
  - `src/sql/functions/chemistry.rs` - Chemical elements

### Data Structures
- `src/data/datatable.rs` - Core data table structure (columns, rows, types)
- `src/data/data_view.rs` - View layer with sorting, filtering, column operations
- `src/data/csv_datasource.rs` - CSV loading and parsing
- `src/data/json_datasource.rs` - JSON data handling

### TUI Components (for interactive mode)
- `src/ui/enhanced_tui.rs` - Main TUI interface
- `src/app_state_container.rs` - Central state management
- `src/action.rs` - Action system for state updates
- `src/handlers/` - Event handlers for keyboard input

### Unit Conversion System
- `src/data/unit_converter.rs` - Core conversion logic
- `src/sql/functions/convert.rs` - CONVERT() SQL function
- Supports: temperature, distance, weight, volume, area, speed, pressure, time, energy

## 📝 DEVELOPMENT WORKFLOW

### Adding a New SQL Function

1. **Choose the right category** or create new one in `src/sql/functions/mod.rs`:
   ```rust
   pub enum FunctionCategory {
       Mathematical,
       String,
       Date,
       Conversion,  // etc.
   }
   ```

2. **Create function implementation**:
   ```rust
   // In src/sql/functions/your_category.rs
   pub struct YourFunction;
   
   impl SqlFunction for YourFunction {
       fn signature(&self) -> FunctionSignature {
           FunctionSignature {
               name: "YOUR_FUNC",
               category: FunctionCategory::YourCategory,
               arg_count: ArgCount::Fixed(2),
               description: "What it does",
               returns: "Return type",
               examples: vec!["SELECT YOUR_FUNC(arg1, arg2)"],
           }
       }
       
       fn evaluate(&self, args: &[DataValue]) -> Result<DataValue> {
           // Implementation
       }
   }
   ```

3. **Register in function registry** (`src/sql/functions/mod.rs`):
   ```rust
   fn register_your_category(&mut self) {
       self.register(Box::new(YourFunction));
   }
   ```

4. **Test it**:
   ```bash
   ./target/release/sql-cli -q "SELECT YOUR_FUNC(1, 2)" -o csv
   ./target/release/sql-cli --function-help YOUR_FUNC
   ```

### Parser Modifications
- **File**: `src/sql/recursive_parser.rs`
- **Key methods**:
  - `parse_select_list()` - SELECT clause items
  - `parse_where_clause()` - WHERE conditions
  - `parse_expression()` - Expressions and operators
  - `parse_function_call()` - Function parsing
- **ALWAYS add Python tests** after parser changes

### Testing Strategy

1. **Quick command-line testing**:
   ```bash
   # Test new feature
   ./target/release/sql-cli -q "YOUR_QUERY" -o csv

   # Debug parser
   ./target/release/sql-cli -q "YOUR_QUERY" --query-plan
   ```

2. **Run test suites**:
   ```bash
   cargo test                                        # Rust unit tests
   ./run_python_tests.sh                            # Python integration tests
   uv run python tests/integration/test_examples.py # Examples (formal + smoke)
   ./run_all_tests.sh                               # ALL THREE test suites
   ```

3. **Examples testing** (new Python-based framework):
   ```bash
   # Run all examples (2 formal with expectations, 117 smoke tests)
   uv run python tests/integration/test_examples.py

   # Run specific example
   uv run python tests/integration/test_examples.py qualified_names

   # Capture expected output for formal testing
   uv run python tests/integration/test_examples.py --capture physics_astronomy_showcase

   # Only fails if FORMAL tests fail (expectations not met)
   # SMOKE test failures are reported but non-blocking
   ```

4. **Always run before committing**:
   ```bash
   cargo fmt                    # Required formatting
   cargo clippy                 # Linting
   ./run_all_tests.sh          # All tests (Rust + Python + Examples)
   ```

## 🗂️ Project Structure

```
sql-cli/
├── src/
│   ├── main.rs                 # Entry point
│   ├── non_interactive.rs      # CLI query mode
│   ├── sql/
│   │   ├── recursive_parser.rs # SQL parser (builds AST)
│   │   ├── functions/          # Function implementations
│   │   │   ├── mod.rs         # Function registry
│   │   │   ├── math.rs        # Math functions
│   │   │   ├── string_methods.rs # String functions
│   │   │   └── convert.rs     # Unit conversions
│   │   └── script_parser.rs   # Script with GO separators
│   ├── data/
│   │   ├── datatable.rs       # Core data structure
│   │   ├── arithmetic_evaluator.rs # Expression evaluation
│   │   ├── query_executor.rs  # Query orchestration
│   │   └── unit_converter.rs  # Unit conversion logic
│   └── ui/                     # TUI components
├── examples/                   # SQL example files
│   └── expectations/          # Captured JSON output for formal tests
├── data/                       # Test data files
├── docs/                       # Technical documentation
├── tests/
│   ├── python_tests/          # Python integration tests
│   ├── integration/           # Integration test scripts
│   │   └── test_examples.py   # Examples test framework (formal + smoke)
│   └── sql_examples/          # Test SQL queries
├── scripts/
│   ├── test_all_examples.sh   # Legacy bash example runner (deprecated)
│   └── capture_expectation.sh # Helper to capture example expectations
└── nvim-plugin/               # Neovim plugin
```

## 📁 File Organization Guidelines

When creating new files, please follow these conventions:

### Keep in Root Directory:
- `README.md` - Main project documentation
- `CHANGELOG.md` - Version history
- `RELEASE_NOTES.md` - Release information  
- `CLAUDE.md` - This AI context guide
- `Cargo.toml`, `Cargo.lock` - Rust project files
- `.gitignore`, `.github/` - Git configuration

### Place in Appropriate Directories:
- **Test SQL files** (`test_*.sql`) → `tests/sql_examples/`
- **Test scripts** (`test_*.sh`, `test_*.lua`) → `tests/integration/`
- **Python tests**`tests/python_tests/`
- **Technical docs** (implementation details, TODOs) → `docs/`
- **Sample data**`data/`
- **SQL examples**`examples/`

### Naming Conventions:
- Test files should start with `test_`
- Data files should have descriptive names (e.g., `trade_reconciliation.csv`)
- Documentation should use UPPER_SNAKE_CASE for visibility (e.g., `MIGRATION_TODO.md`)

## 🎯 Key Principles

1. **Function Registry**: ALL functions go through the registry - no special cases in parser/evaluator
2. **Test Everything**: Add Python tests for SQL features, Rust tests for internals
3. **Use Non-Interactive Mode**: Test queries with `-q` flag before TUI testing
4. **Format Always**: Run `cargo fmt` before every commit
5. **Check Functions**: Use `--list-functions` when unsure about available functions
6. **CTE Pattern for Aggregate Expressions**: Window functions can't handle expressions directly. Use CTEs to pre-calculate expressions, then apply window functions to the resulting columns.

## 🔧 Common Tasks

### Finding Functions
```bash
# List all functions
./target/release/sql-cli --list-functions

# Search for specific function
./target/release/sql-cli --list-functions | grep -i convert

# Get function help
./target/release/sql-cli --function-help CONVERT
```

### Testing Queries
```bash
# Simple query
./target/release/sql-cli -q "SELECT 1+1" -o csv

# Query with data file
./target/release/sql-cli data/test.csv -q "SELECT * FROM test" -o csv

# Query with functions
./target/release/sql-cli -q "SELECT CONVERT(100, 'celsius', 'fahrenheit')" -o csv

# Show query plan (AST)
./target/release/sql-cli -q "SELECT * FROM test WHERE id > 5" --query-plan
```

### Running Tests
```bash
# All tests
./run_all_tests.sh

# Just Rust tests
cargo test

# Just Python tests
./run_python_tests.sh

# Test examples
./scripts/test_all_examples.sh

# Specific test
cargo test test_convert
python tests/python_tests/test_unit_conversions.py
```

## 📚 Test Data Files

- `data/test_simple_strings.csv` - String operations testing
- `data/test_simple_math.csv` - Math operations testing
- `data/sales_data.csv` - Window functions, aggregates
- `data/solar_system.csv` - Astronomical calculations
- `data/trades.json` - JSON data source testing

## ✍️ Writing SQL Examples

When creating SQL examples in `examples/*.sql`, follow these conventions:

### File Structure
Use `examples/accounting_format.sql` as a template:

1. **Data file hint at top** - Use shebang-style comment to specify data file:
   ```sql
   -- #! ../data/international_sales.csv
   ```
   This allows the CLI to find the data file relative to the SQL file.

2. **Statement termination** - EVERY SQL statement must end with:
   - Semicolon (`;`) - Marks end of SQL statement
   - `GO` on its own line - Tells the script parser to execute the batch

   ```sql
   SELECT * FROM table
   WHERE condition = true;
   GO
   ```

3. **Multiple statements** - Each statement needs its own `;` and `GO`:
   ```sql
   -- First query
   SELECT COUNT(*) FROM sales;
   GO

   -- Second query with CTE
   WITH summary AS (
       SELECT region, SUM(amount) as total
       FROM sales
       GROUP BY region
   )
   SELECT * FROM summary
   ORDER BY total DESC;
   GO
   ```

### Example Template
```sql
-- #! ../data/your_data.csv

-- Description of what this example demonstrates
SELECT
    column1,
    column2
FROM your_data
WHERE some_condition;
GO

-- Another example query
WITH cte_name AS (
    SELECT * FROM your_data
)
SELECT * FROM cte_name;
GO
```

### Testing Examples
Examples are automatically tested by:
```bash
./scripts/test_all_examples.sh
```

The script parser is basic - it chunks on `GO` statements, so proper formatting is essential.

## 🚨 Important Notes

- **ALWAYS run `cargo fmt` before committing** - Required for all commits
- **NULL handling**: Empty CSV fields are NULL, use IS NULL/IS NOT NULL
- **CONVERT function**: Use for all unit conversions, don't create individual functions
- **GO separator**: Supported in script files for batch execution
- **F5 in TUI**: Shows debug view with internal state

## 🔗 Quick Links

- Function Registry: `src/sql/functions/mod.rs`
- Parser: `src/sql/recursive_parser.rs`
- Expression Evaluator: `src/data/arithmetic_evaluator.rs`
- Query Executor: `src/data/query_executor.rs`
- Unit Converter: `src/data/unit_converter.rs`

## Agents (IMPORTANT: Always delegate to these specialized agents)

### rust-build-fixer
**ALWAYS delegate to this agent when:**
- Any `cargo build` or `cargo build --release` fails
- User reports compilation errors (e.g., "I'm getting an error...")
- After writing new Rust code (proactively check compilation)
- Formatting issues reported (cargo fmt failures)
- Type errors, borrow checker issues, or any Rust compilation problems

### rust-test-failure-investigator  
**ALWAYS delegate to this agent when:**
- `cargo test` reports ANY failures
- User mentions test failures (e.g., "tests are failing", "test broken")
- After implementing features that might affect tests
- CI pipeline test failures are reported
- Integration test failures occur

### debug-analyzer
**ALWAYS delegate to this agent when:**
- User provides F5 debug output
- Large debug dumps need analysis
- State inconsistency issues in TUI
- Performance bottlenecks need investigation

**CRITICAL**: Do NOT try to fix compilation errors or test failures yourself. ALWAYS delegate to the appropriate agent immediately.