Failing SQL Feature
PostgreSQL LIKE / ILIKE combined with ANY / ALL over an array constructor cannot be parsed:
col LIKE ANY (ARRAY['%a%', '%b%'])
col ILIKE ALL (ARRAY['%a%', '%b%'])
This is the standard PostgreSQL idiom for matching a column against multiple patterns in a single predicate (PostgreSQL docs:
9.7.1. LIKE +
9.24. Row and Array Comparisons). The parser bails on the ( immediately after ANY / ALL, because there is no grammar branch that allows an ARRAY[...] constructor on the right-hand side of LIKE.
SQL Example
Minimal failing input:
SELECT *
FROM t
WHERE col LIKE ANY (ARRAY['%a%', '%b%']);
Also fails:
SELECT *
FROM t
WHERE col ILIKE ANY (ARRAY['%a%', '%b%']);
SELECT *
FROM t
WHERE col LIKE ALL (ARRAY['%a%', '%b%']);
A more realistic example, where the predicate sits inside a CASE expression in the SELECT list (this is the exact shape that originally tripped the parser for us):
SELECT
CASE
WHEN category = 'stock'
AND transaction_type LIKE ANY (ARRAY['%deposit%', '%inflow%', '%dividend%'])
THEN 1
ELSE 0
END AS inflow_count
FROM transactions;
Observed error:
net.sf.jsqlparser.parser.ParseException:
Encountered unexpected token: "(" "(" at line 1, column ...
Was expecting one of: "." "::" "THEN" "[" "^"
Reproduction online (JSQLFormatter, latest SNAPSHOT): <paste the http://jsqlformatter.manticore-projects.com link here after pasting the SQL above>
Software Information
- JSqlParser:
5.4-SNAPSHOT (master, commit 2b141568, 2026-04-12). Also reproduced on 4.9.
- Database: PostgreSQL.
Grammar references
Checked against the latest SNAPSHOT grammar at src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt (and equivalently the published Syntax Diagram).
1. LikeExpression rhs is restricted to SimpleExpression() — lines 7036–7073, in particular line 7059:
Expression LikeExpression(Expression leftExpression) #LikeExpression:
{ ... }
{
[<K_NOT> { result.setNot(true); } ]
(
token = <K_LIKE>
| token = <K_ILIKE>
| token = <K_RLIKE>
| token = <K_REGEXP_LIKE>
| token = <K_REGEXP>
| token = <K_SIMILAR_TO>
| token = <K_MATCH_ANY>
| token = <K_MATCH_ALL>
| token = <K_MATCH_PHRASE>
| token = <K_MATCH_PHRASE_PREFIX>
| token = <K_MATCH_REGEXP>
) { result.setLikeKeyWord( LikeExpression.KeyWord.from(token.image)); }
[ LOOKAHEAD(2) <K_BINARY> {result.setUseBinary(true); } ]
rightExpression = SimpleExpression() // <-- line 7059
...
}
LikeExpression never dispatches to AnyComparisonExpression, so the ANY / SOME / ALL keyword on the right-hand side cannot be picked up at all in this position.
2. AnyComparisonExpression only accepts a parenthesized SELECT — lines 7389–7406, in particular line 7402:
Expression AnyComparisonExpression() :
{ AnyType anyType; Select select; }
{
(
<K_ANY> { anyType = AnyType.ANY; }
| <K_SOME> { anyType = AnyType.SOME; }
| <K_ALL> { anyType = AnyType.ALL; }
)
select = ParenthesedSelect() // <-- line 7402
{
return new AnyComparisonExpression(anyType, select);
}
}
So even if LikeExpression did route through AnyComparisonExpression, the array form (ARRAY[...]) would still be rejected — only a (SELECT ...) is accepted today.
What does already work, and why it doesn't help here
There is one ANY(ARRAY...) test case on master,
src/test/java/net/sf/jsqlparser/expression/CastExpressionTest.java:100-107:
@Test
void testParenthesisCastIssue1997() throws JSQLParserException {
String sqlStr = "SELECT ((foo)::text = ANY((ARRAY['bar'])::text[]))";
assertSqlCanBeParsedAndDeparsed(sqlStr, true);
sqlStr = "SELECT ((foo)::text = ANY((((ARRAY['bar'])))::text[]))";
assertSqlCanBeParsedAndDeparsed(sqlStr, true);
}
This passes only because ANY is here on the right-hand side of =, where it can be parsed as a function name applied to a fully parenthesized cast expression ((ARRAY[...])::text[]). That escape hatch is unavailable on the right-hand side of LIKE, because LikeExpression's rhs production is SimpleExpression() and the ANY keyword is never reached as a function-name token in that slot.
SelectTest:3299 shows the same situation:
"SELECT * FROM pg_constraint WHERE pg_attribute.attnum = ANY(pg_constraint.conkey)"
Again, ANY(col) parses as a function call on the rhs of =.
A grep across src/ on master returns zero test cases for LIKE ANY, LIKE ALL, ILIKE ANY, or ILIKE ALL, so this combination genuinely is not covered.
Suggested direction (optional)
Two grammar changes appear to be needed together:
- In
LikeExpression (around line 7059), allow the rhs to optionally dispatch to AnyComparisonExpression when the next token is ANY / SOME / ALL, instead of only SimpleExpression().
- In
AnyComparisonExpression (around line 7402), accept an ArrayConstructor (or a parenthesized array / cast expression) in addition to ParenthesedSelect().
An alternative would be a dedicated AST node for LIKE ANY (ARRAY...) rather than overloading AnyComparisonExpression, but reusing AnyComparisonExpression looks more consistent with how = ANY (...) is already modeled.
Happy to put up a PR with the grammar change + tests for LIKE ANY (ARRAY[...]), LIKE ALL (ARRAY[...]), and the ILIKE variants once the maintainers confirm a preferred shape.
Failing SQL Feature
PostgreSQL
LIKE/ILIKEcombined withANY/ALLover an array constructor cannot be parsed:col LIKE ANY (ARRAY['%a%', '%b%'])col ILIKE ALL (ARRAY['%a%', '%b%'])This is the standard PostgreSQL idiom for matching a column against multiple patterns in a single predicate (PostgreSQL docs:
9.7.1. LIKE +
9.24. Row and Array Comparisons). The parser bails on the
(immediately afterANY/ALL, because there is no grammar branch that allows anARRAY[...]constructor on the right-hand side ofLIKE.SQL Example
Minimal failing input:
Also fails:
A more realistic example, where the predicate sits inside a
CASEexpression in theSELECTlist (this is the exact shape that originally tripped the parser for us):Observed error:
Reproduction online (JSQLFormatter, latest SNAPSHOT): <paste the http://jsqlformatter.manticore-projects.com link here after pasting the SQL above>
Software Information
5.4-SNAPSHOT(master, commit2b141568, 2026-04-12). Also reproduced on4.9.Grammar references
Checked against the latest SNAPSHOT grammar at
src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt(and equivalently the published Syntax Diagram).1.
LikeExpressionrhs is restricted toSimpleExpression()— lines 7036–7073, in particular line 7059:LikeExpressionnever dispatches toAnyComparisonExpression, so theANY/SOME/ALLkeyword on the right-hand side cannot be picked up at all in this position.2.
AnyComparisonExpressiononly accepts a parenthesizedSELECT— lines 7389–7406, in particular line 7402:So even if
LikeExpressiondid route throughAnyComparisonExpression, the array form (ARRAY[...]) would still be rejected — only a(SELECT ...)is accepted today.What does already work, and why it doesn't help here
There is one
ANY(ARRAY...)test case on master,src/test/java/net/sf/jsqlparser/expression/CastExpressionTest.java:100-107:This passes only because
ANYis here on the right-hand side of=, where it can be parsed as a function name applied to a fully parenthesized cast expression((ARRAY[...])::text[]). That escape hatch is unavailable on the right-hand side ofLIKE, becauseLikeExpression's rhs production isSimpleExpression()and theANYkeyword is never reached as a function-name token in that slot.SelectTest:3299shows the same situation:"SELECT * FROM pg_constraint WHERE pg_attribute.attnum = ANY(pg_constraint.conkey)"Again,
ANY(col)parses as a function call on the rhs of=.A grep across
src/on master returns zero test cases forLIKE ANY,LIKE ALL,ILIKE ANY, orILIKE ALL, so this combination genuinely is not covered.Suggested direction (optional)
Two grammar changes appear to be needed together:
LikeExpression(around line 7059), allow the rhs to optionally dispatch toAnyComparisonExpressionwhen the next token isANY/SOME/ALL, instead of onlySimpleExpression().AnyComparisonExpression(around line 7402), accept anArrayConstructor(or a parenthesized array / cast expression) in addition toParenthesedSelect().An alternative would be a dedicated AST node for
LIKE ANY (ARRAY...)rather than overloadingAnyComparisonExpression, but reusingAnyComparisonExpressionlooks more consistent with how= ANY (...)is already modeled.Happy to put up a PR with the grammar change + tests for
LIKE ANY (ARRAY[...]),LIKE ALL (ARRAY[...]), and theILIKEvariants once the maintainers confirm a preferred shape.