Skip to content

Commit

Permalink
Fix 5330 add Postgresql ILIKE operator (sqldelight#5333)
Browse files Browse the repository at this point in the history
* override binary_like_operator

Add `ILIKE` to `binary_like_operator`

Postgresql doesn't use `GLOB | REGEXP | MATCH` keywords
It would require rewriting the mixin just to add `ILIKE`

Add like and ilike patterns to regex_match_operator
regex_match_operator is ordered by shortest matching characters first as the parser gets confused

* Add tests

fixture test
integration tests
  • Loading branch information
griffio authored Jul 8, 2024
1 parent 19e393a commit a407d5c
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"static com.alecstrong.sql.psi.core.psi.SqlTypes.FOREIGN"
"static com.alecstrong.sql.psi.core.psi.SqlTypes.FROM"
"static com.alecstrong.sql.psi.core.psi.SqlTypes.GENERATED"
"static com.alecstrong.sql.psi.core.psi.SqlTypes.GLOB"
"static com.alecstrong.sql.psi.core.psi.SqlTypes.GROUP"
"static com.alecstrong.sql.psi.core.psi.SqlTypes.HAVING"
"static com.alecstrong.sql.psi.core.psi.SqlTypes.ID"
Expand All @@ -54,8 +55,10 @@
"static com.alecstrong.sql.psi.core.psi.SqlTypes.INSERT"
"static com.alecstrong.sql.psi.core.psi.SqlTypes.INTO"
"static com.alecstrong.sql.psi.core.psi.SqlTypes.KEY"
"static com.alecstrong.sql.psi.core.psi.SqlTypes.LIKE"
"static com.alecstrong.sql.psi.core.psi.SqlTypes.LIMIT"
"static com.alecstrong.sql.psi.core.psi.SqlTypes.LP"
"static com.alecstrong.sql.psi.core.psi.SqlTypes.MATCH"
"static com.alecstrong.sql.psi.core.psi.SqlTypes.MINUS"
"static com.alecstrong.sql.psi.core.psi.SqlTypes.MULTIPLY"
"static com.alecstrong.sql.psi.core.psi.SqlTypes.NO"
Expand All @@ -69,6 +72,7 @@
"static com.alecstrong.sql.psi.core.psi.SqlTypes.PARTITION"
"static com.alecstrong.sql.psi.core.psi.SqlTypes.PLUS"
"static com.alecstrong.sql.psi.core.psi.SqlTypes.PRIMARY"
"static com.alecstrong.sql.psi.core.psi.SqlTypes.REGEXP"
"static com.alecstrong.sql.psi.core.psi.SqlTypes.RENAME"
"static com.alecstrong.sql.psi.core.psi.SqlTypes.REPLACE"
"static com.alecstrong.sql.psi.core.psi.SqlTypes.ROLLBACK"
Expand Down Expand Up @@ -109,6 +113,7 @@ overrides ::= type_name
| create_index_stmt
| select_stmt
| ordering_term
| binary_like_operator
| literal_value

column_constraint ::= [ CONSTRAINT {identifier} ] (
Expand Down Expand Up @@ -192,6 +197,12 @@ create_index_stmt ::= CREATE [ UNIQUE ] INDEX [ 'CONCURRENTLY' ] [ IF NOT EXISTS
pin = 6
}

binary_like_operator ::= ( 'ILIKE' | LIKE | GLOB | REGEXP | MATCH ) {
extends = "com.alecstrong.sql.psi.core.psi.impl.SqlBinaryLikeOperatorImpl"
implements = "com.alecstrong.sql.psi.core.psi.SqlBinaryLikeOperator"
override = true
}

identity_clause ::= 'IDENTITY' [ LP [ 'SEQUENCE' 'NAME' sequence_name ] [ sequence_parameters* ] RP ]

generated_clause ::= GENERATED ( (ALWAYS AS LP <<expr '-1'>> RP 'STORED') | ( (ALWAYS | BY DEFAULT) AS identity_clause ) ) {
Expand Down Expand Up @@ -445,7 +456,7 @@ match_operator_expression ::= ( {function_expr} | {column_expr} ) match_operator
pin = 2
}

regex_match_operator ::= '~*' | '~' | '!~*' | '!~'
regex_match_operator ::= '~~*' | '~*' | '!~~*' | '!~*' | '~~' | '~' | '!~~' | '!~'

regex_match_operator_expression ::= ( {function_expr} | {column_expr} ) regex_match_operator <<expr '-1'>> {
mixin = "app.cash.sqldelight.dialects.postgresql.grammar.mixins.RegExMatchOperatorExpressionMixin"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
CREATE TABLE Test (
txt TEXT NOT NULL
);

SELECT * FROM Test WHERE txt LIKE 'testing%';

SELECT * FROM Test WHERE txt ILIKE 'test%';

SELECT * FROM Test WHERE txt ~~ 'testin%';

SELECT * FROM Test WHERE txt ~~* '%esting%';

SELECT txt !~~ 'testing%' FROM Test;

SELECT txt !~~* 'testing%' FROM Test;

SELECT txt ILIKE 'test%' FROM Test;
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
CREATE TABLE Test_Like (
txt TEXT NOT NULL
);

insert:
INSERT INTO Test_Like (txt) VALUES(?);

selectWhereLike:
SELECT * FROM Test_Like WHERE txt LIKE ?;

selectWhereILike:
SELECT * FROM Test_Like WHERE txt ILIKE ?;

selectWhereLikeRegex:
SELECT * FROM Test_Like WHERE txt ~~ 'testin%';

selectWhereILikeRegex:
SELECT * FROM Test_Like WHERE txt ~~* '%esting%';

selectLikeRegex:
SELECT txt ~~ 'testing%', txt !~~ 'testing%' FROM Test_Like;

selectILikeRegex:
SELECT txt ~~* 'testing%', txt !~~* 'testing%' FROM Test_Like;
Original file line number Diff line number Diff line change
Expand Up @@ -866,6 +866,42 @@ class PostgreSqlTest {
}
}

@Test
fun testLike() {
database.likeQueries.insert("testing")

with(database.likeQueries.selectWhereLike("test%").executeAsList()) {
assertThat(first()).isEqualTo("testing")
}

with(database.likeQueries.selectWhereLikeRegex().executeAsList()) {
assertThat(first()).isEqualTo("testing")
}

with(database.likeQueries.selectLikeRegex().executeAsList()) {
assertThat(first().expr).isTrue()
assertThat(first().expr_).isFalse()
}
}

@Test
fun testILike() {
database.likeQueries.insert("TESTING")

with(database.likeQueries.selectWhereILike("test%").executeAsList()) {
assertThat(first()).isEqualTo("TESTING")
}

with(database.likeQueries.selectWhereILikeRegex().executeAsList()) {
assertThat(first()).isEqualTo("TESTING")
}

with(database.likeQueries.selectILikeRegex().executeAsList()) {
assertThat(first().expr).isTrue()
assertThat(first().expr_).isFalse()
}
}

@Test
fun testRankOver() {
database.windowFunctionsQueries.insert("t", 2)
Expand Down

0 comments on commit a407d5c

Please sign in to comment.