Repository navigation
fix: a pattern is a string, IS is a keyword in any case, YES and NO are names - #21
Merged
Merged
Conversation
…re names Three places where the filter parser and PostgreSQL disagreed. LIKE, ILIKE, SIMILAR TO and the ~~ operators take a string pattern, as the POSIX operators already did: PostgreSQL has no ~~ that takes a number or a boolean, whatever the column's type is. `is` in lower case is the IS keyword, like every other spelling of it; the lexer kept it back as an identifier. YES and NO are no boolean literals: SQL has TRUE and FALSE, and PostgreSQL reads the other two as names. A field may be called yes. Co-Authored-By: Claude Opus 5.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
Three places where the filter parser and PostgreSQL disagreed about an input. What the pattern operators take is read from PostgreSQL's manual, 9.7. Pattern Matching:
and
~~,~~*,!~~,!~~*are what PostgreSQL translatesLIKE,ILIKEand their negations to.name LIKE 1,name NOT ILIKE -1,name ~~ 1,name SIMILAR TO 1,name LIKE TRUEexpected string pattern for operator LIKE, got LITERALoperator does not exist: text ~~ integer, and the same for an integer, a numeric and a boolean column: no~~takes oneYESandNOas boolean literals:active = YES,active IN (yes, no)trueandfalseyesISin lower case:id is null,id is distinct from 1,active is trueIs,iSandISwere accepted)yesorno, in the allow-list:yes = 1Why each
~,~*,!~,!~*) already refused anything else;LIKE,ILIKE,SIMILAR TOand the~~family took any literal. The documentation already said that the parser "checks that the right-hand side is a string literal" for all of them. It is not a matter of the column's type, which the parser does not know: a number is no pattern for any column.iswas kept back as an identifier by a special case in the lexer, written for a test that tokenized an English sentence. Every other keyword, and every other spelling of this one, was read in any case.YESandNOare not SQL's. An expression that parsed with one could not be spliced into aWHEREclause as it was written: PostgreSQL looked for a column.Not in it
The
ESCAPEclause is not part of the grammar, before or now;name LIKE 'x!%' ESCAPE '!'is refused, and the filtering page says so. A pattern uses the default escape character, the backslash.Compatibility
Two inputs that were accepted are refused, so this is for a release note:
docs/migration.mdhas the section ("v1.0.3 → the next release"; the version is the maintainer's to name), with what changes for a caller that walks the tree (reflect.Boolliterals come fromTRUE/FALSEonly; aLIKEnode's right side and aSimilarToNode'sPatternare always a string literal) and forLexerusers.Tests
filter_pg_patterns_test.go, each row run against PostgreSQL 18.6 with what it answered in the comment: 20 refused patterns (every operator, three column types, inside a group, underNOT,ESCAPE), the refusal's wording for the six operators, 14 accepted patterns whose node carries a string literal;ISin four spellings across its predicates, andis = 1refused;YES/NOrefused in eight positions,TRUE/FALSEin any case, a field calledyes, and the string'yes'. Three older tests pinned the old behaviour and are corrected.go test -race -tags=unit ./...passes; coverage 97.5 %, the new function 100 %.🤖 Generated with Claude Code