Skip to content

v2 spec: an expression the INSERT evaluates never sees the schema's own settings (lands with the library build) - #632

Draft
EricAndrechek wants to merge 3 commits into
v2from
v2-insert-eval-settings
Draft

EricAndrechek wants to merge 3 commits into
v2from
v2-insert-eval-settings

Conversation

@EricAndrechek

@EricAndrechek EricAndrechek commented Oct 12, 2026 •

Copy link
Copy Markdown
Member

Hold: this lands with the first dev build whose library does it (the artifact producer names the build). Until then the published library still layers the schema's own settings under INSERT-time expressions. Prose only, so the fingerprint doesn't move.

What

spec/abi-v2/docs.md:

  • "Settings." (the layering): at the INSERT, the schema's own settings reach only the parse, as a server's CREATE-time settings never reach its INSERT.
    • The parse class keeps all five layers: the settings ClickHouse's own FormatFactory::getFormatSettings reads (input_format_*, date_time_input_format, input_format_allow_errors_*, …). A type gate among them (Nullable(Tuple)'s, for one) is the exception; it binds the CREATE only.
    • Everything else the INSERT does runs under the call's own settings, the server profile and chs_set_defaults only, over the build's own. Every type gate stays at the build's default unless one of those three sets it. That covers:
      • every expression it evaluates: a DEFAULT or MATERIALIZED fill, a CHECK, a TTL, a partition key the server rebuilds at INSERT (one with a modulo), a projection, a Values body's expressions, and any aggregate function's creator in them;
      • its limits, max_partitions_per_insert_block and throw_on_max_partitions_per_insert_block among them.
    • The sorting key and skip indices, which a server builds under its global context, run under the server profile and chs_set_defaults only. An aggregate function's creator there still reads the call's settings.
    • The consequence: a gated CAST or a gated aggregate function in such an expression (a Values body's included), gated only in the schema's own settings, is refused as the server refuses it (455, 44 or 63). A schema-level partition limit doesn't reach the INSERT. A caller whose real INSERT session carries such a setting passes it in the call's settings or the server profile.
    • Measured by the artifact producer, against the server and the library:
      • FORMAT Values (CAST(1 AS LowCardinality(UInt32))), with the gate only in the schema's settings, is refused 455;
      • a 2-partition body under a schema-level limit of 1 is stored;
      • a 101-partition body under a schema-level throw_on_max_partitions_per_insert_block=0 is refused 252, at the server's default limit of 100.
    • Unchanged: session_timezone keeps the zone path.
  • chs_filter_create, chs_filter_eval_body, chs_block_create: an evaluation's settings are the INSERT session's. They govern parsing the body AND the expressions the INSERT evaluates, and still never reach the WHERE.

Not changed here: docs/guides/settings.md describes generation 1's precedence, and the ABI v1 reference is unchanged.

Measured

  • Fingerprint: unchanged, sha256:d60a681ea0e249ab9e2c83b50640ad9cef040261ddf61805106c93e2c68774e4.
  • include/v2/chtypes.h: a509580c… → 9ccd5716f64eb26b3c9e0982765c589ded8f139b162d3bc9de50edd825848227 (prose).
  • Gates, each exit 0:
    • gen.py --selftest;
    • --major 2 --check and --major 1 --check;
    • check-no-hand-decls.py --scope all;
    • lint-spelling and lint-cited-paths;
    • markdownlint-cli2@0.18.1 and dprint@0.57.4 check;
    • lint-public (last): ok — no pointers into the private repository, its private notes, or a local filesystem.

🤖 Generated with Claude Code

EricAndrechek and others added 3 commits October 12, 2026 18:50
…wn settings

A DEFAULT or MATERIALIZED fill, a CHECK, a TTL, a partition key the server
rebuilds at INSERT, a projection and any aggregate function's creator in them
run under the call's own settings, the server profile and chs_set_defaults
only, with type gates at the build's defaults unless one of those sets them;
the sorting key and skip indices under the server profile and
chs_set_defaults only. A server's CREATE-time settings never reach its INSERT,
so a gated CAST or aggregate function there, gated only in the schema's own
settings, is refused as the server refuses it (455, 44, 63). Parsing keeps all
five layers, and session_timezone keeps the zone path. An evaluation's
settings now say they govern the INSERT's own expressions too.

Prose only: the fingerprint is unchanged.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Whether the expressions a Values body evaluates while it is read keep the
schema's own settings is still being measured against the server, so the
Settings paragraph no longer says either way. Parsing keeps all five layers.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Measured against the server: a Values body's CAST does not get the schema's
type gates (455), and a schema-level partition limit does not reach the
INSERT. So only the settings FormatFactory::getFormatSettings reads keep the
schema's layer, a type gate among them excepted; every INSERT-time
evaluation and every INSERT limit runs under the call's settings, the server
profile and chs_set_defaults.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@EricAndrechek

Copy link
Copy Markdown
Member Author

Landing checklist (handoff 2026-10-13; #633 item 2):

  1. Trigger: the artifact producer reports that the dev build which makes INSERT-time evaluation stop reading the schema's own settings is on staging (its batch 17). Until then, the published library still layers the schema's settings under those expressions, so this stays a draft.

  2. If v2 spec: rule r8 — no input crashes the process (lands with the next spec batch) #630 landed first: merge v2 in, then run scripts/abi-v1/gen.py --major 2 --write and --check. Both PRs move include/v2/chtypes.h. The fingerprint stays d60a681e….

  3. Merge on the maintainers' clearance, once the required checks are green.

  4. The consumer notice for that build names the behaviour change:

    • a gated CAST or aggregate function in a DEFAULT, MATERIALIZED, CHECK or Values body, gated only in the schema's settings, is refused (455/44/63);
    • a schema-level max_partitions_per_insert_block / throw_on_max_partitions_per_insert_block no longer reaches the INSERT.

    A caller whose real INSERT session carries such a setting passes it in the call's settings or the server profile.

This branch has not been deployed

No deployments
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