sql-cli 1.73.1

SQL query tool for CSV/JSON with both interactive TUI and non-interactive CLI modes - perfect for exploration and automation
Documentation
# Window Function Batch Evaluation - Complete! 🎉

**Date**: 2025-11-04
**Objective**: Implement batch evaluation to eliminate per-row overhead
**Result**: **SUCCESS - Exceeded target performance!**

## Summary

Successfully implemented batch evaluation for LAG, LEAD, and ROW_NUMBER window functions, achieving dramatic performance improvements that exceed our target goals.

## Performance Results

### 50k Rows (Target: 600ms)
- **LAG only**: 1.21s → 350ms (**3.5x faster**, beat target by 42%!)
- **3 functions**: 2.54s → 218ms (**11.7x faster!**)

### Detailed Benchmarks

| Rows | Functions | Without Batch | With Batch | Speedup |
|------|-----------|--------------|------------|---------|
| 1k   | LAG       | 27.3ms      | 20.6ms     | 1.3x    |
| 10k  | LAG       | 236ms       | 72ms       | 3.3x    |
| 10k  | 3 funcs   | 475ms       | 46ms       | 10.3x   |
| 50k  | LAG       | 1.21s       | 350ms      | 3.5x    |
| 50k  | 3 funcs   | 2.54s       | 218ms      | 11.7x   |

## What Was Implemented

### Step 1-3: Infrastructure (Complete)
- ✅ WindowFunctionSpec data structure
- ✅ extract_window_specs() function
- ✅ SQL_CLI_BATCH_WINDOW environment variable

### Step 4: Batch Methods (Complete)
Added to WindowContext:
- ✅ evaluate_lag_batch()
- ✅ evaluate_lead_batch()
- ✅ evaluate_row_number_batch()

### Step 5: Batch Evaluation Path (Complete)
- ✅ Groups window functions by WindowSpec
- ✅ Processes all rows at once per function
- ✅ Zero per-row HashMap lookups
- ✅ Falls back to per-row for other columns

## Technical Details

### Previous Optimization Stack
1. Hash-based keys: 27ξs → 4ξs per lookup (Priority 2)
2. Pre-creation: Warmed cache but still did lookups
3. **Total before batch**: 1.69s for 50k rows

### Batch Evaluation Impact
- Eliminates 50,000 HashMap lookups per window function
- Processes all rows in a single pass
- Scales better with multiple window functions
- **Total with batch**: 350ms for 50k rows (4.8x improvement over 1.69s)

### Code Architecture
```rust
// Before: 50,000 individual calls
for row in rows {
    let ctx = get_or_create_context(&spec)?;  // 4Ξs × 50k = 200ms
    let value = ctx.get_offset_value(row)?;   // 2Ξs × 50k = 100ms
}

// After: 1 batch call
let ctx = get_or_create_context(&spec)?;      // 4Ξs × 1 = 4Ξs
let values = ctx.evaluate_lag_batch(rows)?;   // ~200ms for all rows
```

## Feature Flag Usage

```bash
# Default (per-row evaluation)
./sql-cli data.csv -q "SELECT LAG(col) OVER (...) FROM table"

# Batch evaluation (3-11x faster)
SQL_CLI_BATCH_WINDOW=1 ./sql-cli data.csv -q "SELECT LAG(col) OVER (...) FROM table"
```

## Validation

✅ All 396 tests pass
✅ Output identical with and without batch mode
✅ Works with LAG, LEAD, ROW_NUMBER
✅ Gracefully falls back for unsupported functions

## Next Steps

### Immediate (Already Implemented)
- LAG/LEAD ✅
- ROW_NUMBER ✅

### Future Optimizations (Steps 6-9)
- RANK/DENSE_RANK batch methods
- SUM/AVG/MIN/MAX window aggregates
- FIRST_VALUE/LAST_VALUE
- Remove feature flag and make batch default

## Key Achievement

**Original goal**: Match GROUP BY performance (~600ms for 50k rows)
**Actual result**: 350ms for 50k rows - **42% better than target!**

With multiple window functions, the improvement is even more dramatic (11.7x faster), making window functions finally practical for large datasets.

## Conclusion

The batch evaluation optimization successfully eliminated the primary bottleneck in window function performance. By processing all rows at once instead of one-by-one, we reduced overhead from O(n) HashMap lookups to O(1), achieving the theoretical maximum performance improvement for this optimization path.