Skip to content

feat(executor): implement ILIKE [CLAUDE] - #8144

Merged
georgesittas merged 1 commit into
tobymao:mainfrom
jbylund:feat/executor-ilike
Aug 12, 2026
Merged

feat(executor): implement ILIKE [CLAUDE]#8144
georgesittas merged 1 commit into
tobymao:mainfrom
jbylund:feat/executor-ilike

Conversation

@jbylund

@jbylund jbylund commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

The gap

ILIKE is absent from the executor's ENV entirely, so both it and NOT ILIKE raise rather than answering:

>>> execute("SELECT s FROM t WHERE s ILIKE 'bump%'", tables=t).rows
ExecuteError: Step 'Join: t (...)' failed: name 'ILIKE' is not defined

This is the loose end from #8139, which taught the generator to honor negate on both Like and ILike — so the flag now reaches an ILIKE the ENV cannot resolve.

The change

ILIKE is LIKE with re.IGNORECASE, through one shared helper so the two cannot drift. The escaping and anchoring from 44b73a0 is exactly what ILIKE needs, and that expression moves into the helper unchanged.

ILIKE 'bump%'          -> ['Bump Version']
ILIKE '%version'       -> ['Bump Version', 'B.mp Version']
NOT ILIKE 'bump%'      -> the rest
ILIKE 'b.mp version'   -> ['B.mp Version']                    -- '.' is literal
ILIKE 'b_mp version'   -> ['Bump Version', 'B.mp Version']    -- '_' is the wildcard

Tests

Each pattern is run in both cases and expected to give the same rows, which is the property that actually distinguishes ILIKE from LIKE. Hand-cased patterns assert it only incidentally: they would still pass with IGNORECASE dropped, for whichever spelling happened to match. Verified by removing re.IGNORECASE — the test fails immediately.

The table carries "B.mp Version" alongside "Bump Version" so the . rows discriminate a literal dot from the _ wildcard, rather than only asserting a non-match.

Full suite: 1317 tests, OK.

ILIKE was absent from the executor's ENV entirely, so both it and NOT ILIKE
raised `name 'ILIKE' is not defined` rather than answering:

    >>> execute("SELECT s FROM t WHERE s ILIKE 'bump%'", tables=t).rows
    ExecuteError: Step 'Join: t (...)' failed: name 'ILIKE' is not defined

The loose end from tobymao#8139, which taught the generator to honor negate on both
Like and ILike -- the flag now reaches an ILIKE the ENV could not resolve.

Implemented as LIKE with re.IGNORECASE, sharing one helper so the two cannot
drift: the escaping and anchoring semantics landed in 44b73a0 are exactly
what ILIKE needs too, and that expression moves into the helper unchanged.

Tests mirror test_like_semantics, with each pattern run in both cases and
expected to give the same rows -- the property that distinguishes ILIKE from
LIKE, and one that hand-cased patterns assert only incidentally. A row
carrying a literal dot keeps the "." patterns telling a literal apart from
the "_" wildcard.
@georgesittas
georgesittas merged commit 98f3d66 into tobymao:main Aug 12, 2026
8 checks passed
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