ClickHouse: map PostgreSQL regex-match operators (~, ~*, !~, !~*) to match()#5
Open
alexey-milovidov wants to merge 1 commit into
Open
ClickHouse: map PostgreSQL regex-match operators (~, ~*, !~, !~*) to match()#5alexey-milovidov wants to merge 1 commit into
alexey-milovidov wants to merge 1 commit into
Conversation
ClickHouse has no REGEXP_LIKE function and no case-insensitive regex
operator. The PostgreSQL regex-match operators were emitted as
REGEXP_LIKE(...) (for ~ and !~) or an invalid "x REGEXP_ILIKE y" infix
form (for ~* and !~*), both of which ClickHouse rejects at parse time.
Map them to ClickHouse's match(haystack, pattern):
x ~ 'p' -> match(x, 'p')
x ~* 'p' -> match(x, '(?i)p')
x !~ 'p' -> NOT (match(x, 'p'))
x !~* 'p' -> NOT (match(x, '(?i)p'))
Case-insensitive matching uses an inline (?i) flag: inlined into a
string-literal pattern for readable output, and wrapped with concat() for a
non-literal pattern expression so the flag still applies. The mapping is on
the RegexpLike/RegexpILike nodes, so MySQL RLIKE/REGEXP sources transpile to
match() as well.
The polymorphic operators (@>, <@, &&, @@, >>, <<) are intentionally left
untouched: their meaning is type-dependent and cannot be resolved without
operand type information.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Maps PostgreSQL's regex-match operators to ClickHouse's
match()when transpiling to the ClickHouse dialect:x ~ 'p'match(x, 'p')x ~* 'p'match(x, '(?i)p')x !~ 'p'NOT (match(x, 'p'))x !~* 'p'NOT (match(x, '(?i)p'))The mapping lives on the
RegexpLike/RegexpILikeAST nodes, so MySQLRLIKE/REGEXPsources also transpile tomatch().Why
ClickHouse has no
REGEXP_LIKEfunction and no case-insensitive regex operator. Previously these operators were emitted asREGEXP_LIKE(...)(for~/!~) or an invalid infixx REGEXP_ILIKE y(for~*/!~*), both of which ClickHouse rejects:This surfaced while transpiling PostgreSQL's regression test suite to ClickHouse; the
~-family operators are common in real queries (e.g.WHERE name ~ '^A').How
Adds a ClickHouse branch to
generate_regexp_likeandgenerate_regexp_i_like. Case-insensitivity uses an inline(?i)flag — inlined into a string-literal pattern for readable output, and wrapped asconcat('(?i)', pattern)for a non-literal pattern so the flag still applies.!~/!~*are already represented asNOT(RegexpLike/RegexpILike), so they follow automatically.Scope: only the unambiguous operators
Deliberately excluded are PostgreSQL's polymorphic operators —
@>,<@,&&,@@,>>,<<. Their meaning is type-dependent (array vs jsonb vs range vs inet vs bit-string containment / overlap / shift), which a purely syntactic transpiler cannot resolve without operand type information. Mapping@>tohasAllwould be right for arrays but wrong for jsonb/ranges, and PostgreSQL's>>/<<are bit-string/inet operators (not integer shifts), sobitShiftRightwould be incorrect. These continue to pass through unchanged — surfacing as a ClickHouse parse error rather than silently-wrong results. The regex-match operators are unambiguous (text-only), which is why they are safe to map here.Tests
Adds
crates/polyglot-sql/tests/postgres_regexp_clickhouse.rs. Output semantics were verified against a real ClickHouse instance (match('ABC','(?i)abc') = 1,match('ABC','abc') = 0,NOT (match('abc','x')) = 1). The fullpolyglot-sqlsuite passes; the only failing test,tpch_query2_transpile_postgres_to_fabric, is pre-existing onmainand unrelated to this change.Upstream PR: tobilg#316