Skip to content

Commit 113b7cf

Browse files
committed
Polishing.
Enable EclipseLink integration tests for UserRepositoryTests. Disable tests that fail because of non-spec compliance, update test to pass structured query parsing. Improve exception message for failures if the CriteriaBuilder does not support ILIKE. Move tests to according test classes. See #4112
1 parent 5dbf808 commit 113b7cf

File tree

6 files changed

+224
-116
lines changed

6 files changed

+224
-116
lines changed

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

Lines changed: 49 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141

4242
import org.antlr.v4.runtime.CharStreams;
4343
import org.antlr.v4.runtime.CommonTokenStream;
44+
import org.antlr.v4.runtime.ParserRuleContext;
4445
import org.antlr.v4.runtime.tree.ParseTree;
4546
import org.antlr.v4.runtime.tree.TerminalNode;
4647
import org.hibernate.query.criteria.HibernateCriteriaBuilder;
@@ -50,6 +51,8 @@
5051
import org.springframework.data.domain.Sort;
5152
import org.springframework.data.jpa.domain.JpaSort;
5253
import org.springframework.util.Assert;
54+
import org.springframework.util.ClassUtils;
55+
import org.springframework.util.StringUtils;
5356

5457
/**
5558
* Parses the content of {@link JpaSort#unsafe(String...)} as an HQL {@literal sortExpression} and renders that into a
@@ -62,6 +65,9 @@
6265
@SuppressWarnings({ "unchecked", "rawtypes", "ConstantValue", "NullAway" })
6366
class HqlOrderExpressionVisitor extends HqlBaseVisitor<Expression<?>> {
6467

68+
private static final boolean HIBERNATE_PRESENT = ClassUtils.isPresent(
69+
"org.hibernate.query.criteria.HibernateCriteriaBuilder", HqlOrderExpressionVisitor.class.getClassLoader());
70+
6571
private static final DateTimeFormatter DATE_TIME = new DateTimeFormatterBuilder().parseCaseInsensitive()
6672
.append(ISO_LOCAL_DATE).optionalStart().appendLiteral(' ').optionalEnd().optionalStart().appendLiteral('T')
6773
.optionalEnd().append(ISO_LOCAL_TIME).optionalStart().appendLiteral(' ').optionalEnd().optionalStart()
@@ -225,22 +231,53 @@ public Expression<?> visitStringPatternMatching(HqlParser.StringPatternMatchingC
225231
? cb.notLike(condition, match) //
226232
: cb.notLike(condition, match, escape);
227233
}
228-
} else if (ctx.ILIKE() != null && cb instanceof HibernateCriteriaBuilder) {
234+
} else if (ctx.ILIKE() != null) {
235+
236+
if (HIBERNATE_PRESENT) {
237+
if (cb instanceof HibernateCriteriaBuilder hcb) {
238+
239+
if (ctx.NOT() == null) {
240+
return escape == null //
241+
? hcb.ilike(condition, match) //
242+
: hcb.ilike(condition, match, escape);
243+
} else {
244+
return escape == null //
245+
? hcb.notIlike(condition, match) //
246+
: hcb.notIlike(condition, match, escape);
247+
}
248+
}
249+
}
229250

230-
HibernateCriteriaBuilder hcb = (HibernateCriteriaBuilder) cb;
251+
throw new UnsupportedOperationException(
252+
"ILIKE pattern [%s] not supported by %s ".formatted(renderContext(ctx), cb));
253+
} else {
254+
throw new UnsupportedOperationException("Unsupported string matching pattern: " + renderContext(ctx).trim());
255+
}
256+
}
231257

232-
if (ctx.NOT() == null) {
233-
return escape == null //
234-
? hcb.ilike(condition, match) //
235-
: hcb.ilike(condition, match, escape);
236-
} else {
237-
return escape == null //
238-
? hcb.notIlike(condition, match) //
239-
: hcb.notIlike(condition, match, escape);
258+
private static String renderContext(ParserRuleContext ctx) {
259+
260+
if (ctx.children == null) {
261+
return "";
262+
}
263+
264+
StringBuilder builder = new StringBuilder();
265+
for (ParseTree child : ctx.children) {
266+
267+
String text = "";
268+
if (child instanceof TerminalNode) {
269+
text = child.getText();
270+
} else if (child instanceof ParserRuleContext) {
271+
text = renderContext((ParserRuleContext) child);
240272
}
241-
} else {
242-
throw new UnsupportedOperationException("Unsupported string pattern: " + ctx.getText());
273+
274+
if (!builder.isEmpty() && StringUtils.hasText(text)) {
275+
builder.append(" ");
276+
}
277+
builder.append(text);
243278
}
279+
280+
return builder.toString();
244281
}
245282

246283
@Override

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ public class ParameterMetadataProvider {
7272
private int bindMarker;
7373

7474
/**
75-
* Creates a new {@link ParameterMetadataProvider} from the given {@link CriteriaBuilder} and
75+
* Creates a new {@code ParameterMetadataProvider} from the given {@link CriteriaBuilder} and
7676
* {@link ParametersParameterAccessor}.
7777
*
7878
* @param accessor must not be {@literal null}.
@@ -115,7 +115,7 @@ public ParameterMetadataProvider(JpaParameters parameters, EscapeCharacter escap
115115
}
116116

117117
/**
118-
* Creates a new {@link ParameterMetadataProvider} from the given {@link CriteriaBuilder} an {@link Iterable} of all
118+
* Creates a new {@code ParameterMetadataProvider} from the given {@link CriteriaBuilder} an {@link Iterable} of all
119119
* bindable parameter values, and {@link Parameters}.
120120
*
121121
* @param bindableParameterValues may be {@literal null}.

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

Lines changed: 117 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@
3434
* @author Moritz Becker
3535
* @author Andrey Kovalev
3636
* @author Krzysztof Krason
37+
* @author Mark Paluch
3738
*/
3839
@ContextConfiguration(value = "classpath:eclipselink.xml")
39-
@Disabled("hsqldb seems to hang on this test class without leaving a surefire report")
4040
class EclipseLinkNamespaceUserRepositoryTests extends NamespaceUserRepositoryTests {
4141

4242
/**
@@ -102,30 +102,6 @@ void returnsNullValueInMap() {}
102102
@Test
103103
void bindsNativeQueryResultsToProjectionByName() {}
104104

105-
/**
106-
* Ignores the test. Reconsider once https://bugs.eclipse.org/bugs/show_bug.cgi?id=533240 is fixed.
107-
*/
108-
@Override
109-
void findByEmptyArrayOfIntegers() {}
110-
111-
/**
112-
* Ignores the test. Reconsider once https://bugs.eclipse.org/bugs/show_bug.cgi?id=533240 is fixed.
113-
*/
114-
@Override
115-
void findByAgeWithEmptyArrayOfIntegersOrFirstName() {}
116-
117-
/**
118-
* Ignores the test. Reconsider once https://bugs.eclipse.org/bugs/show_bug.cgi?id=533240 is fixed.
119-
*/
120-
@Override
121-
void findByEmptyCollectionOfIntegers() {}
122-
123-
/**
124-
* Ignores the test. Reconsider once https://bugs.eclipse.org/bugs/show_bug.cgi?id=533240 is fixed.
125-
*/
126-
@Override
127-
void findByEmptyCollectionOfStrings() {}
128-
129105
/**
130106
* Ignores the test for EclipseLink.
131107
*/
@@ -165,4 +141,120 @@ void findByElementVarargInAttributeIgnoreCase() {}
165141
@Override
166142
@Test // DATAJPA-1303
167143
void findByElementCollectionInAttributeIgnoreCaseWithNulls() {}
144+
145+
@Disabled("Binding collections to IN predicates not supported")
146+
@Override
147+
@Test
148+
void invokesQueryWithVarargsParametersCorrectly() {}
149+
150+
@Disabled("Named parameters in native SQL queries are not supported in EclipseLink")
151+
@Override
152+
@Test
153+
void insertStatementModifyingQueryWithParamsWorks() {}
154+
155+
@Disabled("Named parameters in native SQL queries are not supported in EclipseLink")
156+
@Override
157+
@Test
158+
void bindsSpELParameterOnlyUsedInCountQuery() {}
159+
160+
@Disabled
161+
@Override
162+
@Test
163+
public void correctlyBuildSortClauseWhenSortingByFunctionAliasAndFunctionContainsNamedParameters() {}
164+
165+
@Disabled
166+
@Override
167+
@Test
168+
public void allowsExecutingPageableMethodWithUnpagedArgument() {}
169+
170+
@Disabled("No Tuples support in EclipseLink")
171+
@Override
172+
@Test
173+
public void supportsProjectionsWithNativeQueriesAndUnderscoresColumnNameToCamelCaseProperty() {}
174+
175+
@Disabled
176+
@Override
177+
@Test
178+
public void findByFluentExampleWithSimplePropertyPathsDoesntLoadUnrequestedPaths() {}
179+
180+
@Disabled("Not spec-compliant")
181+
@Override
182+
@Test
183+
public void findByFluentSpecificationWithInterfaceBasedProjection() {}
184+
185+
@Disabled("Not spec-compliant")
186+
@Override
187+
@Test
188+
public void findByFluentSpecificationWithDtoProjection() {}
189+
190+
@Disabled("Named parameters in native SQL queries are not supported in EclipseLink")
191+
@Override
192+
@Test
193+
public void modifyingUpdateNativeQueryWorksWithJSQLParser() {}
194+
195+
@Disabled("EclipseLink treats id as keyword")
196+
@Override
197+
@Test
198+
public void scrollByPredicateKeysetWithInterfaceProjection() {}
199+
200+
@Disabled("EclipseLink treats id as keyword")
201+
@Override
202+
@Test
203+
public void executesDerivedExistsQuery() {}
204+
205+
@Disabled("Not spec-compliant")
206+
@Override
207+
@Test
208+
public void findByFluentSpecificationWithCollectionPropertyPathsDoesntLoadUnrequestedPaths() {}
209+
210+
@Disabled("Not spec-compliant")
211+
@Override
212+
@Test
213+
public void findByFluentExampleWithComplexPropertyPathsDoesntLoadUnrequestedPaths() {}
214+
215+
@Disabled("Not spec-compliant")
216+
@Override
217+
@Test
218+
public void findByFluentExampleWithCollectionPropertyPathsDoesntLoadUnrequestedPaths() {}
219+
220+
@Disabled("Not spec-compliant")
221+
@Override
222+
@Test
223+
public void findByFluentSpecificationWithSimplePropertyPathsDoesntLoadUnrequestedPaths() {}
224+
225+
@Disabled("Not spec-compliant")
226+
@Override
227+
@Test
228+
public void findByFluentSpecificationWithComplexPropertyPathsDoesntLoadUnrequestedPaths() {}
229+
230+
@Disabled("Not spec-compliant")
231+
@Override
232+
@Test
233+
public void findByFluentPredicateWithProjectionAndPageRequest() {}
234+
235+
@Disabled("Not spec-compliant")
236+
@Override
237+
@Test
238+
public void findByFluentPredicateWithProjectionAndAll() {}
239+
240+
@Disabled("Binding collections to IN predicates not supported")
241+
@Override
242+
@Test
243+
public void findByCollectionWithPageRequest() {}
244+
245+
@Disabled("Binding collections to IN predicates not supported")
246+
@Override
247+
@Test
248+
public void findByCollectionWithPageable() {}
249+
250+
@Disabled("EclipseLink does not support records")
251+
@Override
252+
@Test
253+
public void supportsRecordsWithNativeQueries() {}
254+
255+
@Disabled("Not spec-compliant")
256+
@Override
257+
@Test
258+
public void correctlyBuildSortClauseWhenSortingByFunctionAliasAndFunctionContainsPositionalParameters() {}
259+
168260
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3304,7 +3304,7 @@ void findAllShouldApplyUnsafeSort() {
33043304
repository.saveAllAndFlush(List.of(firstUser, secondUser, thirdUser, fourthUser));
33053305

33063306
assertThat(
3307-
repository.findAll(JpaSort.unsafe("case when firstname ilike 'O%' escape '^' then 'A' else firstname end")))
3307+
repository.findAll(JpaSort.unsafe("case when firstname like 'O%' escape '^' then 'A' else firstname end")))
33083308
.containsExactly(firstUser, thirdUser, secondUser, fourthUser);
33093309
}
33103310

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

Lines changed: 0 additions & 76 deletions
This file was deleted.

0 commit comments

Comments
 (0)