sql-cli 1.67.1

SQL query tool for CSV/JSON with both interactive TUI and non-interactive CLI modes - perfect for exploration and automation
Documentation
# Rendering with DataView Instead of DataProvider

## Current Setup (DataProvider)
```rust
fn render_table_with_provider(&self, f: &mut Frame, area: Rect, provider: &dyn DataProvider) {
    let row_count = provider.get_row_count();
    let headers = provider.get_column_names();
    // Get rows as Vec<String>
    let row_data = provider.get_row(index);
}
```

## Better Setup (DataView)
```rust
fn render_table_with_dataview(&self, f: &mut Frame, area: Rect, dataview: &DataView) {
    let row_count = dataview.row_count();
    let headers = dataview.column_names();
    
    // Get typed row data
    if let Some(row) = dataview.get_row(index) {
        // Convert to strings for display
        let row_strings: Vec<String> = row.values.iter()
            .map(|v| v.to_string())
            .collect();
    }
}
```

## Why DataView is Better

### DataProvider (Limited)
- Only provides string data
- No awareness of filtering/sorting state
- No column visibility info beyond what BufferAdapter provides
- Just a "dumb" data accessor

### DataView (Complete)
- Provides typed data (can format better)
- Knows about active filters (can show filter indicator)
- Knows about column search (can highlight matches)
- Knows about sort state (can show sort arrows)
- Has column visibility built-in
- Can provide row indices for jump-to-row

## Migration Path

### Option 1: Replace DataProvider Usage
```rust
// Instead of getting a DataProvider
if let Some(provider) = self.get_data_provider() {
    self.render_table_with_provider(f, area, provider.as_ref());
}

// Get DataView directly
if let Some(dataview) = self.buffer().get_dataview() {
    self.render_table_with_dataview(f, area, dataview);
}
```

### Option 2: Make DataView implement DataProvider
```rust
impl DataProvider for DataView {
    fn get_row(&self, index: usize) -> Option<Vec<String>> {
        self.get_row(index).map(|row| {
            row.values.iter().map(|v| v.to_string()).collect()
        })
    }
    
    fn get_column_names(&self) -> Vec<String> {
        self.column_names()
    }
    
    fn get_row_count(&self) -> usize {
        self.row_count()
    }
    
    fn get_column_count(&self) -> usize {
        self.column_count()
    }
}
```

Then you can pass DataView where DataProvider is expected.

### Option 3: Remove DataProvider Completely
Since DataView has everything we need, we can:
1. Remove the DataProvider trait
2. Remove BufferAdapter 
3. Render directly from DataView

## Recommendation

**Short term:** Make DataView implement DataProvider (Option 2) to get everything compiling quickly.

**Long term:** Remove DataProvider completely (Option 3) and render directly from DataView. This gives you:
- Better type information for formatting
- Access to all view state for UI indicators
- Simpler architecture (one less abstraction layer)

## Benefits of Direct DataView Rendering

1. **Show filter status**: `if dataview.has_filter() { show_indicator() }`
2. **Show column search**: `if let Some(match) = dataview.get_current_column_match() { highlight(match) }`
3. **Show sort arrows**: Check sort state directly
4. **Better formatting**: Use DataValue types for proper number/date formatting
5. **Performance**: One less abstraction layer

## Example Implementation

```rust
fn render_table_from_dataview(&self, f: &mut Frame, area: Rect) {
    let Some(dataview) = self.buffer().get_dataview() else {
        // Render empty state
        return;
    };
    
    // Get view information
    let row_count = dataview.row_count();
    let headers = dataview.column_names();
    let has_filter = dataview.has_filter();
    let column_search = dataview.column_search_pattern();
    
    // Build header with indicators
    let mut header_cells = vec![];
    for (idx, name) in headers.iter().enumerate() {
        let mut cell_text = name.clone();
        
        // Add sort indicator
        if let Some(sort_info) = self.get_sort_info(idx) {
            cell_text.push_str(sort_info);
        }
        
        // Highlight if column search match
        if let Some(pattern) = column_search {
            if name.contains(pattern) {
                // Highlight this header
            }
        }
        
        header_cells.push(Cell::from(cell_text));
    }
    
    // Render with full context
    // ...
}
```