Skip to content

Document SQL LIKE semantics: wildcards, ESCAPE, case per engine, cost - #786

Draft
kriszyp wants to merge 7 commits into
mainfrom
docs/sql-like-semantics
Draft

kriszyp wants to merge 7 commits into
mainfrom
docs/sql-like-semantics

Conversation

@kriszyp

@kriszyp kriszyp commented Nov 2, 2026 •

Copy link
Copy Markdown
Member

⊙ Problem

The SQL reference describes LIKE only as "Searches for a pattern". harper#3936 makes ESCAPE work and stops matching from backtracking in v5.4. No page says what a pattern means. Also undocumented: the new engine matches case-sensitively and the legacy engine does not. Under the default sql.engine: auto, the same LIKE can match different rows depending on indexes.

🤔 Is the requirement right?

Yes. The brief asks for the v5.4 matching rules. The case split is the part most likely to change which rows an UPDATE or DELETE touches, so it gets the most space.

💡 Solution

🤔 Define sql.engine and sql.allowFullScan on the SQL page?

Yes, in two short paragraphs, because LIKE depends on them and no page defines them. A full sql entry in the configuration options page also needs maxSortRows and maxHashRows, which I did not check. It is tracked in #785.

⚖️ Alternatives

  • Rewrite only the operators-table row: a table cell can't hold the per-engine case rules or the cost and full-scan rules.
  • Make both engines match case the same way, in harper: harper#3936 keeps the split on purpose. These docs describe what ships.

🔧 Changes

✅ Verification

  • Checked against harper#3936 (48d0e92) DESIGN.md, sqlEngine/expressions/like.ts, sqlTranslator/alasqlLike.ts, and integration/unit tests, plus a scratch Harper build under auto, new, new with allowFullScan, and legacy.
  • Checked the "before v5.4.0" claims against [email protected]. On the new engine, ESCAPE was ignored, * acted as a quantifier, and % and _ skipped line breaks. On the legacy engine, _ skipped line breaks and 'a\d' matched a5.
  • npm run build passes, including links and anchors. So do format:check, lint, typecheck and test:examples.
Selected results (PR head, sql.engine: auto unless noted)
Query Result
ip LIKE 't0!%' ESCAPE '!' t0% only
ip LIKE 't0%' (indexed, new engine) t0%, t0!z, t0a; not T0b
note LIKE 't0%' (unindexed, falls back) also T0b
note LIKE 't0%' ORDER BY id new engine, not T0b
ip LIKE '%T0B' falls back, matches T0b
DELETE ... WHERE ip LIKE 't0%' deletes 3, keeps T0b
note LIKE 'a_b' matches a\nb and a\rb on both engines
note LIKE '[z-a]%' 400 (legacy)
ESCAPE '!!', ESCAPE '', ESCAPE 1, trailing escape 400 on all engines
Segment > 10,000 characters between % wildcards 400 on all engines
Legacy > 64 _ pattern naming every noncharacter and PUA pair 400 (legacy)
note LIKE '%_%_%_%_%_%_%_%_%_%_%_%_%_%_Z' on a 100 KB value about 40 ms per request
sql.engine: new, note LIKE 't0%' 400, no usable index condition

🤔 Merge after harper#3936?

Yes. harper#3936 merged to main (ef427ad), and no 5.4 release tag includes it yet, so the v5.4.0 badges match the next release.

Refs HarperFast/harper#3936

🤖 Generated by Gemini (gemini-4-argon-high); posted via @kriszyp.

Related PRs: #783 overlaps, #788 overlaps
Complexity: medium

Deferred findings

Origin — the dispatch brief this PR was written from

Document SQL LIKE wildcards, ESCAPE, and case sensitivity (harper#3936)

Document SQL LIKE semantics in the operations-API SQL reference (reference/operations-api/sql.md, which today lists LIKE only as "Searches for a pattern"), following HarperFast/harper PR HarperFast/harper#3936 (milestone v5.4).

What to document, as user-facing behavior:

  • Wildcards: % matches any run of characters, including line breaks; _ matches exactly one character other than a line break (\n, \r, U+2028, U+2029).
  • LIKE pattern ESCAPE 'c': the escape character makes the next character literal (for example ip LIKE 't0!%' ESCAPE '!' matches exactly t0%). The escape must be exactly one character. A pattern ending in the escape character, an empty or multi-character ESCAPE, and a non-string ESCAPE are rejected with a 400. ESCAPE works in SELECT, UPDATE and DELETE.
  • Case sensitivity: with sql.engine: new (and statements auto serves with the new engine) LIKE is case-sensitive; the legacy engine (sql.engine: legacy, and auto fallbacks) is case-insensitive. Say this plainly; a user running auto can see either.
  • Legacy-only extension: [abc], [a-z] and [^abc] character classes; a reversed range such as [z-a] is a 400. Characters such as *, \, ^, $ are literals in patterns on both engines.
  • Matching cost is linear in the value length for a given pattern (no pathological patterns), so a long pattern on a large table costs time proportional to data scanned; a LIKE with no other indexed condition may require sql.allowFullScan or fall back to the legacy engine under auto (link the existing sql.engine docs if present).

Version note: these are v5.4 behaviors; earlier versions ignored ESCAPE in the new engine and treated * as a wildcard-like regex quantifier there.

Dispatch: task docs-harper-3936 · queued by task:harper-sql-like-linear-matcher-escape · ran by claude/opus/xhigh · worker kzyp-xps-1

Review-Coverage: authored=gemini; ran=cursor-composer,codex,claude; adjudicated=domain; declined=cursor-grok,muse; rounds=8; full=1 @ 0fc2fb7

Review-Attention: skim ~2m (decisions: document-vs-unify-like-case, edge-case-depth, config-keys-home) @ 0fc2fb7

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the SQL documentation and release notes to detail the new SQL engine's behavior, specifically regarding case sensitivity, the new ESCAPE clause in LIKE pattern matching, and performance improvements that prevent backtracking. The review feedback suggests minor documentation improvements, such as avoiding the VersionBadge component mid-sentence inside tables, restructuring a section to place a list of rejected patterns immediately after its introductory sentence, and separating performance limitations from recommendations into distinct sentences for better readability.

Comment thread reference/operations-api/sql.md Resolved
Comment thread reference/operations-api/sql.md Resolved
Comment thread reference/operations-api/sql.md Resolved
@github-actions
github-actions Bot temporarily deployed to pr-786 November 2, 2026 22:18 Inactive
@github-actions

github-actions Bot commented Nov 2, 2026

Copy link
Copy Markdown

🚀 Preview Deployment

Your preview deployment is ready!

🔗 Preview URL: https://preview.harper-documentation.harperfabric.com/pr-786

This preview will update automatically when you push new commits.

@github-actions
github-actions Bot temporarily deployed to pr-786 November 2, 2026 22:24 Inactive
@github-actions

github-actions Bot commented Nov 2, 2026

Copy link
Copy Markdown

🚀 Preview Deployment

Your preview deployment is ready!

🔗 Preview URL: https://preview.harper-documentation.harperfabric.com/pr-786

This preview will update automatically when you push new commits.

@github-actions

github-actions Bot commented Nov 4, 2026

Copy link
Copy Markdown

🚀 Preview Deployment

Your preview deployment is ready!

🔗 Preview URL: https://preview.harper-documentation.harperfabric.com/pr-786

This preview will update automatically when you push new commits.

kriszyp and others added 7 commits November 4, 2026 08:50
Adds a LIKE Pattern Matching section to the operations-API SQL reference
for harper#3936 (v5.4): % and _ semantics, ESCAPE and its 400s, case
sensitivity per engine and how auto can serve either, legacy-only
character classes, and the per-value linear matching bound. Defines
sql.engine and sql.allowFullScan in the fallback contract, lists LIKE
among the engine behavior differences, and adds a 5.4 release note.

Refs HarperFast/harper#3936

Dispatch-Task: docs-harper-3936
Co-Authored-By: Claude Opus 5.5 <[email protected]>
- Name what keeps an unindexed LIKE on the new engine under auto: an
  indexed AND condition, ORDER BY on the primary key, allowFullScan.
- Say the legacy engine checks a pattern when it tests a row.
- Drop the claim that no pattern is expensive; both lengths multiply.
- Scope the full-scan fallback list to auto with allowFullScan off, and
  note that pairing a suffix LIKE with an indexed condition makes it
  case-sensitive.

Dispatch-Task: docs-harper-3936
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Point the scan-routing sentences at the fallback contract rather than
enumerating which statements fall back, scan on the new engine, or get a
400, and scope eager pattern checks to statements the new engine plans.

Dispatch-Task: docs-harper-3936
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Dispatch-Task: docs-harper-3936
Co-Authored-By: Claude Opus 5.5 <[email protected]>
…length advice

Dispatch-Task: docs-harper-3936
Co-Authored-By: Claude Opus 5.5 <[email protected]>
- Document that _ matches any one character including line breaks on both SQL engines in v5.4.0.
- Document the 10,000-character LIKE segment limit and its 400 error shape on both engines.
- Document the legacy-engine 400 error when a pattern with more than 64 _ wildcards uses a character from every reserved noncharacter and Private Use Area pair.
- Clarify escaped [ on the legacy engine and literal pattern checking under auto.

Dispatch-Task: documentation-786-like-rules-update
Co-Authored-By: Gemini <[email protected]>
Dispatch-Task: documentation-786-like-rules-update
Dispatch-Task: pr-maint-53d171c3888f7402736f60bbd9a4d118
Co-Authored-By: Gemini <[email protected]>
@github-actions

github-actions Bot commented Nov 4, 2026

Copy link
Copy Markdown

🚀 Preview Deployment

Your preview deployment is ready!

🔗 Preview URL: https://preview.harper-documentation.harperfabric.com/pr-786

This preview will update automatically when you push new commits.

This branch was successfully deployed

1 active deployment
pr-786 — 0fc2fb79 Deployed Nov 4, 2026 by github-actions[bot]
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.

1 participant