Skip to content

Add NONE, AUTO and ALWAYS string quoting modes for table output #762

Description

@apstndb

Goal and current scope

Add a single human-display string quoting policy, CLI_STRING_QUOTE_MODE = NONE | AUTO | ALWAYS, following the requested three-mode design. This replaces the unpublished CLI_SHOW_NULLS proposal in #992; do not retain overlapping boolean controls or change SQL NULL's spelling. The default is NONE, preserving today's bytes. This body supersedes the earlier marker/NULL-only proposals.

SQLite demonstrates independent table-layout and quote-policy controls; Spanner Studio's 2025-12-03 release note establishes an all-STRING display-only precedent. These are references, not a promise to copy their escaping, defaults or dialect semantics.

Accepted display contract

Apply the mode only in TABLE, TABLE_COMMENT, TABLE_DETAIL_COMMENT and VERTICAL, including typed client-side/INFORMATION_SCHEMA SHOW results, DML returned rows, streaming/buffered results and STRING children within ARRAY/STRUCT.

  • NONE: preserve the existing formatter unchanged, including raw STRINGs and existing NULL styling.
  • ALWAYS: quote every non-NULL STRING, including empty STRING.
  • AUTO: quote a STRING if any of the following holds; otherwise retain its raw spelling:
    • It is empty, or has leading/trailing Unicode whitespace.
    • It exactly equals one of NULL, null, true, false, NaN, +Inf, -Inf. These include the actual current SQL NULL, BOOL, FLOAT and JSON-null display tokens. The comparisons are case-sensitive; Null and TRUE remain raw.
    • Its entire contents match the decimal-number-like grammar ^[+-]?(?:[0-9]+(?:\.[0-9]*)?|\.[0-9]+)(?:[eE][+-]?[0-9]+)?$. Examples: 123, 0123, +1, 1e3, .5, 1.. Exclude 0xFF, 1+1 and partial matches. Use a precompiled expression, not per-cell SQL parsing or float conversion/range checks.
    • It contains a double quote, backslash, comma, square bracket or curly brace, or any rune for which strconv.IsPrint is false. Brackets and comma matter for the existing recursive ARRAY/STRUCT display, so check them anywhere, not only at the start. Single quotes alone do not trigger quoting because this policy uses a fixed double-quote delimiter.

AUTO is a documented readability heuristic, not the mathematically smallest set and not full cross-type roundtripping (dates, BYTES, JSON and PROTO/ENUM retain their existing formats). The explicit set is preferable to guessing the type of every cell. Ordinary abc and <NULL> remain raw; empty STRING becomes "".

AUTO and ALWAYS share exactly one quoting operation: strconv.Quote. It provides fixed double quotes with escaped quotes, backslashes and nonprintable characters, preserving NUL and arbitrary Go string bytes. This is a display escape grammar, not a claim of JSON or SQL literal syntax; do not label Go-only escapes such as \x00 as JSON. Every input containing a double quote is itself quoted in AUTO, preventing newly quoted output from colliding with an unchanged already-quoted input.

SQL NULL always remains NULL, with typed no-wrap/dim styling preserved. Non-STRING formatting stays unchanged, including nil/empty BYTES and arrays, JSON's own null, and PROTO/ENUM plugins. A STRING NULL renders as "NULL"; a STRING containing the quotes around NULL renders as "\"NULL\"" in AUTO/ALWAYS.

Implementation boundaries

Use the existing enums/enumer and EnumVar conventions, normal SET/SHOW/RESET/SET LOCAL behavior, and the existing narrow cloned WithComplexPlugin / PluginFromNullable STRING seam over pinned spanvalue v0.8.4. Do not mutate shared presets, change the whole literal format, add a renderer framework or upgrade dependencies. Reuse the held PR's formatting integration; remove obsolete boolean code/tests/docs.

Keep CSV, TSV, JSONL, SQL export, TAB, HTML and XML byte-for-byte unchanged, including SQL-configured client-side export fallbacks. Preformatted plan/stat/presentation rows, headers and metadata remain outside this typed STRING policy. Do not broaden #790 exports or #284 truncation.

Acceptance and verification

  • Verify the policy through actual typed format/render paths in every mode: SQL NULL; ordinary/string NULL/quoted NULL; empty/whitespace; booleans, finite/nonfinite number-like strings; decimal grammar boundaries; quotes/backslashes/NUL/newline/nonprinting Unicode; punctuation in recursive ARRAY/STRUCT; literal strings that equal another value's quoted output.
  • Compare a one-element STRING array containing a,b with two elements a and b; AUTO must keep those displayed contents distinct. Preserve nested NULLs, JSON null and PROTO/ENUM behavior.
  • Cover normal/colorless/color-enabled output, streaming/buffered tables, typed SHOW, DML returned rows and normal SET/RESET/LOCAL lifecycle. Assert actual failures/causes for invalid ENUM values; preserve state on rejection.
  • Keep exact-byte NONE/default and excluded-format regressions. Prefer representative real-path table tests over duplicated helper-only assertions.
  • Update user documentation with the three modes, AUTO's documented rules, shared display escapes and unchanged exports. Regenerate reference metadata with make docs-update.
  • One PR, Fixes #762. Before every additive push, integrate current main, run focused tests, make check and make check-race, capture output and check exit codes. Coverage floor remains 80. Do not merge before exact-head independent acceptance.

References: https://www.sqlite.org/climode.html ; https://docs.cloud.google.com/spanner/docs/release-notes?hl=en#December_03_2025 . Local survey and actual formatter token proof were completed on 2026-09-15 JST; the latter observed true, false, NaN, +Inf, -Inf, and 0.500000 using spanvalue v0.8.4.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestoutput-formattingOutput format and display improvements

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions