Skip to content

fix(schema-compiler): use ClickHouse String type in Tesseract casts (#10316)#11053

Open
igorlukanin wants to merge 1 commit into
cube-js:masterfrom
igorlukanin:fix/clickhouse-tesseract-string-cast-10316
Open

fix(schema-compiler): use ClickHouse String type in Tesseract casts (#10316)#11053
igorlukanin wants to merge 1 commit into
cube-js:masterfrom
igorlukanin:fix/clickhouse-tesseract-string-cast-10316

Conversation

@igorlukanin

Copy link
Copy Markdown
Member

Issue

Fixes the ClickHouse string-cast casing bug reported in #10316.

When the Tesseract SQL planner (CUBEJS_TESSERACT_SQL_PLANNER=true) renders a string cast on ClickHouse — e.g. the composite-primary-key concatenation behind a count measure queried through a join — it emits CAST(x AS STRING). STRING is not a valid ClickHouse type name (ClickHouse uses String, case-sensitive), so the query is rejected.

-- Tesseract (buggy):
count(CAST(order_id AS STRING) || CAST(product_id AS STRING))
-- Legacy planner (correct):
count(toString(CAST(`order_id` as String)) || toString(CAST(`product_id` as String)))

Root cause

BaseQuery defines types.string = 'STRING'. The legacy ClickHouse path never hits it because ClickHouseQuery.castToString() is overridden to emit String. Tesseract, however, renders the types.string template directly, and ClickHouseQuery.sqlTemplates() overrides boolean/timestamp but not string — so the base STRING leaks through.

Fix

Override templates.types.string = 'String' in ClickHouseQuery.sqlTemplates(), mirroring the existing boolean/timestamp overrides.

Note: #10316 also reported a null-safe IS NULL join-key bug, which was already fixed in v1.6.24 (#10494). This PR addresses the remaining string-cast-casing symptom.

@hughtopping

hughtopping commented Jun 11, 2026

Copy link
Copy Markdown

Hi @igorlukanin - we've found that we get a different issue when String is added here. We're getting the following error from Clickhouse: Cannot convert NULL to a non-nullable type.

Using Nullable(String) rather than String fixes the error.

Here's a repro test case:

Clickhouse

CREATE TABLE buyer (id String, first_name String, last_name String, email_addresses Array(String)) ENGINE = MergeTree() ORDER BY id;
CREATE TABLE purchase (id String, buyer_id String) ENGINE = MergeTree() ORDER BY id;

INSERT INTO buyer VALUES ('1', 'Alice', 'Smith', ['alice@example.com', 'alice.smith@example.com']);
INSERT INTO purchase VALUES ('1', '1');

Cube

# purchases.yml
cubes:
  - name: purchases
    sql: SELECT id, buyer_id FROM purchase
    joins:
      - name: buyers
        sql: "{purchases}.buyer_id = {buyers}.id"
        relationship: many_to_one
    dimensions:
      - name: id
        sql: id
        type: string
        primary_key: true
# buyers.yml
cubes:
  - name: buyers
    sql: SELECT id, first_name, last_name FROM buyer
    joins:
      - name: purchases
        sql: "{buyers}.id = {purchases}.buyer_id"
        relationship: one_to_many
      - name: buyer_email_addresses
        sql: "{buyers}.id = {buyer_email_addresses}.buyer_id"
        relationship: one_to_many
    dimensions:
      - name: id
        sql: id
        type: string
        primary_key: true
      - name: first_name
        sql: first_name
        type: string
# buyer_email_addresses.yml
cubes:
  - name: buyer_email_addresses
    sql: |
      SELECT id AS buyer_id, arrayJoin(email_addresses) AS email_address
      FROM buyer
    joins:
      - name: buyers
        sql: "{buyer_email_addresses}.buyer_id = {buyers}.id"
        relationship: many_to_one
    dimensions:
      - name: id
        sql: buyer_id
        type: string
        primary_key: true
        public: false
      - name: email_address
        sql: email_address
        type: string
    measures: []

Cube SQL API query

SELECT
    purchases.id,
    buyers.first_name,
    array_agg(buyer_email_addresses.email_address) AS email_addresses
FROM purchases
CROSS JOIN buyers
CROSS JOIN buyer_email_addresses
WHERE purchases.id = '1'
GROUP BY purchases.id, buyers.first_name

Edit: this was also reported by another user in #10415 (comment)

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

Labels

javascript Pull requests that update Javascript code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants