|
From: <hib...@li...> - 2006-06-28 05:21:29
|
Author: ste...@jb...
Date: 2006-06-28 01:20:51 -0400 (Wed, 28 Jun 2006)
New Revision: 10061
Added:
trunk/Hibernate3/src/org/hibernate/criterion/LikeExpression.java
Modified:
trunk/Hibernate3/src/org/hibernate/criterion/Example.java
trunk/Hibernate3/test/org/hibernate/test/criteria/CriteriaQueryTest.java
Log:
HHH-1847 : added escape option for like operator in QBE (Scott Marlow)
Modified: trunk/Hibernate3/src/org/hibernate/criterion/Example.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/criterion/Example.java 2006-06-28 02:53:39 UTC (rev 10060)
+++ trunk/Hibernate3/src/org/hibernate/criterion/Example.java 2006-06-28 05:20:51 UTC (rev 10061)
@@ -36,6 +36,7 @@
private final Set excludedProperties = new HashSet();
private PropertySelector selector;
private boolean isLikeEnabled;
+ private Character escapeCharacter;
private boolean isIgnoreCaseEnabled;
private MatchMode matchMode;
@@ -85,6 +86,14 @@
}
/**
+ * Set escape character for "like" clause
+ */
+ public Example setEscapeCharacter(Character escapeCharacter) {
+ this.escapeCharacter = escapeCharacter;
+ return this;
+ }
+
+ /**
* Set the property selector
*/
public Example setPropertySelector(PropertySelector selector) {
@@ -300,8 +309,18 @@
Criterion crit;
if ( propertyValue!=null ) {
boolean isString = propertyValue instanceof String;
- String op = isLikeEnabled && isString ? " like " : "=";
- crit = new SimpleExpression( propertyName, propertyValue, op, isIgnoreCaseEnabled && isString );
+ if ( isLikeEnabled && isString ) {
+ crit = new LikeExpression(
+ propertyName,
+ ( String ) propertyValue,
+ matchMode,
+ escapeCharacter,
+ isIgnoreCaseEnabled
+ );
+ }
+ else {
+ crit = new SimpleExpression( propertyName, propertyValue, "=", isIgnoreCaseEnabled && isString );
+ }
}
else {
crit = new NullExpression(propertyName);
Added: trunk/Hibernate3/src/org/hibernate/criterion/LikeExpression.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/criterion/LikeExpression.java 2006-06-28 02:53:39 UTC (rev 10060)
+++ trunk/Hibernate3/src/org/hibernate/criterion/LikeExpression.java 2006-06-28 05:20:51 UTC (rev 10061)
@@ -0,0 +1,75 @@
+package org.hibernate.criterion;
+
+import org.hibernate.Criteria;
+import org.hibernate.HibernateException;
+import org.hibernate.dialect.Dialect;
+import org.hibernate.engine.TypedValue;
+
+/**
+ * A criterion representing a "like" expression
+ *
+ * @author Scott Marlow
+ * @author Steve Ebersole
+ */
+public class LikeExpression implements Criterion {
+ private final String propertyName;
+ private final Object value;
+ private final Character escapeChar;
+ private final boolean ignoreCase;
+
+ protected LikeExpression(
+ String propertyName,
+ String value,
+ Character escapeChar,
+ boolean ignoreCase) {
+ this.propertyName = propertyName;
+ this.value = value;
+ this.escapeChar = escapeChar;
+ this.ignoreCase = ignoreCase;
+ }
+
+ protected LikeExpression(
+ String propertyName,
+ String value) {
+ this( propertyName, value, null, false );
+ }
+
+ protected LikeExpression(
+ String propertyName,
+ String value,
+ MatchMode matchMode) {
+ this( propertyName, matchMode.toMatchString( value ) );
+ }
+
+ protected LikeExpression(
+ String propertyName,
+ String value,
+ MatchMode matchMode,
+ Character escapeChar,
+ boolean ignoreCase) {
+ this( propertyName, matchMode.toMatchString( value ), escapeChar, ignoreCase );
+ }
+
+ public String toSqlString(
+ Criteria criteria,
+ CriteriaQuery criteriaQuery) throws HibernateException {
+ Dialect dialect = criteriaQuery.getFactory().getDialect();
+ String[] columns = criteriaQuery.getColumnsUsingProjection( criteria, propertyName );
+ if ( columns.length != 1 ) {
+ throw new HibernateException( "Like may only be used with single-column properties" );
+ }
+ String lhs = ignoreCase
+ ? dialect.getLowercaseFunction() + '(' + columns[0] + ')'
+ : columns[0];
+ return lhs + " like ?" + ( escapeChar == null ? "" : " escape \'" + escapeChar + "\'" );
+
+ }
+
+ public TypedValue[] getTypedValues(
+ Criteria criteria,
+ CriteriaQuery criteriaQuery) throws HibernateException {
+ return new TypedValue[] {
+ criteriaQuery.getTypedValue( criteria, propertyName, value.toString().toLowerCase() )
+ };
+ }
+}
Modified: trunk/Hibernate3/test/org/hibernate/test/criteria/CriteriaQueryTest.java
===================================================================
--- trunk/Hibernate3/test/org/hibernate/test/criteria/CriteriaQueryTest.java 2006-06-28 02:53:39 UTC (rev 10060)
+++ trunk/Hibernate3/test/org/hibernate/test/criteria/CriteriaQueryTest.java 2006-06-28 05:20:51 UTC (rev 10061)
@@ -24,10 +24,10 @@
import org.hibernate.criterion.Property;
import org.hibernate.criterion.Restrictions;
import org.hibernate.criterion.Subqueries;
+import org.hibernate.criterion.Example;
import org.hibernate.test.TestCase;
import org.hibernate.test.hql.Animal;
import org.hibernate.test.hql.Reptile;
-import org.hibernate.transform.AliasToBeanResultTransformer;
import org.hibernate.transform.Transformers;
import org.hibernate.type.Type;
import org.hibernate.util.SerializationHelper;
@@ -40,7 +40,44 @@
public CriteriaQueryTest(String str) {
super(str);
}
-
+
+ public void testEscapeCharacter() {
+ Session session = openSession();
+ Transaction t = session.beginTransaction();
+ Course c1 = new Course();
+ c1.setCourseCode( "course-1" );
+ c1.setDescription( "%1" );
+ Course c2 = new Course();
+ c2.setCourseCode( "course-2" );
+ c2.setDescription( "%2" );
+ Course c3 = new Course();
+ c3.setCourseCode( "course-3" );
+ c3.setDescription( "control" );
+ session.persist( c1 );
+ session.persist( c2 );
+ session.persist( c3 );
+ session.flush();
+ session.clear();
+
+ // finds all courses which have a description equal to '%1'
+ Course example = new Course();
+ example.setDescription( "&%1" );
+ List result = session.createCriteria( Course.class )
+ .add( Example.create( example ).ignoreCase().enableLike().setEscapeCharacter( new Character( '&' ) ) )
+ .list();
+ assertEquals( 1, result.size() );
+ // finds all courses which contain '%' as the first char in the description
+ example.setDescription( "&%%" );
+ result = session.createCriteria( Course.class )
+ .add( Example.create( example ).ignoreCase().enableLike().setEscapeCharacter( new Character( '&' ) ) )
+ .list();
+ assertEquals( 2, result.size() );
+
+ session.createQuery( "delete Course" ).executeUpdate();
+ t.commit();
+ session.close();
+ }
+
public void testScrollCriteria() {
Session session = openSession();
Transaction t = session.beginTransaction();
|