Support functions that have semicolons as arguments.

A native SQL function with ';' as an argument, e.g. listagg(a.b, ';'), will fail to find anything after it (like an alias). By adding ';' to the list of approved function tokens, queries with functional aliases will work properly.

Resolves #2884.
Original pull request: #2891
This commit is contained in:
Greg L. Turnquist
2023-03-27 14:01:46 -05:00
committed by Mark Paluch
parent f45f534a57
commit dc89da4d08
2 changed files with 29 additions and 1 deletions

View File

@@ -186,7 +186,7 @@ public abstract class QueryUtils {
builder = new StringBuilder();
// any function call including parameters within the brackets
builder.append("\\w+\\s*\\([\\w\\.,\\s'=:\\\\?]+\\)");
builder.append("\\w+\\s*\\([\\w\\.,\\s'=:;\\\\?]+\\)");
// the potential alias
builder.append("\\s+[as|AS]+\\s+(([\\w\\.]+))");

View File

@@ -15,6 +15,8 @@
*/
package org.springframework.data.jpa.repository.query;
import static org.assertj.core.api.Assertions.*;
import static org.springframework.data.jpa.repository.query.QueryUtils.*;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.springframework.data.jpa.repository.query.QueryUtils.*;
@@ -886,4 +888,30 @@ class QueryUtilsUnitTests {
+ ") as timestamp\n" //
+ "from foo f", sort)).endsWith("order by f.age desc");
}
@Test // GH-2884
void functionAliasShouldSupportArgumentsWithCommasOrArgumentsWithSemiColons() {
assertThat(QueryUtils.getFunctionAliases("""
select s.id as id, s.name as name, gp.points
from specialist s
left join (
select q.specialist_id, listagg(q.points, ',') as points
from qualification q
group by q.specialist_id
) gp on gp.specialist_id = s.id
where name like :name
""")).containsExactly("points");
assertThat(QueryUtils.getFunctionAliases("""
select s.id as id, s.name as name, gp.points
from specialist s
left join (
select q.specialist_id, listagg(q.points, ';') as points
from qualification q
group by q.specialist_id
) gp on gp.specialist_id = s.id
where name like :name
""")).containsExactly("points");
}
}