HHH-14739 - Implement ILike support
Signed-off-by: Jan Schatteman <jschatte@redhat.com>
This commit is contained in:
parent
be485796b1
commit
0c1c469352
|
@ -212,6 +212,7 @@ LEAST : [lL] [eE] [aA] [sS] [tT];
|
|||
LEFT : [lL] [eE] [fF] [tT];
|
||||
LENGTH : [lL] [eE] [nN] [gG] [tT] [hH];
|
||||
LIKE : [lL] [iI] [kK] [eE];
|
||||
ILIKE : [iI] [lL] [iI] [kK] [eE];
|
||||
LIMIT : [lL] [iI] [mM] [iI] [tT];
|
||||
LIST : [lL] [iI] [sS] [tT];
|
||||
LN : [lL] [nN];
|
||||
|
|
|
@ -400,20 +400,20 @@ whereClause
|
|||
|
||||
predicate
|
||||
//highest to lowest precedence
|
||||
: LEFT_PAREN predicate RIGHT_PAREN # GroupedPredicate
|
||||
| expression IS (NOT)? NULL # IsNullPredicate
|
||||
| expression IS (NOT)? EMPTY # IsEmptyPredicate
|
||||
| expression (NOT)? IN inList # InPredicate
|
||||
| expression (NOT)? BETWEEN expression AND expression # BetweenPredicate
|
||||
| expression (NOT)? LIKE expression (likeEscape)? # LikePredicate
|
||||
| expression comparisonOperator expression # ComparisonPredicate
|
||||
: LEFT_PAREN predicate RIGHT_PAREN # GroupedPredicate
|
||||
| expression IS (NOT)? NULL # IsNullPredicate
|
||||
| expression IS (NOT)? EMPTY # IsEmptyPredicate
|
||||
| expression (NOT)? IN inList # InPredicate
|
||||
| expression (NOT)? BETWEEN expression AND expression # BetweenPredicate
|
||||
| expression (NOT)? (LIKE | ILIKE) expression (likeEscape)? # LikePredicate
|
||||
| expression comparisonOperator expression # ComparisonPredicate
|
||||
| EXISTS (ELEMENTS|INDICES) LEFT_PAREN dotIdentifierSequence RIGHT_PAREN # ExistsCollectionPartPredicate
|
||||
| EXISTS expression # ExistsPredicate
|
||||
| expression (NOT)? MEMBER OF path # MemberOfPredicate
|
||||
| NOT predicate # NegatedPredicate
|
||||
| predicate AND predicate # AndPredicate
|
||||
| predicate OR predicate # OrPredicate
|
||||
| expression # BooleanExpressionPredicate
|
||||
| EXISTSexpression # ExistsPredicate
|
||||
| expression (NOT)? MEMBER OF path # MemberOfPredicate
|
||||
| NOT predicate # NegatedPredicate
|
||||
| predicate AND predicate # AndPredicate
|
||||
| predicate OR predicate # OrPredicate
|
||||
| expression # BooleanExpressionPredicate
|
||||
;
|
||||
|
||||
comparisonOperator
|
||||
|
@ -973,6 +973,7 @@ identifier
|
|||
| HOUR
|
||||
| ID
|
||||
| IFNULL
|
||||
| ILIKE
|
||||
| IN
|
||||
| INDEX
|
||||
| INDICES
|
||||
|
|
|
@ -33,7 +33,6 @@ import javax.persistence.criteria.Subquery;
|
|||
import org.hibernate.query.NullPrecedence;
|
||||
import org.hibernate.query.SortOrder;
|
||||
import org.hibernate.metamodel.model.domain.DomainType;
|
||||
import org.hibernate.query.sqm.SqmExpressable;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
||||
|
||||
/**
|
||||
|
@ -621,6 +620,18 @@ public interface HibernateCriteriaBuilder extends CriteriaBuilder {
|
|||
@Override
|
||||
JpaPredicate like(Expression<String> x, String pattern, char escapeChar);
|
||||
|
||||
JpaPredicate ilike(Expression<String> x, Expression<String> pattern);
|
||||
|
||||
JpaPredicate ilike(Expression<String> x, String pattern);
|
||||
|
||||
JpaPredicate ilike(Expression<String> x, Expression<String> pattern, Expression<Character> escapeChar);
|
||||
|
||||
JpaPredicate ilike(Expression<String> x, Expression<String> pattern, char escapeChar);
|
||||
|
||||
JpaPredicate ilike(Expression<String> x, String pattern, Expression<Character> escapeChar);
|
||||
|
||||
JpaPredicate ilike(Expression<String> x, String pattern, char escapeChar);
|
||||
|
||||
@Override
|
||||
JpaPredicate notLike(Expression<String> x, Expression<String> pattern);
|
||||
|
||||
|
@ -639,6 +650,18 @@ public interface HibernateCriteriaBuilder extends CriteriaBuilder {
|
|||
@Override
|
||||
JpaPredicate notLike(Expression<String> x, String pattern, char escapeChar);
|
||||
|
||||
JpaPredicate notIlike(Expression<String> x, Expression<String> pattern);
|
||||
|
||||
JpaPredicate notIlike(Expression<String> x, String pattern);
|
||||
|
||||
JpaPredicate notIlike(Expression<String> x, Expression<String> pattern, Expression<Character> escapeChar);
|
||||
|
||||
JpaPredicate notIlike(Expression<String> x, Expression<String> pattern, char escapeChar);
|
||||
|
||||
JpaPredicate notIlike(Expression<String> x, String pattern, Expression<Character> escapeChar);
|
||||
|
||||
JpaPredicate notIlike(Expression<String> x, String pattern, char escapeChar);
|
||||
|
||||
@Override
|
||||
<T> JpaInPredicate<T> in(Expression<? extends T> expression);
|
||||
|
||||
|
|
|
@ -1972,12 +1972,15 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
public SqmPredicate visitLikePredicate(HqlParser.LikePredicateContext ctx) {
|
||||
final boolean negated = ( (TerminalNode) ctx.getChild( 1 ) ).getSymbol().getType() == HqlParser.NOT;
|
||||
final int startIndex = negated ? 3 : 2;
|
||||
final boolean caseSensitive = ( (TerminalNode) ctx.getChild( negated ? 2 : 1 ) ).getSymbol()
|
||||
.getType() == HqlParser.LIKE;
|
||||
if ( ctx.getChildCount() == startIndex + 2 ) {
|
||||
return new SqmLikePredicate(
|
||||
(SqmExpression<?>) ctx.getChild( 0 ).accept( this ),
|
||||
(SqmExpression<?>) ctx.getChild( startIndex ).accept( this ),
|
||||
(SqmExpression<?>) ctx.getChild( startIndex + 1 ).getChild( 1 ).accept( this ),
|
||||
negated,
|
||||
caseSensitive,
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
@ -1986,6 +1989,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
(SqmExpression<?>) ctx.getChild( 0 ).accept( this ),
|
||||
(SqmExpression<?>) ctx.getChild( startIndex ).accept( this ),
|
||||
negated,
|
||||
caseSensitive,
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1970,6 +1970,79 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext {
|
|||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPredicate ilike(Expression<String> searchString, Expression<String> pattern) {
|
||||
return new SqmLikePredicate(
|
||||
(SqmExpression) searchString,
|
||||
(SqmExpression) pattern,
|
||||
false,
|
||||
false,
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPredicate ilike(Expression<String> searchString, String pattern) {
|
||||
return new SqmLikePredicate(
|
||||
(SqmExpression) searchString,
|
||||
value( pattern, (SqmExpression) searchString ),
|
||||
false,
|
||||
false,
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPredicate ilike(
|
||||
Expression<String> searchString,
|
||||
Expression<String> pattern,
|
||||
Expression<Character> escapeChar) {
|
||||
return new SqmLikePredicate(
|
||||
(SqmExpression) searchString,
|
||||
(SqmExpression) pattern,
|
||||
(SqmExpression) escapeChar,
|
||||
false,
|
||||
false,
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPredicate ilike(Expression<String> searchString, Expression<String> pattern, char escapeChar) {
|
||||
return new SqmLikePredicate(
|
||||
(SqmExpression) searchString,
|
||||
(SqmExpression) pattern,
|
||||
literal( escapeChar ),
|
||||
false,
|
||||
false,
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPredicate ilike(Expression<String> searchString, String pattern, Expression<Character> escapeChar) {
|
||||
return new SqmLikePredicate(
|
||||
(SqmExpression) searchString,
|
||||
value( pattern, (SqmExpression) searchString ),
|
||||
(SqmExpression) escapeChar,
|
||||
false,
|
||||
false,
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPredicate ilike(Expression<String> searchString, String pattern, char escapeChar) {
|
||||
return new SqmLikePredicate(
|
||||
(SqmExpression) searchString,
|
||||
value( pattern, (SqmExpression) searchString ),
|
||||
literal( escapeChar ),
|
||||
false,
|
||||
false,
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPredicate notLike(Expression<String> x, Expression<String> pattern) {
|
||||
return not( like( x, pattern ) );
|
||||
|
@ -2000,6 +2073,36 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext {
|
|||
return not( like( x, pattern, escapeChar ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPredicate notIlike(Expression<String> x, Expression<String> pattern) {
|
||||
return not( ilike( x, pattern ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPredicate notIlike(Expression<String> x, String pattern) {
|
||||
return not( ilike( x, pattern ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPredicate notIlike(Expression<String> x, Expression<String> pattern, Expression<Character> escapeChar) {
|
||||
return not( ilike( x, pattern, escapeChar ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPredicate notIlike(Expression<String> x, Expression<String> pattern, char escapeChar) {
|
||||
return not( ilike( x, pattern, escapeChar ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPredicate notIlike(Expression<String> x, String pattern, Expression<Character> escapeChar) {
|
||||
return not( ilike( x, pattern, escapeChar ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPredicate notIlike(Expression<String> x, String pattern, char escapeChar) {
|
||||
return not( ilike( x, pattern, escapeChar ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> SqmInPredicate<T> in(Expression<? extends T> expression) {
|
||||
|
|
|
@ -838,8 +838,9 @@ public class SqmTreePrinter implements SemanticQueryWalker<Object> {
|
|||
|
||||
@Override
|
||||
public Object visitLikePredicate(SqmLikePredicate predicate) {
|
||||
final String likeType = predicate.isCaseSensitive() ? "like" : "ilike";
|
||||
processStanza(
|
||||
predicate.isNegated() ? "is-not-like" : "is-like",
|
||||
( predicate.isNegated() ? "is-not-" : "is-" ) + likeType,
|
||||
() -> {
|
||||
predicate.getPattern().accept( this );
|
||||
predicate.getMatchExpression().accept( this );
|
||||
|
|
|
@ -4468,7 +4468,8 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
(Expression) predicate.getMatchExpression().accept( this ),
|
||||
(Expression) predicate.getPattern().accept( this ),
|
||||
escapeExpression,
|
||||
predicate.isNegated()
|
||||
predicate.isNegated(),
|
||||
predicate.isCaseSensitive()
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ public class SqmLikePredicate extends AbstractNegatableSqmPredicate {
|
|||
private final SqmExpression<?> matchExpression;
|
||||
private final SqmExpression<?> pattern;
|
||||
private final SqmExpression<?> escapeCharacter;
|
||||
private final boolean isCaseSensitive;
|
||||
|
||||
public SqmLikePredicate(
|
||||
SqmExpression<?> matchExpression,
|
||||
|
@ -26,17 +27,27 @@ public class SqmLikePredicate extends AbstractNegatableSqmPredicate {
|
|||
this( matchExpression, pattern, escapeCharacter, false, nodeBuilder );
|
||||
}
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public SqmLikePredicate(
|
||||
SqmExpression<?> matchExpression,
|
||||
SqmExpression<?> pattern,
|
||||
SqmExpression<?> escapeCharacter,
|
||||
boolean negated,
|
||||
NodeBuilder nodeBuilder) {
|
||||
this( matchExpression, pattern, escapeCharacter, negated, true, nodeBuilder );
|
||||
}
|
||||
|
||||
public SqmLikePredicate(
|
||||
SqmExpression<?> matchExpression,
|
||||
SqmExpression<?> pattern,
|
||||
SqmExpression<?> escapeCharacter,
|
||||
boolean negated,
|
||||
boolean isCaseSensitive,
|
||||
NodeBuilder nodeBuilder) {
|
||||
super( negated, nodeBuilder );
|
||||
this.matchExpression = matchExpression;
|
||||
this.pattern = pattern;
|
||||
this.escapeCharacter = escapeCharacter;
|
||||
this.isCaseSensitive = isCaseSensitive;
|
||||
}
|
||||
|
||||
public SqmLikePredicate(
|
||||
|
@ -50,8 +61,9 @@ public class SqmLikePredicate extends AbstractNegatableSqmPredicate {
|
|||
SqmExpression<?> matchExpression,
|
||||
SqmExpression<?> pattern,
|
||||
boolean negated,
|
||||
boolean isCaseSensitive,
|
||||
NodeBuilder nodeBuilder) {
|
||||
this( matchExpression, pattern, null, negated, nodeBuilder );
|
||||
this( matchExpression, pattern, null, negated, isCaseSensitive, nodeBuilder );
|
||||
}
|
||||
|
||||
public SqmExpression<?> getMatchExpression() {
|
||||
|
@ -66,6 +78,10 @@ public class SqmLikePredicate extends AbstractNegatableSqmPredicate {
|
|||
return escapeCharacter;
|
||||
}
|
||||
|
||||
public boolean isCaseSensitive() {
|
||||
return isCaseSensitive;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(SemanticQueryWalker<T> walker) {
|
||||
return walker.visitLikePredicate( this );
|
||||
|
|
|
@ -4562,15 +4562,60 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
|
|||
|
||||
@Override
|
||||
public void visitLikePredicate(LikePredicate likePredicate) {
|
||||
likePredicate.getMatchExpression().accept( this );
|
||||
if ( likePredicate.isNegated() ) {
|
||||
appendSql( " not" );
|
||||
if ( likePredicate.isCaseSensitive() ) {
|
||||
|
||||
likePredicate.getMatchExpression().accept( this );
|
||||
if ( likePredicate.isNegated() ) {
|
||||
appendSql( " not" );
|
||||
}
|
||||
appendSql( " like " );
|
||||
likePredicate.getPattern().accept( this );
|
||||
if ( likePredicate.getEscapeCharacter() != null ) {
|
||||
appendSql( " escape " );
|
||||
likePredicate.getEscapeCharacter().accept( this );
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
if (dialect.supportsCaseInsensitiveLike()) {
|
||||
|
||||
likePredicate.getMatchExpression().accept( this );
|
||||
if ( likePredicate.isNegated() ) {
|
||||
appendSql( " not" );
|
||||
}
|
||||
appendSql( " " );
|
||||
appendSql( dialect.getCaseInsensitiveLike() );
|
||||
appendSql( " " );
|
||||
likePredicate.getPattern().accept( this );
|
||||
if ( likePredicate.getEscapeCharacter() != null ) {
|
||||
appendSql( " escape " );
|
||||
likePredicate.getEscapeCharacter().accept( this );
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
renderCaseInsensitiveLikeEmulation(likePredicate.getMatchExpression(), likePredicate.getPattern(), likePredicate.getEscapeCharacter(), likePredicate.isNegated());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
protected void renderCaseInsensitiveLikeEmulation(Expression lhs, Expression rhs, Expression escapeCharacter, boolean negated) {
|
||||
//LOWER(lhs) operator LOWER(rhs)
|
||||
appendSql( " " );
|
||||
appendSql( dialect.getLowercaseFunction() );
|
||||
appendSql( "( ");
|
||||
lhs.accept( this );
|
||||
appendSql( " )" );
|
||||
appendSql( negated ? " not" : "" );
|
||||
appendSql( " like " );
|
||||
likePredicate.getPattern().accept( this );
|
||||
if ( likePredicate.getEscapeCharacter() != null ) {
|
||||
appendSql( dialect.getLowercaseFunction() );
|
||||
appendSql( "( " );
|
||||
rhs.accept( this );
|
||||
appendSql( " ) " );
|
||||
if ( escapeCharacter != null ) {
|
||||
appendSql( " escape " );
|
||||
likePredicate.getEscapeCharacter().accept( this );
|
||||
escapeCharacter.accept( this );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ public class LikePredicate implements Predicate {
|
|||
private final Expression pattern;
|
||||
private final Expression escapeCharacter;
|
||||
private final boolean negated;
|
||||
private final boolean isCaseSensitive;
|
||||
|
||||
public LikePredicate(
|
||||
Expression matchExpression,
|
||||
|
@ -28,11 +29,22 @@ public class LikePredicate implements Predicate {
|
|||
public LikePredicate(
|
||||
Expression matchExpression,
|
||||
Expression pattern,
|
||||
Expression escapeCharacter, boolean negated) {
|
||||
Expression escapeCharacter,
|
||||
boolean negated) {
|
||||
this( matchExpression, pattern, escapeCharacter, negated, true );
|
||||
}
|
||||
|
||||
public LikePredicate(
|
||||
Expression matchExpression,
|
||||
Expression pattern,
|
||||
Expression escapeCharacter,
|
||||
boolean negated,
|
||||
boolean isCaseSensitive) {
|
||||
this.matchExpression = matchExpression;
|
||||
this.pattern = pattern;
|
||||
this.escapeCharacter = escapeCharacter;
|
||||
this.negated = negated;
|
||||
this.isCaseSensitive = isCaseSensitive;
|
||||
}
|
||||
|
||||
public LikePredicate(Expression matchExpression, Expression pattern) {
|
||||
|
@ -55,6 +67,10 @@ public class LikePredicate implements Predicate {
|
|||
return negated;
|
||||
}
|
||||
|
||||
public boolean isCaseSensitive() {
|
||||
return isCaseSensitive;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return false;
|
||||
|
|
|
@ -0,0 +1,278 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.orm.test.query.hql;
|
||||
|
||||
import java.util.List;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.Root;
|
||||
|
||||
import org.hibernate.query.Query;
|
||||
import org.hibernate.query.criteria.HibernateCriteriaBuilder;
|
||||
|
||||
import org.hibernate.testing.orm.domain.StandardDomainModel;
|
||||
import org.hibernate.testing.orm.domain.gambit.BasicEntity;
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.ServiceRegistry;
|
||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
/**
|
||||
* @author Jan Schatteman
|
||||
*/
|
||||
@ServiceRegistry
|
||||
@DomainModel(
|
||||
standardModels = StandardDomainModel.GAMBIT
|
||||
)
|
||||
@SessionFactory
|
||||
public class ILikeCriteriaTest {
|
||||
|
||||
@BeforeEach
|
||||
public void prepareData(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
em -> {
|
||||
BasicEntity be1 = new BasicEntity(1, "Product_one");
|
||||
em.persist( be1 );
|
||||
BasicEntity be2 = new BasicEntity(2, "proDUct two");
|
||||
em.persist( be2 );
|
||||
BasicEntity be3 = new BasicEntity(3, "Product three");
|
||||
em.persist( be3 );
|
||||
BasicEntity be4 = new BasicEntity(4, "pROducT four");
|
||||
em.persist( be4 );
|
||||
BasicEntity be5 = new BasicEntity(5, "Product five");
|
||||
em.persist( be5 );
|
||||
BasicEntity be6 = new BasicEntity(6, "Prodact six");
|
||||
em.persist( be6 );
|
||||
BasicEntity be7 = new BasicEntity(7, "prodACt seven");
|
||||
em.persist( be7 );
|
||||
BasicEntity be8 = new BasicEntity(8, "Prod_act eight");
|
||||
em.persist( be8 );
|
||||
BasicEntity be9 = new BasicEntity(9, "prod_ACt nine");
|
||||
em.persist( be9 );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void tearDown(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> session.createQuery( "delete from BasicEntity" ).executeUpdate()
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLike(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
HibernateCriteriaBuilder cb = session.getCriteriaBuilder();
|
||||
CriteriaQuery cq = cb.createQuery( BasicEntity.class);
|
||||
Root<BasicEntity> from = cq.from( BasicEntity.class );
|
||||
|
||||
cq.where( cb.like( from.get( "data" ), "Prod%" ) );
|
||||
Query q = session.createQuery( cq );
|
||||
List l = q.getResultList();
|
||||
assertEquals( 5, l.size() );
|
||||
|
||||
cq.where( cb.like( from.get( "data" ), cb.literal( "Prod%" ) ) );
|
||||
q = session.createQuery( cq );
|
||||
l = q.getResultList();
|
||||
assertEquals( 5, l.size() );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLikeEscape(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
HibernateCriteriaBuilder cb = session.getCriteriaBuilder();
|
||||
CriteriaQuery cq = cb.createQuery( BasicEntity.class);
|
||||
Root<BasicEntity> from = cq.from( BasicEntity.class );
|
||||
|
||||
cq.where( cb.like( from.get( "data" ), cb.literal( "Prod%" ), cb.literal( '$' ) ) );
|
||||
Query q = session.createQuery( cq );
|
||||
List l = q.getResultList();
|
||||
assertEquals( 5, l.size() );
|
||||
|
||||
cq.where( cb.like( from.get( "data" ), cb.literal( "Prod%" ), '$' ) );
|
||||
q = session.createQuery( cq );
|
||||
l = q.getResultList();
|
||||
assertEquals( 5, l.size() );
|
||||
|
||||
cq.where( cb.like( from.get( "data" ), "Prod%", cb.literal( '$' ) ) );
|
||||
q = session.createQuery( cq );
|
||||
l = q.getResultList();
|
||||
assertEquals( 5, l.size() );
|
||||
|
||||
cq.where( cb.like( from.get( "data" ), "Prod%", '$' ) );
|
||||
q = session.createQuery( cq );
|
||||
l = q.getResultList();
|
||||
assertEquals( 5, l.size() );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotLike(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
HibernateCriteriaBuilder cb = session.getCriteriaBuilder();
|
||||
CriteriaQuery cq = cb.createQuery( BasicEntity.class);
|
||||
Root<BasicEntity> from = cq.from( BasicEntity.class );
|
||||
|
||||
cq.where( cb.notLike( from.get( "data" ), "Prod%" ) );
|
||||
Query q = session.createQuery( cq );
|
||||
List l = q.getResultList();
|
||||
assertEquals( 4, l.size() );
|
||||
|
||||
cq.where( cb.notLike( from.get( "data" ), cb.literal( "Prod%" ) ) );
|
||||
q = session.createQuery( cq );
|
||||
l = q.getResultList();
|
||||
assertEquals( 4, l.size() );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotLikeEscape(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
HibernateCriteriaBuilder cb = session.getCriteriaBuilder();
|
||||
CriteriaQuery cq = cb.createQuery( BasicEntity.class);
|
||||
Root<BasicEntity> from = cq.from( BasicEntity.class );
|
||||
|
||||
cq.where( cb.notLike( from.get( "data" ), cb.literal( "Pr%$_%" ), cb.literal( '$' ) ) );
|
||||
Query q = session.createQuery( cq );
|
||||
List l = q.getResultList();
|
||||
assertEquals( 7, l.size() );
|
||||
|
||||
cq.where( cb.notLike( from.get( "data" ), cb.literal( "Pr%$_%" ), '$' ) );
|
||||
q = session.createQuery( cq );
|
||||
l = q.getResultList();
|
||||
assertEquals( 7, l.size() );
|
||||
|
||||
cq.where( cb.notLike( from.get( "data" ), "Pr%$_%", cb.literal( '$' ) ) );
|
||||
q = session.createQuery( cq );
|
||||
l = q.getResultList();
|
||||
assertEquals( 7, l.size() );
|
||||
|
||||
cq.where( cb.notLike( from.get( "data" ), "Pr%$_%", '$' ) );
|
||||
q = session.createQuery( cq );
|
||||
l = q.getResultList();
|
||||
assertEquals( 7, l.size() );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIlike(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
HibernateCriteriaBuilder cb = session.getCriteriaBuilder();
|
||||
CriteriaQuery cq = cb.createQuery( BasicEntity.class);
|
||||
Root<BasicEntity> from = cq.from( BasicEntity.class );
|
||||
|
||||
cq.where( cb.ilike( from.get( "data" ), "Produ%" ) );
|
||||
Query q = session.createQuery( cq );
|
||||
List l = q.getResultList();
|
||||
assertEquals( 5, l.size() );
|
||||
|
||||
cq.where( cb.ilike( from.get( "data" ), cb.literal( "Produ%" ) ) );
|
||||
q = session.createQuery( cq );
|
||||
l = q.getResultList();
|
||||
assertEquals( 5, l.size() );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIlikeEscape(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
HibernateCriteriaBuilder cb = session.getCriteriaBuilder();
|
||||
CriteriaQuery cq = cb.createQuery( BasicEntity.class);
|
||||
Root<BasicEntity> from = cq.from( BasicEntity.class );
|
||||
|
||||
cq.where( cb.ilike( from.get( "data" ), cb.literal( "Pr%$_%" ), cb.literal( '$' ) ) );
|
||||
Query q = session.createQuery( cq );
|
||||
List l = q.getResultList();
|
||||
assertEquals( 3, l.size() );
|
||||
|
||||
cq.where( cb.ilike( from.get( "data" ), cb.literal( "Pr%$_%" ), '$' ) );
|
||||
q = session.createQuery( cq );
|
||||
l = q.getResultList();
|
||||
assertEquals( 3, l.size() );
|
||||
|
||||
cq.where( cb.ilike( from.get( "data" ), "Pr%$_%", cb.literal( '$' ) ) );
|
||||
q = session.createQuery( cq );
|
||||
l = q.getResultList();
|
||||
assertEquals( 3, l.size() );
|
||||
|
||||
cq.where( cb.ilike( from.get( "data" ), "Pr%$_%", '$' ) );
|
||||
q = session.createQuery( cq );
|
||||
l = q.getResultList();
|
||||
assertEquals( 3, l.size() );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotIlike(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
HibernateCriteriaBuilder cb = session.getCriteriaBuilder();
|
||||
CriteriaQuery cq = cb.createQuery( BasicEntity.class);
|
||||
Root<BasicEntity> from = cq.from( BasicEntity.class );
|
||||
|
||||
cq.where( cb.notIlike( from.get( "data" ), "Produ%" ) );
|
||||
Query q = session.createQuery( cq );
|
||||
List l = q.getResultList();
|
||||
assertEquals( 4, l.size() );
|
||||
|
||||
cq.where( cb.notIlike( from.get( "data" ), cb.literal( "Produ%" ) ) );
|
||||
q = session.createQuery( cq );
|
||||
l = q.getResultList();
|
||||
assertEquals( 4, l.size() );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotIlikeEscape(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
HibernateCriteriaBuilder cb = session.getCriteriaBuilder();
|
||||
CriteriaQuery cq = cb.createQuery( BasicEntity.class);
|
||||
Root<BasicEntity> from = cq.from( BasicEntity.class );
|
||||
|
||||
cq.where( cb.notIlike( from.get( "data" ), cb.literal( "Pr%$_%" ), cb.literal( '$' ) ) );
|
||||
Query q = session.createQuery( cq );
|
||||
List l = q.getResultList();
|
||||
assertEquals( 6, l.size() );
|
||||
|
||||
cq.where( cb.notIlike( from.get( "data" ), cb.literal( "Pr%$_%" ), '$' ) );
|
||||
q = session.createQuery( cq );
|
||||
l = q.getResultList();
|
||||
assertEquals( 6, l.size() );
|
||||
|
||||
cq.where( cb.notIlike( from.get( "data" ), "Pr%$_%", cb.literal( '$' ) ) );
|
||||
q = session.createQuery( cq );
|
||||
l = q.getResultList();
|
||||
assertEquals( 6, l.size() );
|
||||
|
||||
cq.where( cb.notIlike( from.get( "data" ), "Pr%$_%", '$' ) );
|
||||
q = session.createQuery( cq );
|
||||
l = q.getResultList();
|
||||
assertEquals( 6, l.size() );
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,156 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.orm.test.query.hql;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.query.Query;
|
||||
|
||||
import org.hibernate.testing.orm.domain.StandardDomainModel;
|
||||
import org.hibernate.testing.orm.domain.gambit.BasicEntity;
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.ServiceRegistry;
|
||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
/**
|
||||
* @author Jan Schatteman
|
||||
*/
|
||||
@ServiceRegistry
|
||||
@DomainModel(
|
||||
standardModels = StandardDomainModel.GAMBIT
|
||||
)
|
||||
@SessionFactory
|
||||
public class ILikeTest {
|
||||
|
||||
@BeforeEach
|
||||
public void prepareData(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
em -> {
|
||||
BasicEntity be1 = new BasicEntity(1, "Product_one");
|
||||
em.persist( be1 );
|
||||
BasicEntity be2 = new BasicEntity(2, "proDUct two");
|
||||
em.persist( be2 );
|
||||
BasicEntity be3 = new BasicEntity(3, "Product three");
|
||||
em.persist( be3 );
|
||||
BasicEntity be4 = new BasicEntity(4, "pROducT four");
|
||||
em.persist( be4 );
|
||||
BasicEntity be5 = new BasicEntity(5, "Product five");
|
||||
em.persist( be5 );
|
||||
BasicEntity be6 = new BasicEntity(6, "Prodact six");
|
||||
em.persist( be6 );
|
||||
BasicEntity be7 = new BasicEntity(7, "prodACt seven");
|
||||
em.persist( be7 );
|
||||
BasicEntity be8 = new BasicEntity(8, "Prod_act eight");
|
||||
em.persist( be8 );
|
||||
BasicEntity be9 = new BasicEntity(9, "prod_ACt nine");
|
||||
em.persist( be9 );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void tearDown(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> session.createQuery( "delete from BasicEntity" ).executeUpdate()
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLike(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
Query q = session.createQuery( "from BasicEntity be where be.data like 'Prod%'" );
|
||||
List l = q.getResultList();
|
||||
assertEquals( 5, l.size() );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotLike(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
Query q = session.createQuery( "from BasicEntity be where be.data not like 'Prod%'" );
|
||||
List l = q.getResultList();
|
||||
assertEquals( 4, l.size() );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLikeEscape(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
Query q = session.createQuery( "from BasicEntity be where be.data like 'Pr%$_%' escape '$'" );
|
||||
List l = q.getResultList();
|
||||
assertEquals( 2, l.size() );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotLikeEscape(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
Query q = session.createQuery( "from BasicEntity be where be.data not like 'Pr%$_%' escape '$'" );
|
||||
List l = q.getResultList();
|
||||
assertEquals( 7, l.size() );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIlike(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
Query q = session.createQuery( "from BasicEntity be where be.data ilike 'Produ%'" );
|
||||
List l = q.getResultList();
|
||||
assertEquals( 5, l.size() );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotIlike(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
Query q = session.createQuery( "from BasicEntity be where be.data not ilike 'Produ%'" );
|
||||
List l = q.getResultList();
|
||||
assertEquals( 4, l.size() );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIlikeEscape(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
Query q = session.createQuery( "from BasicEntity be where be.data ilike 'Pr%$_%' escape '$'" );
|
||||
List l = q.getResultList();
|
||||
assertEquals( 3, l.size() );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotIlikeEscape(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
Query q = session.createQuery( "from BasicEntity be where be.data not ilike 'Pr%$_%' escape '$'" );
|
||||
List l = q.getResultList();
|
||||
assertEquals( 6, l.size() );
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue