Skip to content

bug: create-table parser does not track backtick identifiers, silently dropping projections on tables with parens in a column name #196

Description

@alvarogar4

Bug Description

extractCreateTableBody walks create_table_query counting parenthesis depth and skips over ' and " string literals — but it does not track backtick-quoted identifiers:

if (char === "'" || char === '"') {
  inString = true
  stringQuote = char
  continue
}

A backtick-quoted column name containing a parenthesis (ClickHouse permits this) therefore decrements the depth counter mid-identifier, the column-list body is truncated at the wrong offset, and everything derived from that body is silently lost.

Reproduction

const query = `CREATE TABLE app.t (
  a String,
  \`weird)name\` String,
  PROJECTION p INDEX a TYPE basic
)
ENGINE = MergeTree
ORDER BY a`

parseProjectionsFromCreateTableQuery(query)   // => []   (expected: the `p` projection)

The projection itself is entirely ordinary — INDEX a TYPE basic. It is the unrelated `weird)name` column that breaks the parse, so a single such column costs the table all of its projections.

Impact

Low in practice: it requires a column whose backtick-quoted name contains ( or ), which is rare. Filing for the record because the failure is silent — chkit pull emits a table with no projections field and no warning, exactly the shape of #183, and drift then reports the live projection as an extra object.

parseClauseFromCreateTableQuery shares the same file and the same blind spot, so partitionBy / ttl / key clauses are exposed to the same truncation.

Investigation Notes

  • packages/clickhouse/src/create-table-parser.tsextractCreateTableBody tracks ' and " only.
  • splitTopLevelComma (packages/core/src/key-clause.ts) does track backticks, and stripWrappingParens (packages/core/src/projection.ts, added in PR fix(pull): capture index-only projections and render them correctly #193) was made to match it. extractCreateTableBody is now the odd one out.

Verified against ClickHouse 26.3.9.1 — a backtick identifier containing ) is accepted and round-trips:

PROJECTION p INDEX `weird)name` TYPE basic

so chkit is the only layer that mishandles it.

Expected Behavior

A backtick-quoted identifier is opaque text to the parser: parens inside it are not nesting.

Proposed Fix

Track ` alongside ' and " in extractCreateTableBody (and in parseClauseFromCreateTableQuery), matching the quote handling already in splitTopLevelComma. Better still, factor the three copies of quote-aware scanning into one shared helper — see also #195.

May share a root-cause family with #190, where engine parameters bleed into the parsed primaryKey/orderBy; worth checking whether one hardening pass fixes both.

Verification

  • Unit in packages/clickhouse/src/index.test.ts: the CREATE TABLE above yields [{ name: 'p', index: 'a', type: 'basic' }].
  • Also assert a backtick identifier inside the projection's own index expression: PROJECTION p INDEX (`weird)name`) TYPE basic{ index: '`weird)name`' } (core already normalizes this correctly).

Found while verifying #183 / PR #193.

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

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions