Skip to content

feat(schema): add the ClickHouse text skip index type - #212

Closed
any-victor wants to merge 3 commits into
obsessiondb:mainfrom
victor-software-house:feat/text-skip-index
Closed

any-victor wants to merge 3 commits into
obsessiondb:mainfrom
victor-software-house:feat/text-skip-index

Conversation

@any-victor

@any-victor any-victor commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

Summary

ClickHouse 26.2 made the text index generally available. chkit had no text variant in the skip index union, so a schema could not declare, generate, pull, or drift-check a full-text index.

  1. Model. type: 'text' takes a required tokenizer (SQL, for example 'splitByNonAlpha' or 'ngrams(3)') and the optional preprocessor, postprocessor, supportPhraseSearch, dictionaryBlockSize, dictionaryBlockFrontcodingCompression, postingListBlockSize, and postingListCodec.
  2. Render. chkit writes TYPE text(tokenizer = ..., ...) with the parameters in one fixed order (packages/core/src/text-index.ts).
  3. Introspection and drift. ClickHouse keeps the parameters in the order the DDL was written. Introspection parses type_full by key, and drift compares the re-rendered form, so the order a table was created with does not show as drift.
  4. Pull and validation. chkit pull writes the fields back. Validation reports text_index_missing_tokenizer for an empty tokenizer.
  5. chkit-py. Same support as SkipIndexText, with the same render order and parser (chkit_python/src/chkit/core/text_index.py).

Depends on #211

This branch is stacked on #211 (fix/drift-index-arguments). The text drift check reads type_full, which #211 introduces. Until #211 merges, the diff here includes its commit; the text change is the top commit, 37d0e41.

Test plan

  • New e2e case in drift.e2e.test.ts: lower(email) with ngrams(3), and a column with splitByString, a preprocessor, dictionary_block_size = 512, and posting_list_codec = 'bitpacking'. Drift reports nothing right after migrate.
  • Unit cases: fixed render order and the missing-tokenizer issue (core), parsing parameters written out of order (clickhouse, chkit-py), pull rendering (plugin-pull), and a chkit-py pull round trip.
  • sql-validation e2e: a text case in both the CREATE and the ALTER ADD INDEX lists, in TypeScript and chkit-py.
  • bun run typecheck, bun run lint, and bun run build clean.
  • Against a local ClickHouse 26.9.1.1629: drift e2e 6 pass; core 90, clickhouse 41, plugin-pull 30, drift unit 16 pass.
  • chkit-py against the same server: 1,345 pass, 1 skipped; ruff check and mypy src clean.

…d parens

system.data_skipping_indices.type holds only the index name, so introspection parsed every argument of set, bloom_filter, tokenbf_v1, and ngrambf_v1 as 0 and drift reported index_mismatch right after migrate. type_full carries the arguments.

chkit renders INDEX name (expr), and ClickHouse keeps those parentheses in expr, so the comparison also drops one pair when it encloses the whole expression.
any-victor added a commit to victor-software-house/chkit that referenced this pull request Sep 25, 2026
Downstream-Reason: Model the ClickHouse text index (GA since 26.2) as a skip index type so schemas can declare, pull, migrate, and drift-check it.
Upstream-Status: submitted
Drop-When: obsessiondb#212 (obsessiondb#212) is merged and the base is rebased past it.
any-victor added a commit to victor-software-house/chkit that referenced this pull request Sep 25, 2026
Downstream-Reason: Model the ClickHouse text index (GA since 26.2) as a skip index type so schemas can declare, pull, migrate, and drift-check it.
Upstream-Status: submitted
Drop-When: obsessiondb#212 (obsessiondb#212) is merged and the base is rebased past it.
The TypeScript comparison already drops one pair of parentheses that
encloses the whole index expression. chkit-py still compared the stored
`(lower(x))` against `lower(x)`, so `chkit drift --live` reported
index_mismatch for every skip index right after migrate.
ClickHouse 26.2 made the text index generally available, and chkit could not
declare it: the skip index union had no `text` variant, so a schema with a
full-text index could not be generated, pulled, or drift-checked.

`type: 'text'` takes a required `tokenizer` and the optional preprocessor,
postprocessor, phrase search, dictionary, and posting list parameters.
chkit renders them in one fixed order. ClickHouse keeps them in the order the
DDL was written, so introspection parses `type_full` by key and drift compares
the re-rendered form. Pull writes the fields back, validation reports a
missing tokenizer, and chkit-py carries the same support as `SkipIndexText`.
@KeKs0r

KeKs0r commented Sep 27, 2026

Copy link
Copy Markdown
Member

thanks a lot for this. There were some missing pieaces and I needed to rebase. I merged your proposal in a new PR: #215

Thanks for the input and let me know if there are other missing pieces or general feedback. Would love to learn how you are using ChKit.

@KeKs0r KeKs0r closed this Sep 27, 2026
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.

2 participants