[BUG] Regex Expectations on ClickHouse call regexp_like(), which the server does not have — the dialect's predicate is match()
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) through1.23.0; confirmed againstclickhouse/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:
ExpectColumnValuesToMatchLikePatternfor patternsLIKEcan 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):
@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_infopytest tests/integration/data_sources_and_expectations/expectations/test_expect_column_values_to_match_regex.py::test_regex_evaluates_on_clickhouse -m clickhouseObserved:
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, ghiRequirements
- 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
successandunexpected_countthat PostgreSQL, MySQL and SQLite return for the same data and pattern. - Both polarities must hold:
NotMatchRegex/NotMatchRegexListcount a row unexpected when the pattern matches, andmatch_on="all"/"any"on the list variants behave as on other SQL dialects. - Regex results on every other dialect must be unchanged; the fix is confined to the ClickHouse branch of
get_dialect_regex_expression. - The public signatures and parameters of the four Expectations must not change.
- 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:252and:254—sa.func.regexp_like(...)andsa.not_(sa.func.regexp_like(...))inside theClickHouseDialectbranch. Trino and Databricks legitimately useregexp_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")andnot_match_regex_list→ success. Server-side:SELECT match('aa','^a'), match('aa','^a$')→1, 0.REGEXP_MATCHESis an alias and would also work;matchis the documented primary name. - The repository's own note that the fix should follow: the curated exclusion at
clickhouse.py:119documents 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.29has noregexp_likeunder any name —system.functionslistsmatch,REGEXP_MATCHES,REGEXP_EXTRACT,REGEXP_REPLACEand theregexp*/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