[BUG] Regex Expectations on ClickHouse call regexp_like(), which the server does not have — the dialect's predicate is match()

Author: joshua-staufferCreated Sep 17, 2026Updated Sep 18, 2026
Labelsbughelp wantedgood first issueready-for-workclaimed

What's wrong

The four regex Expectations — ExpectColumnValuesToMatchRegex, ExpectColumnValuesToNotMatchRegex, ExpectColumnValuesToMatchRegexList, ExpectColumnValuesToNotMatchRegexList — never evaluate on ClickHouse. Every call returns a raised exception instead of a verdict, although ClickHouse has a regex predicate.

All four metrics get their SQL from get_dialect_regex_expression (great_expectations/expectations/metrics/util.py:246-254), whose ClickHouse branch emits regexp_like(column, pattern). ClickHouse has no regexp_like; its predicate is match(haystack, pattern) (alias REGEXP_MATCHES), with RE2 syntax and substring semantics. The server rejects the query: Code: 46. DB::Exception: Function with name 'regexp_like' does not exist.

Impact

  • Crashes: success=False, raised_exception=True, for every regex Expectation on every ClickHouse data source, regardless of data or pattern. The four Expectations are unusable on this backend.
  • Present since the ClickHouse branch was added in 0.17.0 (#7719, 2023) through 1.23.0; confirmed against clickhouse/clickhouse-server:25.8.29 (current LTS), so this is not a server-version regression — the function never existed.
  • The repository already knows: the ClickHouse harness config carries a curated-tier exclusion for the regex case family (tests/integration/test_utils/data_source_config/clickhouse.py:119) whose reason text names this exact server error and says an issue is still needed. This is that issue.
  • Workaround: ExpectColumnValuesToMatchLikePattern for patterns LIKE can express; nothing for real regex.

Reproduction

Reproduced on 1.23.0 (673082d4b), Python 3.11, against the repository's ClickHouse container (assets/docker/clickhouse, clickhouse-sqlalchemy 0.3.2).

Add to tests/integration/data_sources_and_expectations/expectations/test_expect_column_values_to_match_regex.py (import ClickHouseDatasourceTestConfig alongside the module's other configs):

python
@parameterize_batch_for_data_sources(
    data_source_configs=[ClickHouseDatasourceTestConfig()],
    data=DATA,
)
def test_regex_evaluates_on_clickhouse(batch_for_datasource: Batch) -> None:
    """ClickHouse has a regex predicate, so the expectation must evaluate rather than raise.

    Every value in BASIC_STRINGS is three lowercase letters, so the pattern matches all three and
    the expectation must succeed. Today the ClickHouse branch of the dialect-regex helper emits
    ``regexp_like(...)``, a function this server does not have, so the server rejects the query and
    the result carries a ``DB::Exception`` instead of a verdict.
    """
    result = batch_for_datasource.validate(
        gxe.ExpectColumnValuesToMatchRegex(column=BASIC_STRINGS, regex="^[a-z]{3}$")
    )
    assert result.success, result.exception_info
bash
pytest tests/integration/data_sources_and_expectations/expectations/test_expect_column_values_to_match_regex.py::test_regex_evaluates_on_clickhouse -m clickhouse

Observed:

FAILED ...::test_regex_evaluates_on_clickhouse[clickhouse]
exception_message: Orig exception: Code: 46.
DB::Exception: Function with name `regexp_like` does not exist. In scope SELECT s AS unexpected_values
  FROM (SELECT * FROM repro_regex WHERE true) AS anon_1
  WHERE (s IS NOT NULL) AND (NOT regexp_like(s, '^[a-z]{3}$')) LIMIT 20.

Expected:

1 passed   # success=True; "^[a-z]{3}$" matches abc, def, ghi

Requirements

  1. When any of the four regex Expectations runs against a ClickHouse data source, it must evaluate the pattern and return a verdict, with substring semantics for an unanchored pattern — the same success and unexpected_count that PostgreSQL, MySQL and SQLite return for the same data and pattern.
  2. Both polarities must hold: NotMatchRegex / NotMatchRegexList count a row unexpected when the pattern matches, and match_on="all" / "any" on the list variants behave as on other SQL dialects.
  3. Regex results on every other dialect must be unchanged; the fix is confined to the ClickHouse branch of get_dialect_regex_expression.
  4. The public signatures and parameters of the four Expectations must not change.
  5. The four regex test modules under tests/integration/data_sources_and_expectations/expectations/ must run ClickHouse in their success and failure cases, and the curated-tier "regex_match" exclusion on the ClickHouse harness config must be removed so the curated suite becomes the regression test.

Out of scope: Snowflake's regex anchoring (#12213 — a different branch of the same helper); type comparison on ClickHouse Nullable(...) columns (separate defect); RE2-versus-PCRE pattern-syntax differences (no lookaround or backreferences in RE2 — a documentation concern, not this fix); SQL Server's lack of regex support.

Context

  • Root cause: util.py:252 and :254sa.func.regexp_like(...) and sa.not_(sa.func.regexp_like(...)) inside the ClickHouseDialect branch. Trino and Databricks legitimately use regexp_like; the ClickHouse branch appears to have been modelled on them.
  • Fix shape, verified: replacing those two calls with sa.func.match(...) and changing nothing else makes all four Expectations return correct verdicts and counts against the container — match_regex "^[a-z]{3}$" → success; match_regex "^a" → 2 unexpected of 3 (substring semantics); not_match_regex "^z" → success; not_match_regex "[a-z]" → 3 unexpected; match_regex_list(match_on="all") and not_match_regex_list → success. Server-side: SELECT match('aa','^a'), match('aa','^a$')1, 0. REGEXP_MATCHES is an alias and would also work; match is the documented primary name.
  • The repository's own note that the fix should follow: the curated exclusion at clickhouse.py:119 documents the same cause and asks for a filing. #12103 did the equivalent for Oracle's regex branch — added the branch, deleted the exclusion, let the curated suite pin it.
  • Ruled out: server version (25.8.29 has no regexp_like under any name — system.functions lists match, REGEXP_MATCHES, REGEXP_EXTRACT, REGEXP_REPLACE and the regexp*/replaceRegexp* family only); harness or fixture fault (the same fixture data passes on every other SQL dialect the module runs, and the same table evaluates correctly under the probe above).
  • Also recorded in tests/integration/data_sources_and_expectations/data_source_backlog.md ("Fifteen candidates were measured…"), which calls this family "genuinely a data-source property" — it is not; the backlog should be corrected when this lands.

Source: fivetran/great_expectations