Skip to content

Commit ad4c60f

Browse files
committed
Restrict alias detection to only "from" token.
Looking for "from" token during alias detection must NOT be triggered by columns and other constructs that may also have "from" (e.g. :effectiveFrom binding variable). See #2508.
1 parent e7177d5 commit ad4c60f

File tree

5 files changed

+51
-11
lines changed

5 files changed

+51
-11
lines changed

spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/QueryUtils.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ public abstract class QueryUtils {
138138
static {
139139

140140
StringBuilder builder = new StringBuilder();
141-
builder.append("(?<=from)"); // from as starting delimiter
141+
builder.append("(?<=[^a-zA-Z0-9]+from)"); // from as starting delimiter (with no characters prefixing it)
142142
builder.append("(?:\\s)+"); // at least one space separating
143143
builder.append(IDENTIFIER_GROUP); // Entity name, can be qualified (any
144144
builder.append("(?:\\sas)*"); // exclude possible "as" keyword

spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/DefaultQueryUtilsUnitTests.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ class DefaultQueryUtilsUnitTests {
4545

4646
private static final String QUERY = "select u from User u";
4747
private static final String FQ_QUERY = "select u from org.acme.domain.User$Foo_Bar u";
48-
private static final String SIMPLE_QUERY = "from User u";
48+
private static final String SIMPLE_QUERY = " from User u";
4949
private static final String COUNT_QUERY = "select count(u) from User u";
5050

5151
private static final String QUERY_WITH_AS = "select u from User as u where u.username = ?";

spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/QueryEnhancerUnitTests.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ class QueryEnhancerUnitTests {
4141

4242
private static final String QUERY = "select u from User u";
4343
private static final String FQ_QUERY = "select u from org.acme.domain.User$Foo_Bar u";
44-
private static final String SIMPLE_QUERY = "from User u";
44+
private static final String SIMPLE_QUERY = " from User u";
4545
private static final String COUNT_QUERY = "select count(u) from User u";
4646

4747
private static final String QUERY_WITH_AS = "select u from User as u where u.username = ?";

spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/QueryUtilsUnitTests.java

+42-2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package org.springframework.data.jpa.repository.query;
1717

18+
import static java.util.regex.Pattern.*;
1819
import static org.assertj.core.api.Assertions.*;
1920
import static org.springframework.data.jpa.repository.query.QueryUtils.*;
2021

@@ -50,7 +51,7 @@ class QueryUtilsUnitTests {
5051

5152
private static final String QUERY = "select u from User u";
5253
private static final String FQ_QUERY = "select u from org.acme.domain.User$Foo_Bar u";
53-
private static final String SIMPLE_QUERY = "from User u";
54+
private static final String SIMPLE_QUERY = " from User u";
5455
private static final String COUNT_QUERY = "select count(u) from User u";
5556

5657
private static final String QUERY_WITH_AS = "select u from User as u where u.username = ?";
@@ -123,13 +124,52 @@ void detectsAliasCorrectly() {
123124
assertThat(detectAlias("(select u from User u where not exists ((from User u2 where not exists (from User u3))))"))
124125
.isEqualTo("u");
125126
assertThat(detectAlias(
126-
"from Foo f left join f.bar b with type(b) = BarChild where (f.id = (select max(f.id) from Foo f2 where type(f2) = FooChild) or 1 <> 1) and 1=1"))
127+
" from Foo f left join f.bar b with type(b) = BarChild where (f.id = (select max(f.id) from Foo f2 where type(f2) = FooChild) or 1 <> 1) and 1=1"))
127128
.isEqualTo("f");
128129
assertThat(detectAlias(
129130
"(from Foo f max(f) ((((select * from Foo f2 (from Foo f3) max(*)) (from Foo f4)) max(f5)) (f6)) (from Foo f7))"))
130131
.isEqualTo("f");
131132
}
132133

134+
@Test // GH-2508
135+
void detectAliasWithCastCorrectly() {
136+
137+
assertThat(detectAlias(" from User u where (cast(:effective as date) is null) OR :effective >= u.createdAt"))
138+
.isEqualTo("u");
139+
assertThat(
140+
detectAlias(" from User u where (cast(:effectiveDate as date) is null) OR :effectiveDate >= u.createdAt"))
141+
.isEqualTo("u");
142+
assertThat(
143+
detectAlias(" from User u where (cast(:effectiveFrom as date) is null) OR :effectiveFrom >= u.createdAt"))
144+
.isEqualTo("u");
145+
assertThat(
146+
detectAlias(" from User u where (cast(:e1f2f3ectiveFrom as date) is null) OR :effectiveFrom >= u.createdAt"))
147+
.isEqualTo("u");
148+
}
149+
150+
@Test
151+
void foo() {
152+
153+
StringBuilder builder = new StringBuilder();
154+
builder.append("(?<=[^a-zA-Z]+from)");
155+
156+
Pattern pattern = compile(builder.toString(), CASE_INSENSITIVE);
157+
158+
Matcher matcher = pattern.matcher("select * from User u where (cast(:effectiveDate as date) is null)");
159+
int count = 0;
160+
while (matcher.find()) {
161+
count++;
162+
}
163+
assertThat(count).isEqualTo(1);
164+
165+
matcher = pattern.matcher("select * from User u where (cast(:effectiveFrom as date) is null)");
166+
count = 0;
167+
while (matcher.find()) {
168+
count++;
169+
}
170+
assertThat(count).isEqualTo(1);
171+
}
172+
133173
@Test // GH-2260
134174
void testRemoveSubqueries() throws Exception {
135175

spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/StringQueryUnitTests.java

+6-6
Original file line numberDiff line numberDiff line change
@@ -373,18 +373,18 @@ void checkProjection(String query, String expected, String description, boolean
373373
@Test // DATAJPA-1235
374374
void getAlias() {
375375

376-
checkAlias("from User u", "u", "simple query", false);
376+
checkAlias(" from User u", "u", "simple query", false);
377377
checkAlias("select count(u) from User u", "u", "count query", true);
378378
checkAlias("select u from User as u where u.username = ?", "u", "with as", true);
379379
checkAlias("SELECT FROM USER U", "U", "uppercase", false);
380380
checkAlias("select u from User u", "u", "simple query", true);
381381
checkAlias("select u from com.acme.User u", "u", "fully qualified package name", true);
382382
checkAlias("select u from T05User u", "u", "interesting entity name", true);
383-
checkAlias("from User ", null, "trailing space", false);
384-
checkAlias("from User", null, "no trailing space", false);
385-
checkAlias("from User as bs", "bs", "ignored as", false);
386-
checkAlias("from User as AS", "AS", "ignored as using the second", false);
387-
checkAlias("from User asas", "asas", "asas is weird but legal", false);
383+
checkAlias(" from User ", null, "trailing space", false);
384+
checkAlias(" from User", null, "no trailing space", false);
385+
checkAlias(" from User as bs", "bs", "ignored as", false);
386+
checkAlias(" from User as AS", "AS", "ignored as using the second", false);
387+
checkAlias(" from User asas", "asas", "asas is weird but legal", false);
388388

389389
softly.assertAll();
390390
}

0 commit comments

Comments
 (0)