Skip to content

Commit 163b478

Browse files
committed
HHH-3404 regexp support in criteria API
1 parent 447f46d commit 163b478

File tree

5 files changed

+122
-7
lines changed

5 files changed

+122
-7
lines changed

hibernate-core/src/main/java/org/hibernate/query/criteria/HibernateCriteriaBuilder.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -998,6 +998,14 @@ <Y extends Comparable<? super Y>> JpaPredicate between(
998998

999999
JpaPredicate notIlike(Expression<String> x, String pattern, char escapeChar);
10001000

1001+
JpaPredicate likeRegexp(Expression<String> x, String pattern);
1002+
1003+
JpaPredicate ilikeRegexp(Expression<String> x, String pattern);
1004+
1005+
JpaPredicate notLikeRegexp(Expression<String> x, String pattern);
1006+
1007+
JpaPredicate notIlikeRegexp(Expression<String> x, String pattern);
1008+
10011009
@Override
10021010
<T> JpaInPredicate<T> in(Expression<? extends T> expression);
10031011

hibernate-core/src/main/java/org/hibernate/query/criteria/spi/HibernateCriteriaBuilderDelegate.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1255,6 +1255,26 @@ public JpaPredicate notIlike(Expression<String> x, String pattern, char escapeCh
12551255
return criteriaBuilder.notIlike( x, pattern, escapeChar );
12561256
}
12571257

1258+
@Override
1259+
public JpaPredicate likeRegexp(Expression<String> x, String pattern) {
1260+
return criteriaBuilder.likeRegexp( x, pattern );
1261+
}
1262+
1263+
@Override
1264+
public JpaPredicate ilikeRegexp(Expression<String> x, String pattern) {
1265+
return criteriaBuilder.ilikeRegexp( x, pattern );
1266+
}
1267+
1268+
@Override
1269+
public JpaPredicate notLikeRegexp(Expression<String> x, String pattern) {
1270+
return criteriaBuilder.notLikeRegexp( x, pattern );
1271+
}
1272+
1273+
@Override
1274+
public JpaPredicate notIlikeRegexp(Expression<String> x, String pattern) {
1275+
return criteriaBuilder.notIlikeRegexp( x, pattern );
1276+
}
1277+
12581278
@Override
12591279
public <T> JpaInPredicate<T> in(Expression<? extends T> expression) {
12601280
return criteriaBuilder.in( expression );

hibernate-core/src/main/java/org/hibernate/query/hql/internal/SemanticQueryBuilder.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3210,11 +3210,13 @@ public SqmPredicate visitIntersectsPredicate(HqlParser.IntersectsPredicateContex
32103210
query
32113211
);
32123212
}
3213-
final SelfRenderingSqmFunction<Boolean> contains = getFunctionDescriptor( "array_intersects" ).generateSqmExpression(
3214-
asList( lhs, rhs ),
3215-
null,
3216-
queryEngine()
3217-
);
3213+
final SelfRenderingSqmFunction<Boolean> contains =
3214+
getFunctionDescriptor( "array_intersects" )
3215+
.generateSqmExpression(
3216+
asList( lhs, rhs ),
3217+
null,
3218+
queryEngine()
3219+
);
32183220
return new SqmBooleanExpressionPredicate( contains, negated, nodeBuilder() );
32193221
}
32203222

hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmCriteriaNodeBuilder.java

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2953,6 +2953,66 @@ public SqmPredicate notIlike(Expression<String> x, String pattern, char escapeCh
29532953
return not( ilike( x, pattern, escapeChar ) );
29542954
}
29552955

2956+
@Override
2957+
public JpaPredicate likeRegexp(Expression<String> x, String pattern) {
2958+
return new SqmBooleanExpressionPredicate(
2959+
getFunctionDescriptor( "regexp_like" )
2960+
.generateSqmExpression(
2961+
asList( (SqmExpression<String>) x,
2962+
literal( pattern ) ),
2963+
null,
2964+
getQueryEngine()
2965+
),
2966+
this
2967+
);
2968+
}
2969+
2970+
@Override
2971+
public JpaPredicate ilikeRegexp(Expression<String> x, String pattern) {
2972+
return new SqmBooleanExpressionPredicate(
2973+
getFunctionDescriptor( "regexp_like" )
2974+
.generateSqmExpression(
2975+
asList( (SqmExpression<String>) x,
2976+
literal( pattern ),
2977+
literal( "i" ) ),
2978+
null,
2979+
getQueryEngine()
2980+
),
2981+
this
2982+
);
2983+
}
2984+
2985+
@Override
2986+
public JpaPredicate notLikeRegexp(Expression<String> x, String pattern) {
2987+
return new SqmBooleanExpressionPredicate(
2988+
getFunctionDescriptor( "regexp_like" )
2989+
.generateSqmExpression(
2990+
asList( (SqmExpression<String>) x,
2991+
literal( pattern ) ),
2992+
null,
2993+
getQueryEngine()
2994+
),
2995+
true,
2996+
this
2997+
);
2998+
}
2999+
3000+
@Override
3001+
public JpaPredicate notIlikeRegexp(Expression<String> x, String pattern) {
3002+
return new SqmBooleanExpressionPredicate(
3003+
getFunctionDescriptor( "regexp_like" )
3004+
.generateSqmExpression(
3005+
asList( (SqmExpression<String>) x,
3006+
literal( pattern ),
3007+
literal( "i" ) ),
3008+
null,
3009+
getQueryEngine()
3010+
),
3011+
true,
3012+
this
3013+
);
3014+
}
3015+
29563016
@Override
29573017
@SuppressWarnings("unchecked")
29583018
public <T> SqmInPredicate<T> in(Expression<? extends T> expression) {

hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/RegexTest.java

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,14 @@
1010
import org.hibernate.dialect.OracleDialect;
1111
import org.hibernate.dialect.SQLServerDialect;
1212
import org.hibernate.dialect.SybaseASEDialect;
13+
import org.hibernate.query.criteria.HibernateCriteriaBuilder;
1314
import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
1415
import org.hibernate.testing.orm.junit.Jpa;
1516
import org.hibernate.testing.orm.junit.SkipForDialect;
1617
import org.junit.jupiter.api.Test;
1718

1819
import static org.junit.jupiter.api.Assertions.assertEquals;
20+
import static org.junit.jupiter.api.Assertions.assertFalse;
1921
import static org.junit.jupiter.api.Assertions.assertTrue;
2022

2123
@Jpa
@@ -31,6 +33,18 @@ void testInSelect(EntityManagerFactoryScope scope) {
3133
scope.inEntityManager( em -> {
3234
assertTrue( em.createQuery( "select regexp_like('abcdef', 'ab.*')", Boolean.class ).getSingleResult() );
3335
assertTrue( em.createQuery( "select 'abcdef' like regexp 'ab.*'", Boolean.class ).getSingleResult() );
36+
var builder = (HibernateCriteriaBuilder) em.getCriteriaBuilder();
37+
var query = builder.createQuery( Boolean.class );
38+
query.select( builder.likeRegexp( builder.literal( "abcdef" ), "ab.*" ) );
39+
assertTrue( em.createQuery( query ).getSingleResult() );
40+
} );
41+
scope.inEntityManager( em -> {
42+
assertFalse( em.createQuery( "select not regexp_like('abcdef', 'ab.*')", Boolean.class ).getSingleResult() );
43+
assertFalse( em.createQuery( "select 'abcdef' not like regexp 'ab.*'", Boolean.class ).getSingleResult() );
44+
var builder = (HibernateCriteriaBuilder) em.getCriteriaBuilder();
45+
var query = builder.createQuery( Boolean.class );
46+
query.select( builder.notLikeRegexp( builder.literal( "abcdef" ), "ab.*" ) );
47+
assertFalse( em.createQuery( query ).getSingleResult() );
3448
} );
3549
}
3650
}
@@ -48,9 +62,20 @@ void testInSelectCaseInsensitive(EntityManagerFactoryScope scope) {
4862
if ( !( scope.getDialect() instanceof OracleDialect dialect
4963
&& ( dialect.isAutonomous() || dialect.getVersion().isBefore( 23 ) ) ) ) {
5064
scope.inEntityManager( em -> {
51-
assertTrue( em.createQuery( "select regexp_like('ABCDEF', 'ab.*', 'i')", Boolean.class )
52-
.getSingleResult() );
65+
assertTrue( em.createQuery( "select regexp_like('ABCDEF', 'ab.*', 'i')", Boolean.class ).getSingleResult() );
5366
assertTrue( em.createQuery( "select 'abcdef' ilike regexp 'ab.*'", Boolean.class ).getSingleResult() );
67+
var builder = (HibernateCriteriaBuilder) em.getCriteriaBuilder();
68+
var query = builder.createQuery( Boolean.class );
69+
query.select( builder.ilikeRegexp( builder.literal( "ABCDEF" ), "ab.*" ) );
70+
assertTrue( em.createQuery( query ).getSingleResult() );
71+
} );
72+
scope.inEntityManager( em -> {
73+
assertFalse( em.createQuery( "select not regexp_like('ABCDEF', 'ab.*', 'i')", Boolean.class ).getSingleResult() );
74+
assertFalse( em.createQuery( "select 'abcdef' not ilike regexp 'ab.*'", Boolean.class ).getSingleResult() );
75+
var builder = (HibernateCriteriaBuilder) em.getCriteriaBuilder();
76+
var query = builder.createQuery( Boolean.class );
77+
query.select( builder.notIlikeRegexp( builder.literal( "ABCDEF" ), "ab.*" ) );
78+
assertFalse( em.createQuery( query ).getSingleResult() );
5479
} );
5580
}
5681
}

0 commit comments

Comments
 (0)