Vim-like terminal SQL editor with in-memory query engine for ultra-fast navigation and data exploration. Built in Rust using ratatui.
# 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 expectationssrc/main.rs- CLI entry point, argument parsing, mode selection (TUI vs non-interactive)src/non_interactive.rs- Handles-qqueries, script execution, output formatting
-
Parser:
src/sql/recursive_parser.rs- Recursive descent parser, builds AST- Parses SELECT, WHERE, GROUP BY, ORDER BY, functions, expressions
- Returns
SelectStatementAST structure
-
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
-
Query Executor:
src/data/query_executor.rs- Orchestrates query execution- Applies WHERE filters, GROUP BY, ORDER BY, LIMIT
-
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:
- Create implementation in
src/sql/functions/<category>.rs - Implement
SqlFunctiontrait - Register in
mod.rsunder appropriate category - Function automatically available in CLI and help
- Create implementation in
-
Example Function Modules:
src/sql/functions/math.rs- Mathematical functionssrc/sql/functions/string_methods.rs- String manipulationsrc/sql/functions/convert.rs- Unit conversions (CONVERT function)src/sql/functions/astronomy.rs- Astronomical constantssrc/sql/functions/chemistry.rs- Chemical elements
src/data/datatable.rs- Core data table structure (columns, rows, types)src/data/data_view.rs- View layer with sorting, filtering, column operationssrc/data/csv_datasource.rs- CSV loading and parsingsrc/data/json_datasource.rs- JSON data handling
src/ui/enhanced_tui.rs- Main TUI interfacesrc/app_state_container.rs- Central state managementsrc/action.rs- Action system for state updatessrc/handlers/- Event handlers for keyboard input
src/data/unit_converter.rs- Core conversion logicsrc/sql/functions/convert.rs- CONVERT() SQL function- Supports: temperature, distance, weight, volume, area, speed, pressure, time, energy
-
Choose the right category or create new one in
src/sql/functions/mod.rs:pub enum FunctionCategory { Mathematical, String, Date, Conversion, // etc. }
-
Create function implementation:
// 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 } }
-
Register in function registry (
src/sql/functions/mod.rs):fn register_your_category(&mut self) { self.register(Box::new(YourFunction)); }
-
Test it:
./target/release/sql-cli -q "SELECT YOUR_FUNC(1, 2)" -o csv ./target/release/sql-cli --function-help YOUR_FUNC
- File:
src/sql/recursive_parser.rs - Key methods:
parse_select_list()- SELECT clause itemsparse_where_clause()- WHERE conditionsparse_expression()- Expressions and operatorsparse_function_call()- Function parsing
- ALWAYS add Python tests after parser changes
-
Quick command-line testing:
# Test new feature ./target/release/sql-cli -q "YOUR_QUERY" -o csv # Debug parser ./target/release/sql-cli -q "YOUR_QUERY" --query-plan
-
Run test suites:
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
-
Examples testing (new Python-based framework):
# 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
-
Always run before committing:
cargo fmt # Required formatting cargo clippy # Linting ./run_all_tests.sh # All tests (Rust + Python + Examples)
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
When creating new files, please follow these conventions:
README.md- Main project documentationCHANGELOG.md- Version historyRELEASE_NOTES.md- Release informationCLAUDE.md- This AI context guideCargo.toml,Cargo.lock- Rust project files.gitignore,.github/- Git configuration
- 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/
- 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)
- Function Registry: ALL functions go through the registry - no special cases in parser/evaluator
- Test Everything: Add Python tests for SQL features, Rust tests for internals
- Use Non-Interactive Mode: Test queries with
-qflag before TUI testing - Format Always: Run
cargo fmtbefore every commit - Check Functions: Use
--list-functionswhen unsure about available functions - 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.
- Window Function Performance: Window functions use batch evaluation by default for 86% better performance. Set
SQL_CLI_BATCH_WINDOW=0to opt-out if needed.
# 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# 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# 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.pydata/test_simple_strings.csv- String operations testingdata/test_simple_math.csv- Math operations testingdata/sales_data.csv- Window functions, aggregatesdata/solar_system.csv- Astronomical calculationsdata/trades.json- JSON data source testing
When creating SQL examples in examples/*.sql, follow these conventions:
Use examples/accounting_format.sql as a template:
-
Data file hint at top - Use shebang-style comment to specify data file:
-- #! ../data/international_sales.csvThis allows the CLI to find the data file relative to the SQL file.
-
Statement termination - EVERY SQL statement must end with:
- Semicolon (
;) - Marks end of SQL statement GOon its own line - Tells the script parser to execute the batch
SELECT * FROM table WHERE condition = true; GO
- Semicolon (
-
Multiple statements - Each statement needs its own
;andGO:-- 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
-- #! ../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;
GOExamples are automatically tested by:
./scripts/test_all_examples.shThe script parser is basic - it chunks on GO statements, so proper formatting is essential.
- ALWAYS run
cargo fmtbefore 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
- 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
ALWAYS delegate to this agent when:
- Any
cargo buildorcargo build --releasefails - 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
ALWAYS delegate to this agent when:
cargo testreports 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
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.