Skip to content

feat: pretty-printed table output with auto-detected TTY#163

Merged
vmvarela merged 2 commits into
masterfrom
issue-156/pretty-table-output
Jun 5, 2026
Merged

feat: pretty-printed table output with auto-detected TTY#163
vmvarela merged 2 commits into
masterfrom
issue-156/pretty-table-output

Conversation

@vmvarela

@vmvarela vmvarela commented Jun 5, 2026

Copy link
Copy Markdown
Owner

Summary

Implements #156 — when stdout is a TTY, query results are automatically formatted as an aligned table with Unicode box-drawing borders. When piped, output stays CSV (no behavior change for scripts).

Changes

  • src/table.zig (new): Table formatting module with two-pass streaming architecture
    • Pass 1: compute column widths and detect numeric columns (O(cols) memory)
    • Pass 2: stream rows directly from SQLite to writer
    • Unicode visual width detection for CJK characters (width 2)
    • Batch write operations for performance
    • NULL values shown explicitly
    • Unit tests for isNumericString and visualWidth
  • src/args.zig: Added TableMode enum (auto/always/never) and --table/--no-table CLI flags. --table is validated as incompatible with non-CSV/TSV output formats.
  • src/main.zig: Added stdout TTY detection to resolve table mode. Auto-detection restricted to CSV/TSV output formats. Table output disabled when --output writes to a file.
  • README.md: Added table output example in the usage section, documented --table/--no-table in the flags table.
  • build.zig: Added 7 integration tests covering table output, piped CSV, error paths, numeric alignment, empty results, and --output interaction.

Example

$ printf 'region,product,amount\nAMER,Widget,150.00\nEMEA,Gadget,80.50\nAPAC,Widget,200.00' | sql-pipe --table 'SELECT * FROM t ORDER BY amount DESC'
┌────────┬─────────┬────────┐
│ region │ product │ amount │
├────────┼─────────┼────────┤
│ APAC   │ Widget  │  200.0 │
│ AMER   │ Widget  │  150.0 │
│ EMEA   │ Gadget  │   80.5 │
└────────┴─────────┴────────┘

Unicode support (CJK characters align correctly):

$ printf 'name,city\nAlice,Madrid\nCarol,北京' | sql-pipe --table 'SELECT * FROM t'
┌───────┬────────┐
│ name  │ city   │
├───────┼────────┤
│ Alice │ Madrid │
│ Carol │ 北京   │
└───────┴────────┘

Acceptance Criteria

  • When stdout is a TTY, output is formatted as an aligned table with borders
  • When stdout is piped, output remains CSV (no behavior change)
  • Table includes column headers
  • Columns are properly aligned
  • Numeric values are right-aligned
  • Text values are left-aligned
  • Add --table / --no-table flags for explicit control
  • Handle wide tables gracefully (columns sized to content)
  • Unicode visual width support (CJK characters)
  • NULL values shown explicitly
  • All existing tests pass
  • New tests cover TTY detection, table formatting, and piped output

Code Review Improvements

After initial implementation, code review identified and fixed:

  • Blocker: .auto mode now restricted to CSV/TSV output (prevents tables for JSON/XML)
  • High: Two-pass streaming reduces memory from O(rows×cols) to O(cols)
  • High: sqlite3_step errors now checked and propagated
  • Medium: Unicode visual width helper for CJK character alignment
  • Low: Batch write operations for performance
  • Low: Z023 parameter order compliance
  • Low: Unit tests for pure functions

@vmvarela vmvarela added type:feature New functionality priority:high Must be in the next sprint size:l Large — 1 to 2 days labels Jun 5, 2026
When stdout is a TTY, format query results as an aligned table with
Unicode box-drawing borders. When piped, output stays CSV (preserving
scriptability). Numeric columns are right-aligned, text left-aligned.

- Add src/table.zig: buffers rows, computes column widths, detects
  numeric columns, prints formatted table with ┌─┬─┐ borders
- Add --table / --no-table flags for explicit control (TableMode enum)
- Auto-detect stdout TTY in main() to resolve table mode
- Table mode disabled when --output writes to a file
- --table is incompatible with non-CSV/TSV output formats (error)
- Update README.md with table output examples and flag docs
- Add 7 integration tests covering table output, piped CSV, error
  paths, numeric alignment, empty results, and --output interaction

Closes #156
@vmvarela vmvarela force-pushed the issue-156/pretty-table-output branch from c70563f to aed8f0b Compare June 5, 2026 14:21
- Implement two-pass streaming with sqlite3_reset to reduce memory from O(rows×cols) to O(cols)
- Add visualWidth() helper for proper CJK character alignment (width 2)
- Check sqlite3_step return codes and propagate errors
- Batch write operations for better performance
- Show NULL explicitly instead of blank cells
- Fix Z023 parameter order (std.Io before other params)
- Add unit tests for isNumericString and visualWidth
@vmvarela vmvarela merged commit f4ea026 into master Jun 5, 2026
5 checks passed
@vmvarela vmvarela deleted the issue-156/pretty-table-output branch June 5, 2026 14:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

priority:high Must be in the next sprint size:l Large — 1 to 2 days type:feature New functionality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant