Resolve handling of ESCAPE clause with LIKE queries on EclipseLink.

Migrate tests to H2 to verify LIKE with ESCAPE works properly on EclipseLink with Spring Data JPA.

Resolves #2955
Original Pull Request: #2956.
This commit is contained in:
Greg L. Turnquist
2023-05-17 15:47:19 -05:00
committed by Mark Paluch
parent 14642a5869
commit 1f28c61247
11 changed files with 115 additions and 21 deletions

View File

@@ -31,6 +31,7 @@
<eclipselink>3.0.3</eclipselink>
<hibernate>6.2.1.Final</hibernate>
<hsqldb>2.7.1</hsqldb>
<h2>2.1.214</h2>
<jsqlparser>4.5</jsqlparser>
<mysql-connector-java>8.0.31</mysql-connector-java>
<postgresql>42.5.0</postgresql>

View File

@@ -100,6 +100,13 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>${h2}</version>
<scope>test</scope>
</dependency>
<!-- MySQL testing support -->
<dependency>
<groupId>com.mysql</groupId>

View File

@@ -579,7 +579,7 @@ dealingWithNullExpression
// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-like-predicate
stringPatternMatching
: expression NOT? (LIKE | ILIKE) expression (ESCAPE expression)?
: expression NOT? (LIKE | ILIKE) expression (ESCAPE (character|parameter))?
;
// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-elements-indices

View File

@@ -2124,7 +2124,11 @@ class HqlQueryRenderer extends HqlBaseVisitor<List<JpaQueryParsingToken>> {
if (ctx.ESCAPE() != null) {
tokens.add(new JpaQueryParsingToken(ctx.ESCAPE()));
tokens.addAll(visit(ctx.expression(2)));
if (ctx.character() != null) {
tokens.addAll(visit(ctx.character()));
} else if (ctx.parameter() != null) {
tokens.addAll(visit(ctx.parameter()));
}
}
return tokens;

View File

@@ -23,8 +23,9 @@ import org.springframework.test.context.ContextConfiguration;
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=349477.
*
* @author Oliver Gierke
* @author Greg Turnquist
*/
@ContextConfiguration("classpath:eclipselink.xml")
@ContextConfiguration("classpath:eclipselink-h2.xml")
class EclipseLinkUserRepositoryFinderTests extends UserRepositoryFinderTests {
@Disabled
@@ -35,21 +36,4 @@ class EclipseLinkUserRepositoryFinderTests extends UserRepositoryFinderTests {
@Override
void executesInKeywordForPageCorrectly() {}
@Disabled("Can't get ESCAPE clause working with EclipseLink. See #2955")
@Override
void escapingInLikeSpels() {
super.escapingInLikeSpels();
}
@Disabled("Can't get ESCAPE clause working with EclipseLink. See #2955")
@Override
void escapingInLikeSpelsInThePresenceOfEscapeCharacters() {
super.escapingInLikeSpelsInThePresenceOfEscapeCharacters();
}
@Disabled("Can't get ESCAPE clause working with EclipseLink. See #2955")
@Override
void escapingInLikeSpelsInThePresenceOfEscapedWildcards() {
super.escapingInLikeSpelsInThePresenceOfEscapedWildcards();
}
}

View File

@@ -52,10 +52,11 @@ import org.springframework.transaction.annotation.Transactional;
*
* @author Oliver Gierke
* @author Krzysztof Krason
* @author Greg Turnquist
* @see QueryLookupStrategy
*/
@ExtendWith(SpringExtension.class)
@ContextConfiguration(locations = "classpath:config/namespace-application-context.xml")
@ContextConfiguration(locations = "classpath:config/namespace-application-context-h2.xml")
@Transactional
class UserRepositoryFinderTests {

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/data/jpa https://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
<import resource="../infrastructure-h2.xml"/>
<!--
Simplified DAO configuration:
1. Looks for DAO interfaces in ${dao-config.dao-package-name} named ${dao.name}Dao
2. Uses entity classes from ${dao-config.entity-package-name}
3. Registers daos under ${dao.name}Dao in the applicationContext
4. Add postfix attributes to dao-config element as needed
You can register DAOs as needed by simply adding "dao" elements named after domain classes
and provide an DAO interface named as described above.
! Note, that PersistenceAnnotationBeanPostProcessor and PersistenceExceptionTranslationPostProcessor !
! do not have to be explicitly registered as they are included by namespace parser !
-->
<jpa:repositories base-package="org.springframework.data.jpa.repository.sample"/>
<!-- Register custom DAO implementation explicitly -->
<bean id="userRepositoryImpl" class="org.springframework.data.jpa.repository.sample.UserRepositoryImpl"/>
</beans>

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd">
<!-- EclipseLink vendor adaptor with workaround platform class for HSQL usage -->
<bean id="vendorAdaptor" class="org.springframework.data.jpa.repository.CustomEclipseLinkJpaVendorAdapter" parent="abstractVendorAdaptor" />
<util:properties id="jpaProperties">
<prop key="jakarta.persistence.jdbc.driver">org.h2.Driver</prop>
<prop key="jakarta.persistence.jdbc.url">jdbc:h2:mem:hades</prop>
<prop key="jakarta.persistence.jdbc.user">sa</prop>
<prop key="jakarta.persistence.jdbc.password"></prop>
<prop key="jakarta.persistence.ddl-generation">create-tables</prop>
<prop key="eclipselink.weaving.internal">false</prop>
<prop key="eclipselink.logging.level">SEVERE</prop>
</util:properties>
</beans>

View File

@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xsi:schemaLocation="http://www.springframework.org/schema/jdbc https://www.springframework.org/schema/jdbc/spring-jdbc.xsd
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
<import resource="hibernate.xml"/>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="persistenceUnitName" value="spring-data-jpa"/>
<property name="jpaVendorAdapter" ref="vendorAdaptor"/>
<property name="jpaProperties" ref="jpaProperties"/>
</bean>
<bean id="abstractVendorAdaptor" abstract="true">
<property name="generateDdl" value="true"/>
<property name="database" value="H2"/>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<bean name="sampleEvaluationContextExtension"
class="org.springframework.data.jpa.repository.sample.SampleEvaluationContextExtension"/>
<jdbc:embedded-database id="dataSource" type="H2" generate-name="true">
<jdbc:script execution="INIT" separator="/;" location="classpath:scripts/h2-init.sql"/>
<jdbc:script execution="INIT" separator="/;" location="classpath:scripts/h2-stored-procedures.sql"/>
</jdbc:embedded-database>
</beans>

View File

@@ -0,0 +1 @@
;

View File

@@ -0,0 +1,9 @@
/;
DROP alias IF EXISTS plus1inout
/;
CREATE alias plus1inout AS $$
Integer plus1inout(Integer arg) {
return arg + 1;
}
$$
/;