HHH-17773 case-insensitive ordering
This commit is contained in:
parent
d0f3cdeb96
commit
484fcb2984
|
@ -40,6 +40,7 @@ public class Order<X> {
|
|||
private final String attributeName;
|
||||
private final NullPrecedence nullPrecedence;
|
||||
private final int element;
|
||||
private final boolean ignoreCase;
|
||||
|
||||
private Order(SortDirection order, NullPrecedence nullPrecedence, SingularAttribute<X, ?> attribute) {
|
||||
this.order = order;
|
||||
|
@ -48,6 +49,17 @@ public class Order<X> {
|
|||
this.entityClass = attribute.getDeclaringType().getJavaType();
|
||||
this.nullPrecedence = nullPrecedence;
|
||||
this.element = 1;
|
||||
this.ignoreCase = false;
|
||||
}
|
||||
|
||||
private Order(SortDirection order, NullPrecedence nullPrecedence, SingularAttribute<X, ?> attribute, boolean ignoreCase) {
|
||||
this.order = order;
|
||||
this.attribute = attribute;
|
||||
this.attributeName = attribute.getName();
|
||||
this.entityClass = attribute.getDeclaringType().getJavaType();
|
||||
this.nullPrecedence = nullPrecedence;
|
||||
this.element = 1;
|
||||
this.ignoreCase = ignoreCase;
|
||||
}
|
||||
|
||||
private Order(SortDirection order, NullPrecedence nullPrecedence, Class<X> entityClass, String attributeName) {
|
||||
|
@ -57,6 +69,7 @@ public class Order<X> {
|
|||
this.attribute = null;
|
||||
this.nullPrecedence = nullPrecedence;
|
||||
this.element = 1;
|
||||
this.ignoreCase = false;
|
||||
}
|
||||
|
||||
private Order(SortDirection order, NullPrecedence nullPrecedence, int element) {
|
||||
|
@ -66,6 +79,17 @@ public class Order<X> {
|
|||
this.attribute = null;
|
||||
this.nullPrecedence = nullPrecedence;
|
||||
this.element = element;
|
||||
this.ignoreCase = false;
|
||||
}
|
||||
|
||||
private Order(SortDirection order, NullPrecedence nullPrecedence, Class<X> entityClass, String attributeName, boolean ignoreCase) {
|
||||
this.order = order;
|
||||
this.entityClass = entityClass;
|
||||
this.attributeName = attributeName;
|
||||
this.attribute = null;
|
||||
this.nullPrecedence = nullPrecedence;
|
||||
this.element = 1;
|
||||
this.ignoreCase = ignoreCase;
|
||||
}
|
||||
|
||||
public static <T> Order<T> asc(SingularAttribute<T,?> attribute) {
|
||||
|
@ -80,6 +104,10 @@ public class Order<X> {
|
|||
return new Order<>(direction, NullPrecedence.NONE, attribute);
|
||||
}
|
||||
|
||||
public static <T> Order<T> by(SingularAttribute<T,?> attribute, SortDirection direction, boolean ignoreCase) {
|
||||
return new Order<>(direction, NullPrecedence.NONE, attribute, ignoreCase);
|
||||
}
|
||||
|
||||
public static <T> Order<T> by(SingularAttribute<T,?> attribute, SortDirection direction, NullPrecedence nullPrecedence) {
|
||||
return new Order<>(direction, nullPrecedence, attribute);
|
||||
}
|
||||
|
@ -96,6 +124,10 @@ public class Order<X> {
|
|||
return new Order<>( direction, NullPrecedence.NONE, entityClass, attributeName );
|
||||
}
|
||||
|
||||
public static <T> Order<T> by(Class<T> entityClass, String attributeName, SortDirection direction, boolean ignoreCase) {
|
||||
return new Order<>( direction, NullPrecedence.NONE, entityClass, attributeName, ignoreCase );
|
||||
}
|
||||
|
||||
public static <T> Order<T> by(Class<T> entityClass, String attributeName, SortDirection direction, NullPrecedence nullPrecedence) {
|
||||
return new Order<>( direction, nullPrecedence, entityClass, attributeName );
|
||||
}
|
||||
|
@ -124,6 +156,10 @@ public class Order<X> {
|
|||
return nullPrecedence;
|
||||
}
|
||||
|
||||
public boolean isCaseInsensitive() {
|
||||
return ignoreCase;
|
||||
}
|
||||
|
||||
public SingularAttribute<X, ?> getAttribute() {
|
||||
return attribute;
|
||||
}
|
||||
|
|
|
@ -1001,6 +1001,7 @@ public interface HibernateCriteriaBuilder extends CriteriaBuilder {
|
|||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Ordering
|
||||
|
||||
JpaOrder sort(JpaExpression<?> sortExpression, SortDirection sortOrder, NullPrecedence nullPrecedence, boolean ignoreCase);
|
||||
JpaOrder sort(JpaExpression<?> sortExpression, SortDirection sortOrder, NullPrecedence nullPrecedence);
|
||||
JpaOrder sort(JpaExpression<?> sortExpression, SortDirection sortOrder);
|
||||
JpaOrder sort(JpaExpression<?> sortExpression);
|
||||
|
|
|
@ -58,7 +58,6 @@ import org.hibernate.query.criteria.JpaWindow;
|
|||
import org.hibernate.query.criteria.JpaWindowFrame;
|
||||
import org.hibernate.query.NullPrecedence;
|
||||
import org.hibernate.query.sqm.TemporalUnit;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
||||
|
||||
import jakarta.persistence.Tuple;
|
||||
import jakarta.persistence.criteria.CollectionJoin;
|
||||
|
@ -1210,6 +1209,11 @@ public class HibernateCriteriaBuilderDelegate implements HibernateCriteriaBuilde
|
|||
return criteriaBuilder.sort( sortExpression, sortOrder, nullPrecedence );
|
||||
}
|
||||
|
||||
@Override
|
||||
public JpaOrder sort(JpaExpression<?> sortExpression, SortDirection sortOrder, NullPrecedence nullPrecedence, boolean ignoreCase) {
|
||||
return criteriaBuilder.sort( sortExpression, sortOrder, nullPrecedence, ignoreCase );
|
||||
}
|
||||
|
||||
@Override
|
||||
public JpaOrder sort(JpaExpression<?> sortExpression, SortDirection sortOrder) {
|
||||
return criteriaBuilder.sort( sortExpression, sortOrder );
|
||||
|
|
|
@ -1022,6 +1022,13 @@ public interface NodeBuilder extends HibernateCriteriaBuilder {
|
|||
SortDirection sortOrder,
|
||||
NullPrecedence nullPrecedence);
|
||||
|
||||
@Override
|
||||
SqmSortSpecification sort(
|
||||
JpaExpression<?> sortExpression,
|
||||
SortDirection sortOrder,
|
||||
NullPrecedence nullPrecedence,
|
||||
boolean ignoreCase);
|
||||
|
||||
@Override
|
||||
SqmSortSpecification sort(JpaExpression<?> sortExpression, SortDirection sortOrder);
|
||||
|
||||
|
|
|
@ -548,6 +548,11 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
return new SqmSortSpecification( (SqmExpression<?>) sortExpression, sortOrder, nullPrecedence );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmSortSpecification sort(JpaExpression<?> sortExpression, SortDirection sortOrder, NullPrecedence nullPrecedence, boolean ignoreCase) {
|
||||
return new SqmSortSpecification( (SqmExpression<?>) sortExpression, sortOrder, nullPrecedence, ignoreCase );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmSortSpecification sort(JpaExpression<?> sortExpression, SortDirection sortOrder) {
|
||||
return new SqmSortSpecification( (SqmExpression<?>) sortExpression, sortOrder );
|
||||
|
|
|
@ -592,7 +592,7 @@ public class SqmUtil {
|
|||
throw new IllegalQueryOperationException("Select item was of wrong entity type");
|
||||
}
|
||||
final SqmPath<Object> path = root.get( order.getAttributeName() );
|
||||
return builder.sort( path, order.getDirection(), order.getNullPrecedence() );
|
||||
return builder.sort( path, order.getDirection(), order.getNullPrecedence(), order.isCaseInsensitive() );
|
||||
}
|
||||
else {
|
||||
throw new IllegalQueryOperationException("Select item was not an entity type");
|
||||
|
|
|
@ -2541,7 +2541,8 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
return new SortSpecification(
|
||||
expression,
|
||||
sortSpecification.getSortDirection(),
|
||||
sortSpecification.getNullPrecedence()
|
||||
sortSpecification.getNullPrecedence(),
|
||||
sortSpecification.isIgnoreCase()
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -21,19 +21,28 @@ import java.util.Objects;
|
|||
public class SqmSortSpecification implements JpaOrder {
|
||||
private final SqmExpression sortExpression;
|
||||
private final SortDirection sortOrder;
|
||||
|
||||
private final boolean ignoreCase;
|
||||
private NullPrecedence nullPrecedence;
|
||||
|
||||
public SqmSortSpecification(
|
||||
SqmExpression sortExpression,
|
||||
SortDirection sortOrder,
|
||||
NullPrecedence nullPrecedence) {
|
||||
this( sortExpression, sortOrder, nullPrecedence, false );
|
||||
}
|
||||
|
||||
public SqmSortSpecification(
|
||||
SqmExpression sortExpression,
|
||||
SortDirection sortOrder,
|
||||
NullPrecedence nullPrecedence,
|
||||
boolean ignoreCase) {
|
||||
assert sortExpression != null;
|
||||
assert sortOrder != null;
|
||||
assert nullPrecedence != null;
|
||||
this.sortExpression = sortExpression;
|
||||
this.sortOrder = sortOrder;
|
||||
this.nullPrecedence = nullPrecedence;
|
||||
this.ignoreCase = ignoreCase;
|
||||
}
|
||||
|
||||
public SqmSortSpecification(SqmExpression sortExpression) {
|
||||
|
@ -45,7 +54,7 @@ public class SqmSortSpecification implements JpaOrder {
|
|||
}
|
||||
|
||||
public SqmSortSpecification copy(SqmCopyContext context) {
|
||||
return new SqmSortSpecification( sortExpression.copy( context ), sortOrder, nullPrecedence );
|
||||
return new SqmSortSpecification( sortExpression.copy( context ), sortOrder, nullPrecedence, ignoreCase );
|
||||
}
|
||||
|
||||
public SqmExpression<?> getSortExpression() {
|
||||
|
@ -57,6 +66,10 @@ public class SqmSortSpecification implements JpaOrder {
|
|||
return sortOrder;
|
||||
}
|
||||
|
||||
public boolean isIgnoreCase() {
|
||||
return ignoreCase;
|
||||
}
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// JPA
|
||||
|
@ -75,7 +88,7 @@ public class SqmSortSpecification implements JpaOrder {
|
|||
@Override
|
||||
public JpaOrder reverse() {
|
||||
SortDirection newSortOrder = this.sortOrder == null ? SortDirection.DESCENDING : sortOrder.reverse();
|
||||
return new SqmSortSpecification( sortExpression, newSortOrder, nullPrecedence );
|
||||
return new SqmSortSpecification( sortExpression, newSortOrder, nullPrecedence, ignoreCase );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -4370,21 +4370,26 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
|
|||
final Expression sortExpression = sortSpecification.getSortExpression();
|
||||
final NullPrecedence nullPrecedence = sortSpecification.getNullPrecedence();
|
||||
final SortDirection sortOrder = sortSpecification.getSortOrder();
|
||||
final boolean ignoreCase = sortSpecification.isIgnoreCase();
|
||||
final SqlTuple sqlTuple = SqlTupleContainer.getSqlTuple( sortExpression );
|
||||
if ( sqlTuple != null ) {
|
||||
String separator = NO_SEPARATOR;
|
||||
for ( Expression expression : sqlTuple.getExpressions() ) {
|
||||
appendSql( separator );
|
||||
visitSortSpecification( expression, sortOrder, nullPrecedence );
|
||||
visitSortSpecification( expression, sortOrder, nullPrecedence, ignoreCase );
|
||||
separator = COMMA_SEPARATOR;
|
||||
}
|
||||
}
|
||||
else {
|
||||
visitSortSpecification( sortExpression, sortOrder, nullPrecedence );
|
||||
visitSortSpecification( sortExpression, sortOrder, nullPrecedence, ignoreCase );
|
||||
}
|
||||
}
|
||||
|
||||
protected void visitSortSpecification(Expression sortExpression, SortDirection sortOrder, NullPrecedence nullPrecedence) {
|
||||
protected void visitSortSpecification(
|
||||
Expression sortExpression,
|
||||
SortDirection sortOrder,
|
||||
NullPrecedence nullPrecedence,
|
||||
boolean ignoreCase) {
|
||||
if ( nullPrecedence == null || nullPrecedence == NullPrecedence.NONE ) {
|
||||
nullPrecedence = sessionFactory.getSessionFactoryOptions().getDefaultNullPrecedence();
|
||||
}
|
||||
|
@ -4395,6 +4400,10 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
|
|||
emulateSortSpecificationNullPrecedence( sortExpression, nullPrecedence );
|
||||
}
|
||||
|
||||
if ( ignoreCase ) {
|
||||
appendSql("lower(");
|
||||
}
|
||||
|
||||
if ( inOverOrWithinGroupClause() ) {
|
||||
resolveAliasedExpression( sortExpression ).accept( this );
|
||||
}
|
||||
|
@ -4402,6 +4411,10 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
|
|||
sortExpression.accept( this );
|
||||
}
|
||||
|
||||
if ( ignoreCase ) {
|
||||
appendSql(")");
|
||||
}
|
||||
|
||||
if ( sortOrder == SortDirection.DESCENDING ) {
|
||||
appendSql( " desc" );
|
||||
}
|
||||
|
|
|
@ -19,18 +19,24 @@ public class SortSpecification implements SqlAstNode {
|
|||
private final Expression sortExpression;
|
||||
private final SortDirection sortOrder;
|
||||
private final NullPrecedence nullPrecedence;
|
||||
private final boolean ignoreCase;
|
||||
|
||||
public SortSpecification(Expression sortExpression, SortDirection sortOrder) {
|
||||
this( sortExpression, sortOrder, NullPrecedence.NONE );
|
||||
}
|
||||
|
||||
public SortSpecification(Expression sortExpression, SortDirection sortOrder, NullPrecedence nullPrecedence) {
|
||||
this(sortExpression, sortOrder, nullPrecedence, false);
|
||||
}
|
||||
|
||||
public SortSpecification(Expression sortExpression, SortDirection sortOrder, NullPrecedence nullPrecedence, boolean ignoreCase) {
|
||||
assert sortExpression != null;
|
||||
assert sortOrder != null;
|
||||
assert nullPrecedence != null;
|
||||
this.sortExpression = sortExpression;
|
||||
this.sortOrder = sortOrder;
|
||||
this.nullPrecedence = nullPrecedence;
|
||||
this.ignoreCase = ignoreCase;
|
||||
}
|
||||
|
||||
public Expression getSortExpression() {
|
||||
|
@ -45,6 +51,10 @@ public class SortSpecification implements SqlAstNode {
|
|||
return nullPrecedence;
|
||||
}
|
||||
|
||||
public boolean isIgnoreCase() {
|
||||
return ignoreCase;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(SqlAstWalker sqlTreeWalker) {
|
||||
sqlTreeWalker.visitSortSpecification( this );
|
||||
|
|
|
@ -248,7 +248,7 @@ public abstract class AbstractQueryMethod implements MetaAttribute {
|
|||
.append("sort.property()")
|
||||
.append(",\n\t\t\t\t\t\t")
|
||||
.append("sort.isAscending() ? ASCENDING : DESCENDING")
|
||||
.append(")));\n\t\t\t}})");
|
||||
.append(", sort.ignoreCase())));\n\t\t\t}})");
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -234,6 +234,7 @@ public class CriteriaFinderMethod extends AbstractFinderMethod {
|
|||
}
|
||||
|
||||
private static void orderBy(StringBuilder declaration, String paramName) {
|
||||
// TODO: Sort.ignoreCase()
|
||||
declaration
|
||||
.append("\n\t\t")
|
||||
.append(paramName)
|
||||
|
|
Loading…
Reference in New Issue