sql-cli 1.71.0

SQL query tool for CSV/JSON with both interactive TUI and non-interactive CLI modes - perfect for exploration and automation
Documentation
# String Methods Registry Refactoring

## Current State
- String methods are hardcoded in WHERE parser (Contains, StartsWith, EndsWith, ToUpper, ToLower, etc.)
- Each method creates a specific WhereExpr variant
- Evaluator has specific code for each variant

## New Architecture
We've created a registry-based system for string methods that allows:
1. Dynamic registration of new methods
2. Unified evaluation through SqlFunction trait
3. Both function-style and method-style calling

## Implementation Status

### ✅ Completed
1. Created `MethodFunction` trait extending `SqlFunction`
2. Implemented all string methods as registry functions
3. Added method registry to `FunctionRegistry`
4. Methods can be called as functions: `TOUPPER(name)`

### 🔄 In Progress  
Need to connect WHERE parser to use the registry

### 📋 TODO
1. Modify WHERE parser to check registry first
2. Create generic WhereExpr::MethodCall variant
3. Update evaluator to use registry for method evaluation
4. Gradual migration from hardcoded to registry-based

## Migration Strategy

### Phase 1: Parallel Implementation (Current)
- Keep existing hardcoded methods working
- Add registry-based methods alongside
- Both work independently

### Phase 2: Registry Integration
```rust
// In WHERE parser
if let Some(method_func) = registry.get_method(&method_name) {
    // Use registry-based method
    return Ok(WhereExpr::MethodCall {
        column,
        method: method_name,
        args: parsed_args,
    });
} else {
    // Fall back to hardcoded methods
    match method.as_str() {
        "Contains" => { /* existing code */ }
        // ...
    }
}
```

### Phase 3: Evaluator Update
```rust
// In recursive_where_evaluator
WhereExpr::MethodCall { column, method, args } => {
    let method_func = registry.get_method(method)?;
    let column_value = get_column_value(column);
    let result = method_func.evaluate_method(column_value, args)?;
    // Convert result to boolean for WHERE
}
```

### Phase 4: Deprecate Hardcoded
- Remove hardcoded method variants from WhereExpr
- All methods go through registry
- Clean, extensible architecture

## Benefits

1. **Extensibility**: Add new methods without touching parser
2. **Consistency**: Same methods work in SELECT and WHERE
3. **Testing**: Test methods independently
4. **Documentation**: Auto-generated from function signatures
5. **Type Safety**: Compile-time checking via traits

## Example Usage

After full implementation:
```sql
-- Method style (WHERE clause)
SELECT * FROM users WHERE name.Contains('john')
SELECT * FROM users WHERE email.EndsWith('.com')
SELECT * FROM users WHERE status.ToUpper() = 'ACTIVE'

-- Function style (SELECT clause)  
SELECT TOUPPER(name), LENGTH(email) FROM users
SELECT CONTAINS(description, 'important') as has_keyword FROM tasks

-- Both styles work everywhere
SELECT * FROM users WHERE CONTAINS(email, '@gmail')
SELECT name.ToUpper() as uppercase_name FROM users
```

## New Methods to Add

With the registry system, we can easily add:
- `Trim()`, `TrimStart()`, `TrimEnd()`
- `Replace(old, new)`
- `Substring(start, length)`
- `IndexOf(substring)`
- `PadLeft(length, char)`, `PadRight(length, char)`
- `Reverse()`
- `Split(delimiter)` - returns array
- Regular expression methods

## Implementation Notes

### Registry Access
The main challenge is getting the registry to the WHERE parser and evaluator.
Options:
1. Pass registry as parameter (requires API changes)
2. Global/static registry (less flexible)
3. Store in parent context that creates parser

### Type Conversion
Methods return DataValue, but WHERE needs boolean results.
Need conversion rules:
- Boolean values: use directly
- Numeric: 0 is false, non-zero is true
- String: empty is false, non-empty is true
- Null: always false

### Case Sensitivity
The registry handles case-insensitive method lookup via `handles_method()`.
This maintains compatibility with existing case-insensitive mode.