Skip to content

Implement client-side rendering with interactive result exploration#9

Closed
tobias-fire wants to merge 19 commits intofirebolt-db:mainfrom
tobias-fire:feature/client-side-rendering
Closed

Implement client-side rendering with interactive result exploration#9
tobias-fire wants to merge 19 commits intofirebolt-db:mainfrom
tobias-fire:feature/client-side-rendering

Conversation

@tobias-fire
Copy link

@tobias-fire tobias-fire commented Feb 6, 2026

No description provided.

tobias-fire and others added 19 commits February 6, 2026 16:52
Implements --format=auto option that renders JSONLines_Compact output
as formatted tables with automatic content wrapping.

Features:
- New table_renderer module for parsing JSONLines_Compact format
- Dynamic terminal-width-aware table rendering using comfy-table
- Automatic cell content wrapping to fit terminal width
- Support for multiple DATA messages (accumulates before rendering)
- Graceful error handling with fallback to raw output
- Works in both single-query and REPL modes
- Compatible with existing flags (--verbose, --concise)
- Can be saved as default with --update-defaults

Dependencies added:
- terminal_size 0.3 for terminal width detection
- comfy-table 6.2 for table rendering
- home version constraint to avoid edition2024 issues

All tests passing (41/41).

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add display_width() function to correctly calculate line width ignoring ANSI escape codes
- Enable ContentArrangement::Dynamic for proper content wrapping in expanded mode
- Add special handling for single-column chunks with wide content using UpperBoundary constraint
- Make should_use_expanded_mode() consistent with rendering by applying same truncation logic
- Add max_value_length parameter to render functions for context-specific truncation (1000 chars for expanded, 10000 for horizontal)
- Add comprehensive tests for expanded mode, truncation, and ANSI width calculation

Fixes alignment issues where very long truncated values (like settings_names with 1000+ chars) caused table borders to extend beyond terminal width. All chunks now align properly at the right edge.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Use LowerBoundary constraints instead of fixed boundaries for multi-column chunks to prevent unnecessary content wrapping
- Skip bottom border of non-last chunks to eliminate double borders between chunks within the same row
- Improves readability by ensuring column names display on single lines and reducing repetitive border lines

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Use lighter '--' borders for header separators (between column names and values)
- Use heavier '==' borders for chunk separators (between different column groups)
- This emphasizes the separation between chunks while keeping headers lighter

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Use '==' borders at the top of each chunk (except first) to emphasize new section
- Use '--' borders for bottom, header separators, and internal structure
- Creates clearer visual separation where each chunk begins

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Remove bottom border of non-last chunks since the next chunk's top border provides separation
- Reduces visual clutter by having only one separator line (==) between chunks
- Last chunk still has bottom border for proper closure

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Integrate csvlens library to provide an interactive viewer for query
results in REPL mode. Users can type \view or press Ctrl+V (then Enter)
to open the last query result in a full-screen viewer with vim-like
navigation, search, and scrolling capabilities.

Features:
- Store last query result in Context for viewing
- Convert query results to CSV format with proper escaping
- Launch csvlens viewer with temporary CSV file
- Support both \view text command and Ctrl+V keybind
- Add \help command to show available commands
- Handle error cases gracefully (no results, query errors, empty data)

Implementation:
- New viewer module (src/viewer.rs) for csvlens integration
- CSV conversion functions in table_renderer with RFC 4180 escaping
- Temporary file creation using process ID for uniqueness
- Command detection in REPL loop for \view and \help
- Ctrl+V keybind inserts \view command (user presses Enter to execute)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Replaces the complex chunked expanded mode with a cleaner vertical format
that displays each row as a two-column table (column name | value). This
eliminates ~145 lines of chunking logic while improving readability.

Changes:
- Replace render_table_expanded() with render_table_vertical()
- Rename all "expanded" terminology to "vertical" throughout codebase
- Update format option from --format=expanded to --format=vertical
- Simplify row display: "Row N:" header with simple two-column table
- Column names in cyan bold, values with natural wrapping
- Update all tests to match new format

Benefits: Simpler code, cleaner output, easier to scan, no chunk boundaries

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Replaces content-aware vertical mode detection with simple math based on
available space per column. Adds two configurable parameters for control.

Changes:
- Add --min-col-width (default: 15) to control vertical mode threshold
- Add --max-cell-length (default: 1000) for content truncation
- Replace should_use_vertical_mode with simple calculation:
  terminal_width / num_columns < min_col_width
- Update horizontal table renderer to use equal column widths
- Set explicit ColumnConstraint for predictable layout
- Remove all content inspection from decision logic

Benefits:
- Predictable behavior independent of content
- User-configurable thresholds via command-line options
- Simpler code with no content-aware logic
- Equal column widths for consistent visual alignment

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Replace eprintln!("") and println!("") with eprintln!() and println!()
to fix clippy warnings about unnecessary empty string arguments.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add #[allow(dead_code)] attributes with explanatory comments to:
- JsonLineMessage::Start fields (query_id, request_id, query_label)
- ResultColumn.column_type field

These fields are part of the Firebolt JSONLines_Compact protocol and
required for deserialization but not currently used by the renderer.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add 11 new test functions validating Firebolt's JSONLines_Compact
serialization format for all data types:
- BIGINT (JSON string for precision)
- NUMERIC/DECIMAL (JSON string for exact decimals)
- INT (JSON number)
- DOUBLE/REAL (JSON number)
- DATE/TIMESTAMP (ISO format strings)
- ARRAY (JSON array)
- TEXT (JSON string with unicode)
- BYTEA (hex-encoded string)
- GEOGRAPHY (WKB hex string)
- BOOLEAN/NULL
- CSV null handling differences

These tests verify that format_value() correctly handles Firebolt's
type-specific serialization patterns without requiring type-aware logic.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Delete the display_width() function and its test test_display_width()
as they were added but never used. The comfy_table library handles
ANSI escape sequence width calculation internally with
ContentArrangement::Dynamic.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add comprehensive documentation for Firebolt's type-specific JSON
serialization patterns:

1. Added detailed function documentation for format_value() and
   format_value_csv() explaining how each Firebolt type maps to JSON

2. Added new "Data Type Handling in JSONLines_Compact Format" section
   to CLAUDE.md with:
   - Complete type mapping table (INT, BIGINT, NUMERIC, DATE, etc.)
   - Explanation of why BIGINT/NUMERIC use strings (precision)
   - How BYTEA and GEOGRAPHY are hex-encoded
   - Client-side rendering behavior
   - Note that column_type field is available for future use

This documents the actual Firebolt serialization behavior validated
by the comprehensive test suite added in previous commits.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Change println! to print! for raw body output to match upstream behavior.
The server response already includes trailing newlines, so println! was
adding an extra unwanted newline.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
SQL NULL values are now rendered in dark gray color to distinguish
them from the string "NULL". This improves readability by making it
immediately clear which values are actual nulls vs string data.

Changes:
- NULL values displayed in Color::DarkGrey in both horizontal and
  vertical table rendering modes
- Added tests to verify NULL rendering doesn't crash
- Works in both render_table() and render_table_vertical()

To verify: Run a query with NULL values in a terminal:
  fb --core --format=auto "SELECT NULL as n, 'NULL' as s"

The real NULL will appear in darker gray while the string 'NULL'
will display in normal color.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add explicit client-side vs server-side rendering modes using prefix notation
(client:auto, client:vertical, client:horizontal for client rendering;
PSQL, JSON, CSV, etc. for server rendering). Interactive sessions default
to client:auto for pretty tables, while non-interactive sessions default to
PSQL for backward compatibility. Include helpful warnings when users
accidentally omit the client: prefix, and clarify Ctrl+V+Enter behavior
in documentation.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Replace verbose multi-line statistics with a single clean line showing
only relevant metrics: row count with thousand separators and scanned
bytes with smart KB/MB/GB formatting broken down by local (cache) and
remote (storage). Statistics appear between Time and Request Id for
better readability. Respects --concise flag to suppress all metadata.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Document client-side rendering with client: prefix notation, interactive
result exploration via csvlens viewer, smart statistics formatting, and
updated keyboard shortcuts. Include practical example using
information_schema.engine_query_history.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@tobias-fire tobias-fire closed this Feb 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant