Skip to content

Compile a server's verbatim create_table_query for every engine: enforce CHECK, accept ASSUME and storage-only clauses #477

Open

Description

@EricAndrechek

Accept a server's verbatim create_table_query for every engine. Enforce what a server enforces, and accept what only affects storage.

The ask. Compiling the exact create_table_query a server returns (system.tables) should work for every engine a consumer meets:

  • MergeTree and its Replicated* variants, Distributed, Memory, Null, Log, Buffer, and the rest;
  • with TTL (including now()), SETTINGS, PROJECTION, INDEX and CODEC clauses.

The rules:

  • Clauses that only shape storage (engine parameters, TTL, PROJECTION, INDEX, CODEC, storage SETTINGS) are accepted and ignored for validation, not refused. (Corrected below: some table SETTINGS do change INSERT validation, so they are honoured, not ignored.)
  • CONSTRAINT … CHECK is enforced exactly as a server enforces it. 1.0 already does this for the expression's type and value; see docs/limitations.md.
  • CONSTRAINT … ASSUME must be accepted. ⚠️ A real server does not check ASSUME on insert; it is an optimizer assumption, per ClickHouse's documentation (inferred; to be confirmed by the artifact producer's differential proof). So "enforce" here must mean matching the server, which means not rejecting rows on an ASSUME.

Why. Today a downstream consumer reads system.columns and hand-builds a neutral CREATE TABLE … ENGINE = MergeTree ORDER BY tuple(). That drops the table's CHECK constraints, so the SDK cannot enforce them.

Related known gaps (docs/limitations.md):

  • "A time-dependent TTL in a CREATE comes back as an internal error";
  • "SHOW CREATE of a Memory table is declined";
  • MergeTree settings at a non-default value are declined by design. Revisit each under this issue.

Pairs with the per-schema server profile (#419) and discovery (to be filed).

Needs a library change from the artifact producer.

🤖 Generated with Claude Code

Activity

  1. EricAndrechek commented on Oct 6, 2026

    @EricAndrechek
    MemberAuthor

    Correction (measured by the artifact producer), and one confirmation.

    Correction. The body said storage-only clauses "cannot change whether a row is accepted". That is wrong. Some table SETTINGS change INSERT validation:

    • one adds an implicit sign CHECK;
    • another toggles the validation of Nested array lengths (measured on 26.7.3.19).

    So "accept and ignore storage clauses" is not safe as a blanket rule. The rule becomes:

    • storage clauses that cannot affect a row's verdict or stored value (engine parameters, TTL, PROJECTION/INDEX definitions, CODEC) are accepted;
    • table SETTINGS are honoured where they change validation, exactly as the server applies them, and accepted as no-ops only where they cannot.

    Which settings fall in which class comes from the library's own reading of the server's code, never a hand list in a binding.

    Confirmed: CONSTRAINT … ASSUME is accepted and not enforced. Only CHECK is checked, at all four supported tags. That matches a real server, so 1.0's behaviour here is the target.

    Being probed by the artifact producer: whether an INDEX or PROJECTION expression that throws at INSERT on a real server is currently dropped by the compile. If confirmed, that is an over-accept, and it will be registered in docs/limitations.md.

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 request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions