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
# Comment Preservation - Implementation Complete! 🎉

**Date**: 2025-10-20
**Status**: ✅ All 4 phases complete

## Summary

SQL comment preservation is now fully functional in both the CLI and Neovim plugin. When formatting SQL queries with `\sf` in Neovim or using `--format --preserve-comments` from the CLI, comments are preserved in the output.

## What Was Implemented

### Phase 1: Dual-Mode Lexer (Completed 2025-10-18)
- Added `LexerMode` enum (SkipComments, PreserveComments)
- Lexer tokenizes comments as `Token::LineComment` and `Token::BlockComment`
- Backward compatible - default mode skips comments

### Phase 2: Opt-In Parser Mode (Completed 2025-10-19)
- Added `ParserMode` enum (Standard, PreserveComments)
- `Parser::new()` defaults to Standard mode (backward compatible)
- `Parser::with_mode()` allows opting into comment preservation
- Comment collection guarded by mode checks
- 7 parser mode tests passing

### Phase 3: Formatter Integration (Completed 2025-10-20)
- Added `format_comment()` and `format_inline_comment()` methods to `AstFormatter`
- Leading comments emitted before SELECT keyword
- Trailing comments emitted at end of statement
- 6 new comment preservation tests passing
- All 457 tests passing (zero regressions)

### Phase 4: Neovim Plugin Integration (Completed 2025-10-20)
- Added `--preserve-comments` CLI flag
- Updated Neovim plugin to use new flag by default
- Removed manual comment preservation workaround
- `\sf` formatter now preserves comments automatically

## Usage

### CLI Usage

```bash
# Preserve comments when formatting
echo "-- Important query
SELECT id, name FROM users" | ./target/release/sql-cli --format --preserve-comments

# Output:
# -- Important query
# SELECT id, name
# FROM users

# Without --preserve-comments, comments are stripped (default)
echo "-- Comment
SELECT id FROM users" | ./target/release/sql-cli --format

# Output:
# SELECT id
# FROM users
```

### Neovim Plugin Usage

Simply use `\sf` as before - comments are now preserved automatically!

```sql
-- Before formatting
-- User activity query
-- Find active users
SELECT u.id,u.name,u.email FROM users u WHERE u.active=true

-- After \sf (comments preserved!)
-- User activity query
-- Find active users
SELECT u.id, u.name, u.email
FROM users u
WHERE u.active = TRUE
```

## Technical Details

### Files Modified

1. **src/sql/parser/lexer.rs**
   - Added `LexerMode` enum
   - Dual-mode lexer implementation

2. **src/sql/recursive_parser.rs**
   - Added `ParserMode` enum
   - `Parser::with_mode()` constructor
   - Comment collection logic

3. **src/sql/parser/ast.rs**
   - Added `Comment` struct
   - Comment fields in `SelectStatement` and `SelectItem`

4. **src/sql/parser/ast_formatter.rs**
   - `format_comment()` - formats comments on own line
   - `format_inline_comment()` - formats trailing comments
   - Comment emission in `format_select()`

5. **src/main_handlers.rs**
   - Added `--preserve-comments` flag support
   - Uses `ParserMode::PreserveComments` when flag present

6. **nvim-plugin/lua/sql-cli/formatter.lua**
   - Passes `--preserve-comments` flag to CLI
   - Removed manual comment preservation workaround

### Test Coverage

**6 new comment preservation tests:**
- `test_standard_mode_skips_comments` - Backward compatibility
- `test_preserve_mode_captures_leading_comments` - Comment capture
- `test_formatter_emits_comments` - Formatter output
- `test_full_round_trip_with_comments` - Parse → format cycle
- `test_backward_compatibility` - Existing code unchanged
- `test_block_comment_preservation` - Block comments work

**All tests passing:**
- 457 tests pass (including 6 new ones)
- Zero regressions
- Backward compatibility verified

## Limitations & Known Issues

### What Works
- ✅ Leading comments before SELECT statement
- ✅ Trailing comments at end of statement
- ✅ Line comments (`-- comment`)
- ✅ Block comments (`/* comment */`)
- ✅ Multiple consecutive comments
- ✅ Backward compatibility (Standard mode unchanged)

### Current Limitations
- ⚠️ Inline comments within SELECT items not yet supported
  - Example: `SELECT id, /* inline */ name FROM users`
  - This is a known limitation documented in Phase 5 of the plan
- ⚠️ Comments within WHERE/JOIN clauses not yet preserved
  - Future enhancement (Phase 5)

## Configuration

### Neovim Plugin

Comment preservation is **enabled by default**. To disable it, you would need to modify the plugin configuration (though this is not currently exposed as a user option).

### CLI

Use the `--preserve-comments` flag with `--format`:

```bash
# With comment preservation
sql-cli --format --preserve-comments < query.sql

# Without comment preservation (default)
sql-cli --format < query.sql
```

## Examples

### Example 1: Simple Query with Comments

**Input:**
```sql
-- Get all active users
-- Filter by last login date
SELECT id, name, email
FROM users
WHERE active = true
  AND last_login > '2025-01-01'
```

**Output (with --preserve-comments):**
```sql
-- Get all active users
-- Filter by last login date
SELECT id, name, email
FROM users
WHERE active = TRUE
    AND last_login > '2025-01-01'
```

### Example 2: Block Comments

**Input:**
```sql
/*
 * Important: This query is used for reporting
 * Author: John Doe
 * Date: 2025-10-20
 */
SELECT COUNT(*) FROM orders
```

**Output (with --preserve-comments):**
```sql
/* Important: This query is used for reporting
 * Author: John Doe
 * Date: 2025-10-20 */
SELECT COUNT(*)
FROM orders
```

## Performance Impact

- **Standard mode (default)**: Zero performance impact
- **PreserveComments mode**: Minimal overhead
  - Comment collection is fast (simple token iteration)
  - Only active when explicitly requested
  - All 457 tests complete in ~6 seconds

## Future Enhancements (Phase 5)

Potential improvements documented in `COMMENT_PRESERVATION_PHASED_PLAN.md`:

1. **SELECT Item Comments**
   ```sql
   SELECT
       id,        -- Primary key
       name,      -- User name
       email      -- Contact
   FROM users
   ```

2. **WHERE Clause Comments**
   ```sql
   WHERE
       -- Check active users
       status = 'active'
       -- And verified emails
       AND verified = true
   ```

3. **CTE Comments**
   ```sql
   -- User metrics
   WITH user_stats AS (
       SELECT ...
   )
   SELECT * FROM user_stats
   ```

## Success Metrics

✅ All success criteria met:

1. **Functionality**
   - `\sf` in Neovim preserves top-level comments
   - CLI `--format --preserve-comments` works
   - Backward compatibility maintained

2. **Quality**
   - All 457 tests passing
   - Zero regressions
   - Comprehensive test coverage for new features

3. **Documentation**
   - Implementation plan documented
   - Usage examples provided
   - Limitations clearly stated

## Related Documents

- `COMMENT_PRESERVATION_PHASED_PLAN.md` - Detailed implementation plan
- `COMMENT_PRESERVATION_DESIGN.md` - Original design document
- `src/sql/parser/comment_preservation_tests.rs` - Test suite

## Conclusion

Comment preservation is now production-ready and can be used in both CLI and Neovim workflows. The implementation follows the tree-sitter approach of maintaining comments in the AST, enabling formatters to preserve them while keeping the parser and execution engine unchanged.

🎉 Mission accomplished!