[
https://issues.apache.org/jira/browse/CASSANDRA-19985?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18099019#comment-18099019
]
Brad Schoening edited comment on CASSANDRA-19985 at 7/24/26 9:42 PM:
---------------------------------------------------------------------
[~arvindk12] I've just taken a look and overall looks quite good and will be a
terrific enhancement to CQLSH. Howver, there is one small issue:
with select * from system.compaction_history,
{code:java}
{"id": "b6501d90-8195-11f1-86f0-f7138403cdcf", "bytes_in": "14413",
"bytes_out": "3268", "columnfamily_name": "size_estimates", "compacted_at":
"2026-07-17 04:12:23.556000+0000", "compaction_properties":
"{'compaction_type': 'Compaction'}", "keyspace_name": "system", "rows_merged":
"{4: 3}"}{code}
the bigint value in Json is formatted with quotes on the values but should be
just ints:
{noformat}
"bytes_in": 0,
"bytes_out": 0
{noformat}
same is true for null:
{noformat}
"rows_merged": null{noformat}
please add or update the unit tests to match
I reviewed the problem with Claude which provided this summary:
Looked at {{formatting.py}} — the reason {{strval}} can't produce correct JSON
isn't fixable in the printer alone. Every formatter in this file
({{{}format_value_text{}}}, {{{}format_value_map{}}}, etc.) converts values to
CQL-literal-style strings by design — e.g. {{format_value_text}} wraps text in
single quotes when {{{}quote=True{}}}, and {{format_by_type}} maps {{None}} to
the literal string {{'null'}} for terminal display. That formatting happens
before {{JsonTablePrinter}} ever sees the value, so there's no type information
left to recover downstream.
This likely needs a JSON-aware formatting path added to {{formatting.py}}
itself. There are a few ways to approach it, roughly in order of how much of
this file they touch:
* *Parallel {{_json_formatters}} registry* — mirror the existing
{{{}_formatters{}}}/{{{}formatter_for{}}}/{{{}get_formatter{}}}/{{{}format_value{}}}
pattern with a second registry
({{{}_json_formatters{}}}/{{{}json_formatter_for{}}}/{{{}get_json_formatter{}}}/{{{}format_json_value{}}})
whose functions return native Python objects instead of display strings. Types
with no native JSON equivalent (UUID, timestamp, decimal, inet, blob, etc.) can
fall back to calling the existing display formatter with
{{colormap=NO_COLOR_MAP}} and reuse its string output rather than
reimplementing formatting logic. Keeps the display path completely untouched,
at the cost of more total lines (a second formatter per type). This would
likely be the preferred approach.
* *Standalone recursive encoder outside this file* — a single
{{json_encode_value(val, cqltype)}} function (not registry-based) that switches
on {{{}cqltype.type_name{}}}, handling containers recursively and delegating to
{{format_value}} for leaf types it doesn't want to reimplement. Least invasive
to {{{}formatting.py{}}}, but loses the extensibility of the decorator-based
dispatch (adding a new type means editing an if/elif chain instead of
registering a new function).
was (Author: bschoeni):
[~arvindk12] I've just taken a look and overall looks quite good and will be a
terrific enhancement to CQLSH. Howver, there is one small issue:
with select * from system.compaction_history,
{code:java}
{"id": "b6501d90-8195-11f1-86f0-f7138403cdcf", "bytes_in": "14413",
"bytes_out": "3268", "columnfamily_name": "size_estimates", "compacted_at":
"2026-07-17 04:12:23.556000+0000", "compaction_properties":
"{'compaction_type': 'Compaction'}", "keyspace_name": "system", "rows_merged":
"{4: 3}"}{code}
the bigint value in Json is formatted with quotes on the values but should be
just ints:
{noformat}
"bytes_in": 0,
"bytes_out": 0
{noformat}
same is true for null:
{noformat}
"rows_merged": null{noformat}
please add or update the unit tests to match
I reviewed the problem with Claude which provided this summary:
Looked at {{formatting.py}} — the reason {{strval}} can't produce correct JSON
isn't fixable in the printer alone. Every formatter in this file
({{{}format_value_text{}}}, {{{}format_value_map{}}}, etc.) converts values to
CQL-literal-style strings by design — e.g. {{format_value_text}} wraps text in
single quotes when {{{}quote=True{}}}, and {{format_by_type}} maps {{None}} to
the literal string {{'null'}} for terminal display. That formatting happens
before {{JsonTablePrinter}} ever sees the value, so there's no type information
left to recover downstream.
This likely needs a JSON-aware formatting path added to {{formatting.py}}
itself. A few ways to approach it, roughly in order of how much of this file
they touch:
* *Parallel {{_json_formatters}} registry* — mirror the existing
{{{}_formatters{}}}/{{{}formatter_for{}}}/{{{}get_formatter{}}}/{{{}format_value{}}}
pattern with a second registry
({{{}_json_formatters{}}}/{{{}json_formatter_for{}}}/{{{}get_json_formatter{}}}/{{{}format_json_value{}}})
whose functions return native Python objects instead of display strings. Types
with no native JSON equivalent (UUID, timestamp, decimal, inet, blob, etc.) can
fall back to calling the existing display formatter with
{{colormap=NO_COLOR_MAP}} and reuse its string output rather than
reimplementing formatting logic. Keeps the display path completely untouched,
at the cost of more total lines (a second formatter per type).
* *Standalone recursive encoder outside this file* — a single
{{json_encode_value(val, cqltype)}} function (not registry-based) that switches
on {{{}cqltype.type_name{}}}, handling containers recursively and delegating to
{{format_value}} for leaf types it doesn't want to reimplement. Least invasive
to {{{}formatting.py{}}}, but loses the extensibility of the decorator-based
dispatch (adding a new type means editing an if/elif chain instead of
registering a new function).
> Enhance CQLSH to support machine-readable output formatting
> -----------------------------------------------------------
>
> Key: CASSANDRA-19985
> URL: https://issues.apache.org/jira/browse/CASSANDRA-19985
> Project: Apache Cassandra
> Issue Type: New Feature
> Components: CQL/Interpreter
> Reporter: Brad Schoening
> Assignee: Arvind Kandpal
> Priority: Normal
> Attachments: json_formatters.py
>
> Time Spent: 1.5h
> Remaining Estimate: 0h
>
> Existing CQLSH output formatting provides tabular formatting using grid-like
> separators and text alignment which is designed for user readability.
> When CQL is run for non-interactive tasks as part of a pipeline this
> formatting complicates the machine processing of the output. As an example,
> [Sqlite|https://www.sqlite.org/cli.html] has a command line flag -mode to
> switch between tablular, csv, and several other supported formats.
> This enhancement will provide a new mode argument which will initially offer
> tabular and csv output formats. Tabular will remain the default so there will
> be no change for existing users. In the future, other modes such as json and
> insert could be added.
> {noformat}
> --mode={tabular, csv}
> Specify an output display format. The default is tabular.
> {noformat}
> The existing Copy To can be used for exporting to CSV, but it doesn't allow
> for query criteria and thus isn't a general solution for this issue.
> In cqlshmain.py, the EXPAND CQLSH option which uses print_formatted_result()
> for result output is an example of alternative formatting.
> Paging will have to be properly managed. A good formatter should handle a
> stream of rows rather than requiring the entire list in memory, especially
> for large SELECT * queries.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]