fix(output): truncate table cells to the column width - #71
Merged
Conversation
The `-o table` renderer measures each column, caps the width at
--max-col-width (default 50, not unlimited), draws the border from the
capped widths — and then printed the cell values untruncated. Any value
longer than the cap overflowed its cell, so that row ran past the border
and the table came out ragged. A TeamCity project path like
"xTrader2 / Trading Services / Pricing / Analytics / master" is 58 chars,
giving a 75-column row inside a 67-column frame.
Headers had the same hole: `{:^width$}` pads but never truncates, and it
pads by byte length, so a wide or accented header misaligned too. The
comfy-table styles did truncate, but by byte slicing (`&s[..max-3]`),
which panics on a multi-byte boundary.
Add `truncate_to_width` to string_utils: ANSI-aware (escape codes pass
through uncharged, so colours survive), unicode-width-aware (never splits
a multi-byte char or a wide glyph), appending "..." within the budget.
Use it for cells and headers in both copies of the renderer
(non_interactive::output_table_old_style and its duplicate
main::output_table_helper), centre headers by display width, and replace
the byte-slicing in the comfy path.
`--max-col-width 0` remains the way to get untruncated values; it was
already aligned and stays so.
Tests: 6 unit tests plus a doctest for the helper, including a loop
asserting the result never exceeds the budget for widths 0..=60; and
tests/python_tests/test_table_output_alignment.py, which asserts every
line of a rendered table has identical display width across caps
1/2/3/4/5/12/30/57/58/59, long headers, accented and wide characters,
uncapped, and markdown style. 11 of its 15 cases fail against the
pre-fix binary.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NBuWNEbq5TNWsF2YR9wYVH
Adds a skeleton for the question "would more build agents actually help?",
correlating TeamCity queue time with Metricbeat host CPU.
examples/teamcity_agent_capacity.sql live TeamCity + Elasticsearch,
marked [TEST:SKIP] (credentials)
examples/teamcity_agent_capacity_demo.sql same logic over sample data,
runs today, passes as a smoke test
data/teamcity_{builds,cpu}_sample.csv 6 hosts x 5 agents, built to
produce all three verdicts
The analysis classifies each queued build rather than reporting queue time,
because queue time alone does not say agents are short:
hardware_bound agents busy AND CPU pegged -> more agents make it worse
add_agents agents busy AND CPU idle -> more agents per server help
pool_mismatch agents were free -> not a capacity problem
Two things worth recording from building it:
sql-cli has no ASOF JOIN (kdb `aj`); join types are Cross/Full/Inner/Left/Right.
It is expressible by hand — inequality join to every earlier sample, then
ROW_NUMBER() ... ORDER BY ts DESC filtered to rn = 1 — and the examples carry
that pattern with the operand-order constraint spelled out (the planner requires
the left table's column as the left operand).
P44: PARSE_DATETIME's explicit-format path parses `%z` and then discards the
offset, so `+0000`, `+0100` and `-0500` all yield the same instant, while the
one-arg auto-detect path on ISO-8601 input honours it. DuckDB applies the offset
in all three cases. This is the shape of bug that does not announce itself: it
would have shifted every TeamCity timestamp an hour off UTC through BST while
Metricbeat stayed correct, quietly scrambling the correlation for half the year.
Logged in docs/SQL_PARITY.md; the skeleton works around it by rebuilding the
stamp as ISO-8601 for the one-arg parser.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NBuWNEbq5TNWsF2YR9wYVH
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The
-o tablerenderer measures each column, caps the width at --max-col-width (default 50, not unlimited), draws the border from the capped widths — and then printed the cell values untruncated. Any value longer than the cap overflowed its cell, so that row ran past the border and the table came out ragged. A TeamCity project path like "xTrader2 / Trading Services / Pricing / Analytics / master" is 58 chars, giving a 75-column row inside a 67-column frame.Headers had the same hole:
{:^width$}pads but never truncates, and it pads by byte length, so a wide or accented header misaligned too. The comfy-table styles did truncate, but by byte slicing (&s[..max-3]), which panics on a multi-byte boundary.Add
truncate_to_widthto string_utils: ANSI-aware (escape codes pass through uncharged, so colours survive), unicode-width-aware (never splits a multi-byte char or a wide glyph), appending "..." within the budget. Use it for cells and headers in both copies of the renderer (non_interactive::output_table_old_style and its duplicate main::output_table_helper), centre headers by display width, and replace the byte-slicing in the comfy path.--max-col-width 0remains the way to get untruncated values; it was already aligned and stays so.Tests: 6 unit tests plus a doctest for the helper, including a loop asserting the result never exceeds the budget for widths 0..=60; and tests/python_tests/test_table_output_alignment.py, which asserts every line of a rendered table has identical display width across caps 1/2/3/4/5/12/30/57/58/59, long headers, accented and wide characters, uncapped, and markdown style. 11 of its 15 cases fail against the pre-fix binary.
Claude-Session: https://claude.ai/code/session_01NBuWNEbq5TNWsF2YR9wYVH