Skip to content

LIKE ... ESCAPE ... produces incorrect PSI children in binary expression tree #666

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
griffio opened this issue Mar 31, 2025 · 0 comments · May be fixed by #667
Open

LIKE ... ESCAPE ... produces incorrect PSI children in binary expression tree #666

griffio opened this issue Mar 31, 2025 · 0 comments · May be fixed by #667
Labels

Comments

@griffio
Copy link
Contributor

griffio commented Mar 31, 2025

Failing ANSI SQL

SELECT *
FROM itemDownload
WHERE url LIKE :urlLike ESCAPE :escape AND itemId = :itemId AND channelId = :channelId;

SELECT *
FROM itemDownload
WHERE url LIKE :urlLike AND itemId = :itemId AND channelId = :channelId;

Description

Relates to sqlite ESCAPE gets wrong inferred type

Current PSI nodes:

0 = {SqlColumnExprImpl} "SqlColumnExprImpl(COLUMN_EXPR)
1 = {SqlBinaryLikeOperatorImpl} "SqlBinaryLikeOperatorImpl(BINARY_LIKE_OPERATOR)
2 = {SqlBindExprImpl} "SqlBindExprImpl(BIND_EXPR)
3 = {SqlBinaryAndExprImpl} "SqlBinaryAndExprImpl(BINARY_AND_EXPR) <-- BIND_EXPR :escape is child of this node

The desired tree would be

SqlBinaryAndExprImpl(BINARY_AND_EXPR)
├── SqlBinaryLikeExprImpl(BINARY_LIKE_EXPR)
│   ├── SqlColumnExprImpl(COLUMN_EXPR) "url"
│   ├── SqlBindExprImpl(BIND_EXPR) ":urlLike"
│   └── SqlBindExprImpl(BIND_EXPR) ":escape" (optional ESCAPE clause)
└── SqlBinaryAndExprImpl(BINARY_AND_EXPR)
    ├── SqlBinaryEqualityExprImpl(BINARY_EQUALITY_EXPR)
    │   ├── SqlColumnExprImpl(COLUMN_EXPR) "itemId"
    │   └── SqlBindExprImpl(BIND_EXPR) ":itemId"
    └── SqlBinaryEqualityExprImpl(BINARY_EQUALITY_EXPR)
        ├── SqlColumnExprImpl(COLUMN_EXPR) "channelId"
        └── SqlBindExprImpl(BIND_EXPR) ":channelId"

Proposed fix in sql.bnf grammar

LIKE expr ESCAPE expr is unusual as is similar to a function call LIKE(a, [ b ]) with optional argument of type TEXT

Create a new expr that can be assigned TEXT type in SqlDelight since there is no way to infer it

like_arguments_expr ::=  ESCAPE expr. <-- cannot have  expr [ ESCAPE expr ] as expr always causes a parser loop.

binary_like_expr ::= expr binary_like_operator expr [ like_arguments_expr ] {
  mixin = "com.alecstrong.sql.psi.core.psi.mixins.BinaryLikeExprMixin"
}

Move the precedence of binary_like_expr before bind_expr so that binary_like_expr nodes are children nodes of binary_and

expr ::= ( other_expr
         ...
         | binary_and_expr
         ...
         | bind_expr
         | like_arguments_expr
         | binary_like_expr )
@griffio griffio added the bug label Mar 31, 2025
@griffio griffio linked a pull request Apr 1, 2025 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant