Fix collation handling for ordering expressions. Fix SqmQuerySpec#setRestriction

This commit is contained in:
Christian Beikov 2022-01-03 23:27:21 +01:00
parent bddbb4d287
commit cb5e0b08b9
12 changed files with 152 additions and 18 deletions

View File

@ -10,6 +10,7 @@ import java.util.ArrayList;
import java.util.List;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.metamodel.mapping.ordering.ast.OrderingExpression;
import org.hibernate.query.NullPrecedence;
import org.hibernate.query.SortOrder;
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
@ -265,6 +266,11 @@ public abstract class AbstractDomainPath implements DomainPath {
}
}
}
ast.addSortSpecification( new SortSpecification( expression, collation, sortOrder, nullPrecedence ) );
final Expression sortExpression = OrderingExpression.applyCollation(
expression,
collation,
creationState
);
ast.addSortSpecification( new SortSpecification( sortExpression, sortOrder, nullPrecedence ) );
}
}

View File

@ -104,7 +104,12 @@ public class ColumnReference implements OrderingExpression, SequencePart {
}
}
ast.addSortSpecification( new SortSpecification( expression, collation, sortOrder, nullPrecedence ) );
final Expression sortExpression = OrderingExpression.applyCollation(
expression,
collation,
creationState
);
ast.addSortSpecification( new SortSpecification( sortExpression, sortOrder, nullPrecedence ) );
}
TableReference getTableReference(TableGroup tableGroup) {

View File

@ -20,6 +20,7 @@ import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.spi.SqlAstCreationState;
import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.select.QuerySpec;
import org.hibernate.sql.ast.tree.select.SortSpecification;
@ -98,7 +99,12 @@ public class FunctionExpression implements OrderingExpression, FunctionRendering
NullPrecedence nullPrecedence,
SqlAstCreationState creationState) {
final SelfRenderingFunctionSqlAstExpression expression = resolve( ast, tableGroup, modelPartName, creationState );
ast.addSortSpecification( new SortSpecification( expression, collation, sortOrder, nullPrecedence ) );
final Expression sortExpression = OrderingExpression.applyCollation(
expression,
collation,
creationState
);
ast.addSortSpecification( new SortSpecification( sortExpression, sortOrder, nullPrecedence ) );
}
@Override

View File

@ -8,8 +8,13 @@ package org.hibernate.metamodel.mapping.ordering.ast;
import org.hibernate.query.NullPrecedence;
import org.hibernate.query.SortOrder;
import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.sqm.sql.FakeSqmToSqlAstConverter;
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
import org.hibernate.query.sqm.tree.expression.SqmSelfRenderingExpression;
import org.hibernate.sql.ast.spi.SqlAstCreationState;
import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.select.QuerySpec;
@ -33,4 +38,38 @@ public interface OrderingExpression extends Node {
SortOrder sortOrder,
NullPrecedence nullPrecedence,
SqlAstCreationState creationState);
public static Expression applyCollation(
Expression expression,
String collation,
SqlAstCreationState creationState) {
final Expression sortExpression;
if ( collation == null ) {
sortExpression = expression;
}
else {
final QueryEngine queryEngine = creationState.getCreationContext()
.getSessionFactory()
.getQueryEngine();
final SqmToSqlAstConverter converter;
if ( creationState instanceof SqmToSqlAstConverter ) {
converter = (SqmToSqlAstConverter) creationState;
}
else {
converter = new FakeSqmToSqlAstConverter( creationState );
}
sortExpression = queryEngine
.getSqmFunctionRegistry()
.findFunctionDescriptor( "collate" )
.generateSqmExpression(
new SqmSelfRenderingExpression<>( walker -> expression, null, null ),
null,
queryEngine,
queryEngine.getTypeConfiguration()
)
.convertToSqlAst( converter );
}
return sortExpression;
}
}

View File

@ -57,8 +57,13 @@ public class SelfRenderingOrderingExpression extends SelfRenderingSqlFragmentExp
}
}
}
final Expression sortExpression = OrderingExpression.applyCollation(
expression,
collation,
creationState
);
ast.addSortSpecification( new SortSpecification( expression, collation, sortOrder, nullPrecedence ) );
ast.addSortSpecification( new SortSpecification( sortExpression, sortOrder, nullPrecedence ) );
}
}

View File

@ -933,7 +933,7 @@ public class QuerySqmImpl<R>
final EntityPersister entityDescriptor = getSessionFactory().getDomainModel().findEntityDescriptor( entityNameToInsert );
final SqmMultiTableInsertStrategy multiTableStrategy = entityDescriptor.getSqmMultiTableInsertStrategy();
if ( multiTableStrategy == null || sqmInsert instanceof SqmInsertValuesStatement ) {
if ( multiTableStrategy == null ) {
return new SimpleInsertQueryPlan( sqmInsert, domainParameterXref );
}
else {

View File

@ -2029,7 +2029,6 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
}
return new SortSpecification(
expression,
null,
sortSpecification.getSortOrder(),
sortSpecification.getNullPrecedence()
);

View File

@ -0,0 +1,80 @@
/*
* 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.query.sqm.sql;
import java.util.List;
import org.hibernate.LockMode;
import org.hibernate.internal.util.collections.Stack;
import org.hibernate.query.sqm.spi.BaseSemanticQueryWalker;
import org.hibernate.query.sqm.tree.expression.SqmParameter;
import org.hibernate.sql.ast.Clause;
import org.hibernate.sql.ast.spi.FromClauseAccess;
import org.hibernate.sql.ast.spi.SqlAliasBaseGenerator;
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
import org.hibernate.sql.ast.spi.SqlAstCreationState;
import org.hibernate.sql.ast.spi.SqlAstProcessingState;
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
import org.hibernate.sql.ast.tree.expression.Expression;
/**
*
*/
public class FakeSqmToSqlAstConverter extends BaseSemanticQueryWalker implements SqmToSqlAstConverter {
private final SqlAstCreationState creationState;
public FakeSqmToSqlAstConverter(SqlAstCreationState creationState) {
super( creationState.getCreationContext().getServiceRegistry() );
this.creationState = creationState;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// SqlAstCreationState
@Override
public SqlAstCreationContext getCreationContext() {
return creationState.getCreationContext();
}
@Override
public SqlAstProcessingState getCurrentProcessingState() {
return creationState.getCurrentProcessingState();
}
@Override
public SqlExpressionResolver getSqlExpressionResolver() {
return creationState.getSqlExpressionResolver();
}
@Override
public SqlAliasBaseGenerator getSqlAliasBaseGenerator() {
return creationState.getSqlAliasBaseGenerator();
}
@Override
public void registerLockMode(String identificationVariable, LockMode explicitLockMode) {
creationState.registerLockMode( identificationVariable, explicitLockMode );
}
@Override
public FromClauseAccess getFromClauseAccess() {
return creationState.getFromClauseAccess();
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// SqmToSqlAstConverter
@Override
public Stack<Clause> getCurrentClauseStack() {
return null;
}
@Override
public List<Expression> expandSelfRenderingFunctionMultiValueParameter(SqmParameter sqmParameter) {
return null;
}
}

View File

@ -266,6 +266,9 @@ public class SqmQuerySpec<T> extends SqmQueryPart<T>
if ( whereClause == null ) {
setWhereClause( whereClause = new SqmWhereClause( nodeBuilder() ) );
}
else {
whereClause.setPredicate( null );
}
for ( Predicate restriction : restrictions ) {
whereClause.applyPredicate( (SqmPredicate) restriction );
}

View File

@ -3403,7 +3403,6 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
sortSpecificationsRowNumbering.add(
new SortSpecification(
new SqlSelectionExpression( sqlSelections.get( i ) ),
null,
SortOrder.ASCENDING,
NullPrecedence.NONE
)
@ -3437,7 +3436,6 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
new SqlSelectionExpression(
sqlSelections.get( position )
),
null,
sortSpecification.getSortOrder(),
sortSpecification.getNullPrecedence()
)

View File

@ -34,7 +34,7 @@ public class Collation implements SqlExpressable, SqlAstNode {
@Override
public int forEachJdbcType(int offset, IndexedConsumer<JdbcMapping> action) {
return getJdbcTypeCount();
return 0;
}
@Override

View File

@ -10,7 +10,6 @@ import org.hibernate.query.NullPrecedence;
import org.hibernate.query.SortOrder;
import org.hibernate.sql.ast.SqlAstWalker;
import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.sql.ast.tree.expression.Collation;
import org.hibernate.sql.ast.tree.expression.Expression;
/**
@ -20,15 +19,13 @@ public class SortSpecification implements SqlAstNode {
private final Expression sortExpression;
private final SortOrder sortOrder;
private final NullPrecedence nullPrecedence;
private final Collation collation;
public SortSpecification(Expression sortExpression, SortOrder sortOrder) {
this( sortExpression, null, sortOrder, NullPrecedence.NONE );
this( sortExpression, sortOrder, NullPrecedence.NONE );
}
public SortSpecification(Expression sortExpression, String collation, SortOrder sortOrder, NullPrecedence nullPrecedence) {
public SortSpecification(Expression sortExpression, SortOrder sortOrder, NullPrecedence nullPrecedence) {
this.sortExpression = sortExpression;
this.collation = collation == null ? null : new Collation(collation);
this.sortOrder = sortOrder;
this.nullPrecedence = nullPrecedence;
}
@ -37,10 +34,6 @@ public class SortSpecification implements SqlAstNode {
return sortExpression;
}
public Collation getCollation() {
return collation;
}
public SortOrder getSortOrder() {
return sortOrder;
}