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 8b071988c9
commit 1534c87265
2 changed files with 29 additions and 9 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,14 +15,8 @@
*/
package org.springframework.data.jpa.repository.query;
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.applySorting;
import static org.springframework.data.jpa.repository.query.QueryUtils.createCountQueryFor;
import static org.springframework.data.jpa.repository.query.QueryUtils.detectAlias;
import static org.springframework.data.jpa.repository.query.QueryUtils.getOuterJoinAliases;
import static org.springframework.data.jpa.repository.query.QueryUtils.hasConstructorExpression;
import static org.springframework.data.jpa.repository.query.QueryUtils.removeSubqueries;
import static org.assertj.core.api.Assertions.*;
import static org.springframework.data.jpa.repository.query.QueryUtils.*;
import java.util.Collections;
import java.util.Set;
@@ -891,4 +885,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");
}
}