Skip to content

feat: the ESCAPE clause of the pattern operators - #27

Merged
christiangda merged 1 commit into
mainfrom
feat/the-escape-clause
Oct 24, 2026
Merged

christiangda merged 1 commit into
mainfrom
feat/the-escape-clause

Conversation

@christiangda

Copy link
Copy Markdown
Contributor

What was wrong

PostgreSQL writes string LIKE pattern [ESCAPE escape-character], and the same after SIMILAR TO. The clause was not part of this grammar, so name LIKE 'x!%' ESCAPE '!' was refused: a pattern could escape only with the backslash.

What changes

  • The clause follows LIKE, ILIKE, their negations and SIMILAR TO, written with the keyword, in any case.
  • The escape character is a string of one character, counted in characters, not bytes ('é' is one). An empty string turns escaping off.
  • What PostgreSQL refuses is refused, each with its own message:
    • two characters (invalid escape string);
    • a number, a boolean or a column as the escape;
    • the clause after ~~, ~~*, !~~ and !~~*, which take none.
  • BinaryOperatorNode and SimilarToNode carry it as Escape. It is nil without a clause, which is every filter v1.0.5 accepted, and String() writes it.
  • A new field and nothing else changed, so this is a minor version: v1.1.0.

How it was checked

  • Every row of TestFilterParser_TheEscapeClause was run against PostgreSQL 18.6 as SELECT … WHERE (<input>), the version and table shape the existing pattern tests use. What it answered is in each row's comment:
    • 10 accepted inputs, including ESCAPE '' and ESCAPE 'é', plus one in an expression;
    • 11 refused, each checked for its message.
  • Mutants: 7 of 7 caught, each compiling.
    • The ~~ operators taking the clause.
    • Two characters allowed.
    • Bytes counted instead of characters.
    • A non-string escape allowed.
    • The clause not read after SIMILAR TO.
    • The clause left out of String().
    • The NOT LIKE keyword treated as the !~~ operator.
  • go test -race passes, coverage is 97.6%, and golangci-lint reports 0 issues.

Docs: filtering.md (the patterns section, the AST class diagram and table), migration.md (a v1.0.5 → v1.1.0 section).

After this merges and v1.1.0 is tagged, the service and the template each take the bump in a PR of their own.

🤖 Generated with Claude Code

PostgreSQL writes "string LIKE pattern [ESCAPE escape-character]", and
the same after SIMILAR TO; the clause was not part of this grammar, and
"name LIKE 'x!%' ESCAPE '!'" was refused. It follows LIKE, ILIKE, their
negations and SIMILAR TO, written with the keyword, in any case. The
escape character is a string of one character, or empty to turn escaping
off. What PostgreSQL 18.6 refuses is refused: two characters (invalid
escape string), a number, a boolean or a column as the escape, and the
clause after the ~~ operators, which take none.

BinaryOperatorNode and SimilarToNode carry it as Escape, nil without a
clause, which is every filter v1.0.5 accepted; String() writes it. A new
field and nothing else changed: a minor version.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@christiangda christiangda self-assigned this Oct 24, 2026
@christiangda
christiangda merged commit 7279c13 into main Oct 24, 2026
1 check passed
@christiangda
christiangda deleted the feat/the-escape-clause branch October 24, 2026 17:13
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