redesign 'collate' and add tests

* and add tests and documentation for 'collate'
* much better and less-ambiguous syntax for collate(), consistent with cast() and treat()
* reimplement collate() using the function infrastructure
* implement collate() for HSQLDB

This feature was previously untested and at least partially broken, and was making a mess 
of the HQL grammar.
This commit is contained in:
Gavin King 2022-01-02 13:39:33 +01:00 committed by GitHub
parent 4509cad315
commit 5ae55d7bfb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 283 additions and 273 deletions

View File

@ -850,6 +850,15 @@ include::{sourcedir}/HQLTest.java[tags=hql-year-function-example]
---- ----
==== ====
===== `collate()`
Selects a collation to be used for its string-valued argument.
Collations are useful for <<hql-relational-comparisons,binary comparisons>> with `<` or `>`, and in the <<hql-order-by,order by clause>>.
For example, `collate(p.name as ucs_basic)` specifies the SQL standard collation `ucs_basic`.
IMPORTANT: Collations aren't very portable between databases.
[[hql-function-format]] [[hql-function-format]]
===== `format()` ===== `format()`

View File

@ -293,12 +293,12 @@ mapKeyNavigablePath
// GROUP BY clause // GROUP BY clause
groupByClause groupByClause
: GROUP BY groupByExpression ( COMMA groupByExpression )* : GROUP BY groupByExpression ( COMMA groupByExpression )*
; ;
groupByExpression groupByExpression
: identifier collationSpecification? : identifier
| INTEGER_LITERAL collationSpecification? | INTEGER_LITERAL
| expression | expression
; ;
@ -306,7 +306,7 @@ groupByExpression
//HAVING clause //HAVING clause
havingClause havingClause
: HAVING predicate : HAVING predicate
; ;
@ -333,22 +333,22 @@ nullsPrecedence
; ;
sortExpression sortExpression
: identifier collationSpecification? : identifier
| INTEGER_LITERAL collationSpecification? | INTEGER_LITERAL
| expression | expression
; ;
collationSpecification collationExpression
: COLLATE collateName : COLLATE LEFT_PAREN expression AS collation RIGHT_PAREN
; ;
collateName collation
: dotIdentifierSequence : dotIdentifierSequence
; ;
orderingSpecification orderingSpecification
: ASC : ASC
| DESC | DESC
; ;
@ -384,7 +384,7 @@ parameterOrNumberLiteral
// WHERE clause & Predicates // WHERE clause & Predicates
whereClause whereClause
: WHERE predicate : WHERE predicate
; ;
predicate predicate
@ -436,7 +436,7 @@ expression
: LEFT_PAREN expression RIGHT_PAREN # GroupedExpression : LEFT_PAREN expression RIGHT_PAREN # GroupedExpression
| LEFT_PAREN expressionOrPredicate (COMMA expressionOrPredicate)+ RIGHT_PAREN # TupleExpression | LEFT_PAREN expressionOrPredicate (COMMA expressionOrPredicate)+ RIGHT_PAREN # TupleExpression
| LEFT_PAREN subquery RIGHT_PAREN # SubqueryExpression | LEFT_PAREN subquery RIGHT_PAREN # SubqueryExpression
| primaryExpression collationSpecification? # CollateExpression | primaryExpression # BarePrimaryExpression
| signOperator numericLiteral # UnaryNumericLiteralExpression | signOperator numericLiteral # UnaryNumericLiteralExpression
| signOperator expression # UnaryExpression | signOperator expression # UnaryExpression
| expression datetimeField # ToDurationExpression | expression datetimeField # ToDurationExpression
@ -707,6 +707,7 @@ standardFunction
| offsetDateTimeFunction | offsetDateTimeFunction
| cube | cube
| rollup | rollup
| collationExpression
; ;

View File

@ -792,6 +792,7 @@ public abstract class Dialect implements ConversionContext {
* *
* <ul> * <ul>
* <li> format(datetime as pattern) * <li> format(datetime as pattern)
* <li> collate(string as collation)
* <li> str(arg) - synonym of cast(a as String) * <li> str(arg) - synonym of cast(a as String)
* <li> ifnull(arg0, arg1) - synonym of coalesce(a, b) * <li> ifnull(arg0, arg1) - synonym of coalesce(a, b)
* </ul> * </ul>
@ -897,6 +898,10 @@ public abstract class Dialect implements ConversionContext {
) )
); );
//There is a 'collate' operator in a number of major databases
CommonFunctionFactory.collate( queryEngine );
//ANSI SQL extract() function is supported on the databases we care most //ANSI SQL extract() function is supported on the databases we care most
//about (though it is called datepart() in some of them) but HQL defines //about (though it is called datepart() in some of them) but HQL defines
//additional non-standard temporal field types, which must be emulated in //additional non-standard temporal field types, which must be emulated in

View File

@ -210,6 +210,7 @@ public class HSQLDialect extends Dialect {
CommonFunctionFactory.varPopSamp( queryEngine ); CommonFunctionFactory.varPopSamp( queryEngine );
CommonFunctionFactory.addMonths( queryEngine ); CommonFunctionFactory.addMonths( queryEngine );
CommonFunctionFactory.monthsBetween( queryEngine ); CommonFunctionFactory.monthsBetween( queryEngine );
CommonFunctionFactory.collate_quoted( queryEngine );
if ( getVersion().isSameOrAfter( 2 ) ) { if ( getVersion().isSameOrAfter( 2 ) ) {
//SYSDATE is similar to LOCALTIMESTAMP but it returns the timestamp when it is called //SYSDATE is similar to LOCALTIMESTAMP but it returns the timestamp when it is called

View File

@ -2185,6 +2185,32 @@ public class CommonFunctionFactory {
.register(); .register();
} }
/**
* Use the 'collate' operator which exists on at least Postgres, MySQL, Oracle, and SQL Server
*/
public static void collate(QueryEngine queryEngine) {
queryEngine.getSqmFunctionRegistry().patternDescriptorBuilder("collate", "(?1 collate ?2)")
.setInvariantType(
queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.STRING )
)
.setExactArgumentCount( 2 )
.setArgumentListSignature("(string as collation)")
.register();
}
/**
* HSQL requires quotes around certain collations
*/
public static void collate_quoted(QueryEngine queryEngine) {
queryEngine.getSqmFunctionRegistry().patternDescriptorBuilder("collate", "(?1 collate '?2')")
.setInvariantType(
queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.STRING )
)
.setExactArgumentCount( 2 )
.setArgumentListSignature("(string as collation)")
.register();
}
public static void dateTrunc(QueryEngine queryEngine) { public static void dateTrunc(QueryEngine queryEngine) {
queryEngine.getSqmFunctionRegistry().patternDescriptorBuilder( "date_trunc", "date_trunc('?1',?2)" ) queryEngine.getSqmFunctionRegistry().patternDescriptorBuilder( "date_trunc", "date_trunc('?1',?2)" )
.setInvariantType( .setInvariantType(

View File

@ -114,7 +114,7 @@ import org.hibernate.query.sqm.tree.expression.SqmByUnit;
import org.hibernate.query.sqm.tree.expression.SqmCaseSearched; import org.hibernate.query.sqm.tree.expression.SqmCaseSearched;
import org.hibernate.query.sqm.tree.expression.SqmCaseSimple; import org.hibernate.query.sqm.tree.expression.SqmCaseSimple;
import org.hibernate.query.sqm.tree.expression.SqmCastTarget; import org.hibernate.query.sqm.tree.expression.SqmCastTarget;
import org.hibernate.query.sqm.tree.expression.SqmCollate; import org.hibernate.query.sqm.tree.expression.SqmCollation;
import org.hibernate.query.sqm.tree.expression.SqmCollectionSize; import org.hibernate.query.sqm.tree.expression.SqmCollectionSize;
import org.hibernate.query.sqm.tree.expression.SqmDistinct; import org.hibernate.query.sqm.tree.expression.SqmDistinct;
import org.hibernate.query.sqm.tree.expression.SqmDurationUnit; import org.hibernate.query.sqm.tree.expression.SqmDurationUnit;
@ -1912,7 +1912,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
private Map<Class<?>, Enum<?>> getPossibleEnumValues(HqlParser.ExpressionContext expressionContext) { private Map<Class<?>, Enum<?>> getPossibleEnumValues(HqlParser.ExpressionContext expressionContext) {
ParseTree ctx; ParseTree ctx;
// Traverse the expression structure according to the grammar // Traverse the expression structure according to the grammar
if ( expressionContext instanceof HqlParser.CollateExpressionContext && expressionContext.getChildCount() == 1 ) { if ( expressionContext instanceof HqlParser.BarePrimaryExpressionContext && expressionContext.getChildCount() == 1 ) {
ctx = expressionContext.getChild( 0 ); ctx = expressionContext.getChild( 0 );
while ( ctx instanceof HqlParser.PrimaryExpressionContext && ctx.getChildCount() == 1 ) { while ( ctx instanceof HqlParser.PrimaryExpressionContext && ctx.getChildCount() == 1 ) {
@ -2326,17 +2326,30 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
} }
@Override @Override
public Object visitCollateExpression(HqlParser.CollateExpressionContext ctx) { public Object visitCollationExpression(HqlParser.CollationExpressionContext ctx) {
SqmExpression<?> expression = (SqmExpression<?>) ctx.getChild( 0 ).accept( this );
if ( ctx.getChildCount() == 1 ) {
return expression;
}
if ( creationOptions.useStrictJpaCompliance() ) { if ( creationOptions.useStrictJpaCompliance() ) {
throw new StrictJpaComplianceViolation( throw new StrictJpaComplianceViolation(
StrictJpaComplianceViolation.Type.COLLATIONS StrictJpaComplianceViolation.Type.COLLATIONS
); );
} }
return new SqmCollate<>( expression, ctx.getChild( 1 ).getChild( 1 ).getText() );
final SqmExpression<?> expressionToCollate = (SqmExpression<?>) ctx.getChild( 2 ).accept( this );
final SqmCollation castTargetExpression = (SqmCollation) ctx.getChild( 4 ).accept( this );
return getFunctionDescriptor("collate").generateSqmExpression(
asList( expressionToCollate, castTargetExpression ),
null, //why not string?
creationContext.getQueryEngine(),
creationContext.getJpaMetamodel().getTypeConfiguration()
);
}
@Override
public Object visitCollation(HqlParser.CollationContext ctx) {
return new SqmCollation(
ctx.getChild( 0 ).getText(),
null,
creationContext.getNodeBuilder() );
} }
@Override @Override
@ -3466,7 +3479,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
return getFunctionDescriptor("format").generateSqmExpression( return getFunctionDescriptor("format").generateSqmExpression(
asList( expressionToCast, format ), asList( expressionToCast, format ),
null, null, //why not string?
creationContext.getQueryEngine(), creationContext.getQueryEngine(),
creationContext.getJpaMetamodel().getTypeConfiguration() creationContext.getJpaMetamodel().getTypeConfiguration()
); );

View File

@ -27,6 +27,7 @@ import org.hibernate.query.sqm.tree.domain.SqmMinIndexPath;
import org.hibernate.query.sqm.tree.domain.SqmPluralPartJoin; import org.hibernate.query.sqm.tree.domain.SqmPluralPartJoin;
import org.hibernate.query.sqm.tree.domain.SqmPluralValuedSimplePath; import org.hibernate.query.sqm.tree.domain.SqmPluralValuedSimplePath;
import org.hibernate.query.sqm.tree.domain.SqmTreatedPath; import org.hibernate.query.sqm.tree.domain.SqmTreatedPath;
import org.hibernate.query.sqm.tree.expression.JpaCriteriaParameter;
import org.hibernate.query.sqm.tree.expression.SqmAny; import org.hibernate.query.sqm.tree.expression.SqmAny;
import org.hibernate.query.sqm.tree.expression.SqmBinaryArithmetic; import org.hibernate.query.sqm.tree.expression.SqmBinaryArithmetic;
import org.hibernate.query.sqm.tree.expression.SqmByUnit; import org.hibernate.query.sqm.tree.expression.SqmByUnit;
@ -34,30 +35,29 @@ import org.hibernate.query.sqm.tree.expression.SqmCaseSearched;
import org.hibernate.query.sqm.tree.expression.SqmCaseSimple; import org.hibernate.query.sqm.tree.expression.SqmCaseSimple;
import org.hibernate.query.sqm.tree.expression.SqmCastTarget; import org.hibernate.query.sqm.tree.expression.SqmCastTarget;
import org.hibernate.query.sqm.tree.expression.SqmCoalesce; import org.hibernate.query.sqm.tree.expression.SqmCoalesce;
import org.hibernate.query.sqm.tree.expression.SqmCollate; import org.hibernate.query.sqm.tree.expression.SqmCollation;
import org.hibernate.query.sqm.tree.expression.SqmCollectionSize; import org.hibernate.query.sqm.tree.expression.SqmCollectionSize;
import org.hibernate.query.sqm.tree.expression.JpaCriteriaParameter; import org.hibernate.query.sqm.tree.expression.SqmDistinct;
import org.hibernate.query.sqm.tree.expression.SqmDurationUnit; import org.hibernate.query.sqm.tree.expression.SqmDurationUnit;
import org.hibernate.query.sqm.tree.expression.SqmEnumLiteral;
import org.hibernate.query.sqm.tree.expression.SqmEvery; import org.hibernate.query.sqm.tree.expression.SqmEvery;
import org.hibernate.query.sqm.tree.expression.SqmExpression;
import org.hibernate.query.sqm.tree.expression.SqmExtractUnit;
import org.hibernate.query.sqm.tree.expression.SqmFieldLiteral;
import org.hibernate.query.sqm.tree.expression.SqmFormat; import org.hibernate.query.sqm.tree.expression.SqmFormat;
import org.hibernate.query.sqm.tree.expression.SqmFunction; import org.hibernate.query.sqm.tree.expression.SqmFunction;
import org.hibernate.query.sqm.tree.expression.SqmModifiedSubQueryExpression;
import org.hibernate.query.sqm.tree.expression.SqmParameterizedEntityType;
import org.hibernate.query.sqm.tree.expression.SqmEnumLiteral;
import org.hibernate.query.sqm.tree.expression.SqmExpression;
import org.hibernate.query.sqm.tree.expression.SqmFieldLiteral;
import org.hibernate.query.sqm.tree.expression.SqmLiteral; import org.hibernate.query.sqm.tree.expression.SqmLiteral;
import org.hibernate.query.sqm.tree.expression.SqmLiteralEntityType; import org.hibernate.query.sqm.tree.expression.SqmLiteralEntityType;
import org.hibernate.query.sqm.tree.expression.SqmModifiedSubQueryExpression;
import org.hibernate.query.sqm.tree.expression.SqmNamedParameter; import org.hibernate.query.sqm.tree.expression.SqmNamedParameter;
import org.hibernate.query.sqm.tree.expression.SqmParameterizedEntityType;
import org.hibernate.query.sqm.tree.expression.SqmPositionalParameter; import org.hibernate.query.sqm.tree.expression.SqmPositionalParameter;
import org.hibernate.query.sqm.tree.expression.SqmStar;
import org.hibernate.query.sqm.tree.expression.SqmSummarization; import org.hibernate.query.sqm.tree.expression.SqmSummarization;
import org.hibernate.query.sqm.tree.expression.SqmToDuration; import org.hibernate.query.sqm.tree.expression.SqmToDuration;
import org.hibernate.query.sqm.tree.expression.SqmTrimSpecification;
import org.hibernate.query.sqm.tree.expression.SqmTuple; import org.hibernate.query.sqm.tree.expression.SqmTuple;
import org.hibernate.query.sqm.tree.expression.SqmUnaryOperation; import org.hibernate.query.sqm.tree.expression.SqmUnaryOperation;
import org.hibernate.query.sqm.tree.expression.SqmDistinct;
import org.hibernate.query.sqm.tree.expression.SqmExtractUnit;
import org.hibernate.query.sqm.tree.expression.SqmStar;
import org.hibernate.query.sqm.tree.expression.SqmTrimSpecification;
import org.hibernate.query.sqm.tree.from.SqmAttributeJoin; import org.hibernate.query.sqm.tree.from.SqmAttributeJoin;
import org.hibernate.query.sqm.tree.from.SqmCrossJoin; import org.hibernate.query.sqm.tree.from.SqmCrossJoin;
import org.hibernate.query.sqm.tree.from.SqmEntityJoin; import org.hibernate.query.sqm.tree.from.SqmEntityJoin;
@ -197,7 +197,7 @@ public interface SemanticQueryWalker<T> {
T visitTuple(SqmTuple<?> sqmTuple); T visitTuple(SqmTuple<?> sqmTuple);
T visitCollate(SqmCollate<?> sqmCollate); T visitCollation(SqmCollation sqmCollate);
T visitBinaryArithmeticExpression(SqmBinaryArithmetic<?> expression); T visitBinaryArithmeticExpression(SqmBinaryArithmetic<?> expression);

View File

@ -107,7 +107,7 @@ public class SqmFunctionRegistry {
* Get a builder for creating and registering a pattern-based function descriptor. * Get a builder for creating and registering a pattern-based function descriptor.
* *
* @param registrationKey The name under which the descriptor will get registered * @param registrationKey The name under which the descriptor will get registered
* @param pattern The pattern defining the the underlying function call * @param pattern The pattern defining the underlying function call
* *
* @return The builder * @return The builder
*/ */
@ -119,7 +119,7 @@ public class SqmFunctionRegistry {
* Get a builder for creating and registering a pattern-based aggregate function descriptor. * Get a builder for creating and registering a pattern-based aggregate function descriptor.
* *
* @param registrationKey The name under which the descriptor will get registered * @param registrationKey The name under which the descriptor will get registered
* @param pattern The pattern defining the the underlying function call * @param pattern The pattern defining the underlying function call
* *
* @return The builder * @return The builder
*/ */

View File

@ -40,7 +40,7 @@ import org.hibernate.query.sqm.tree.expression.SqmCaseSearched;
import org.hibernate.query.sqm.tree.expression.SqmCaseSimple; import org.hibernate.query.sqm.tree.expression.SqmCaseSimple;
import org.hibernate.query.sqm.tree.expression.SqmCastTarget; import org.hibernate.query.sqm.tree.expression.SqmCastTarget;
import org.hibernate.query.sqm.tree.expression.SqmCoalesce; import org.hibernate.query.sqm.tree.expression.SqmCoalesce;
import org.hibernate.query.sqm.tree.expression.SqmCollate; import org.hibernate.query.sqm.tree.expression.SqmCollation;
import org.hibernate.query.sqm.tree.expression.SqmCollectionSize; import org.hibernate.query.sqm.tree.expression.SqmCollectionSize;
import org.hibernate.query.sqm.tree.expression.SqmDistinct; import org.hibernate.query.sqm.tree.expression.SqmDistinct;
import org.hibernate.query.sqm.tree.expression.SqmDurationUnit; import org.hibernate.query.sqm.tree.expression.SqmDurationUnit;
@ -53,10 +53,10 @@ import org.hibernate.query.sqm.tree.expression.SqmFormat;
import org.hibernate.query.sqm.tree.expression.SqmFunction; import org.hibernate.query.sqm.tree.expression.SqmFunction;
import org.hibernate.query.sqm.tree.expression.SqmLiteral; import org.hibernate.query.sqm.tree.expression.SqmLiteral;
import org.hibernate.query.sqm.tree.expression.SqmLiteralEntityType; import org.hibernate.query.sqm.tree.expression.SqmLiteralEntityType;
import org.hibernate.query.sqm.tree.expression.SqmModifiedSubQueryExpression;
import org.hibernate.query.sqm.tree.expression.SqmNamedParameter; import org.hibernate.query.sqm.tree.expression.SqmNamedParameter;
import org.hibernate.query.sqm.tree.expression.SqmParameterizedEntityType; import org.hibernate.query.sqm.tree.expression.SqmParameterizedEntityType;
import org.hibernate.query.sqm.tree.expression.SqmPositionalParameter; import org.hibernate.query.sqm.tree.expression.SqmPositionalParameter;
import org.hibernate.query.sqm.tree.expression.SqmModifiedSubQueryExpression;
import org.hibernate.query.sqm.tree.expression.SqmStar; import org.hibernate.query.sqm.tree.expression.SqmStar;
import org.hibernate.query.sqm.tree.expression.SqmSummarization; import org.hibernate.query.sqm.tree.expression.SqmSummarization;
import org.hibernate.query.sqm.tree.expression.SqmToDuration; import org.hibernate.query.sqm.tree.expression.SqmToDuration;
@ -977,7 +977,7 @@ public class SqmTreePrinter implements SemanticQueryWalker<Object> {
} }
@Override @Override
public Object visitCollate(SqmCollate<?> sqmCollate) { public Object visitCollation(SqmCollation sqmCollate) {
return null; return null;
} }

View File

@ -829,7 +829,6 @@ public class CteInsertHandler implements InsertHandler {
insertSelectSpec.addSortSpecification( insertSelectSpec.addSortSpecification(
new SortSpecification( new SortSpecification(
rowNumberColumnReference, rowNumberColumnReference,
null,
SortOrder.ASCENDING SortOrder.ASCENDING
) )
); );
@ -996,7 +995,6 @@ public class CteInsertHandler implements InsertHandler {
finalResultQuery.addSortSpecification( finalResultQuery.addSortSpecification(
new SortSpecification( new SortSpecification(
idColumnReference, idColumnReference,
null,
SortOrder.ASCENDING SortOrder.ASCENDING
) )
); );

View File

@ -317,7 +317,6 @@ public class InsertExecutionDelegate implements TableBasedInsertHandler.Executio
idSelectQuerySpec.addSortSpecification( idSelectQuerySpec.addSortSpecification(
new SortSpecification( new SortSpecification(
columnReference, columnReference,
null,
SortOrder.ASCENDING SortOrder.ASCENDING
) )
); );

View File

@ -40,29 +40,29 @@ import org.hibernate.query.sqm.tree.expression.SqmCaseSearched;
import org.hibernate.query.sqm.tree.expression.SqmCaseSimple; import org.hibernate.query.sqm.tree.expression.SqmCaseSimple;
import org.hibernate.query.sqm.tree.expression.SqmCastTarget; import org.hibernate.query.sqm.tree.expression.SqmCastTarget;
import org.hibernate.query.sqm.tree.expression.SqmCoalesce; import org.hibernate.query.sqm.tree.expression.SqmCoalesce;
import org.hibernate.query.sqm.tree.expression.SqmCollate; import org.hibernate.query.sqm.tree.expression.SqmCollation;
import org.hibernate.query.sqm.tree.expression.SqmCollectionSize; import org.hibernate.query.sqm.tree.expression.SqmCollectionSize;
import org.hibernate.query.sqm.tree.expression.SqmDistinct;
import org.hibernate.query.sqm.tree.expression.SqmDurationUnit; import org.hibernate.query.sqm.tree.expression.SqmDurationUnit;
import org.hibernate.query.sqm.tree.expression.SqmEnumLiteral; import org.hibernate.query.sqm.tree.expression.SqmEnumLiteral;
import org.hibernate.query.sqm.tree.expression.SqmEvery; import org.hibernate.query.sqm.tree.expression.SqmEvery;
import org.hibernate.query.sqm.tree.expression.SqmExpression; import org.hibernate.query.sqm.tree.expression.SqmExpression;
import org.hibernate.query.sqm.tree.expression.SqmExtractUnit;
import org.hibernate.query.sqm.tree.expression.SqmFieldLiteral; import org.hibernate.query.sqm.tree.expression.SqmFieldLiteral;
import org.hibernate.query.sqm.tree.expression.SqmFormat; import org.hibernate.query.sqm.tree.expression.SqmFormat;
import org.hibernate.query.sqm.tree.expression.SqmFunction; import org.hibernate.query.sqm.tree.expression.SqmFunction;
import org.hibernate.query.sqm.tree.expression.SqmLiteral; import org.hibernate.query.sqm.tree.expression.SqmLiteral;
import org.hibernate.query.sqm.tree.expression.SqmLiteralEntityType; import org.hibernate.query.sqm.tree.expression.SqmLiteralEntityType;
import org.hibernate.query.sqm.tree.expression.SqmModifiedSubQueryExpression;
import org.hibernate.query.sqm.tree.expression.SqmNamedParameter; import org.hibernate.query.sqm.tree.expression.SqmNamedParameter;
import org.hibernate.query.sqm.tree.expression.SqmParameterizedEntityType; import org.hibernate.query.sqm.tree.expression.SqmParameterizedEntityType;
import org.hibernate.query.sqm.tree.expression.SqmPositionalParameter; import org.hibernate.query.sqm.tree.expression.SqmPositionalParameter;
import org.hibernate.query.sqm.tree.expression.SqmModifiedSubQueryExpression; import org.hibernate.query.sqm.tree.expression.SqmStar;
import org.hibernate.query.sqm.tree.expression.SqmSummarization; import org.hibernate.query.sqm.tree.expression.SqmSummarization;
import org.hibernate.query.sqm.tree.expression.SqmToDuration; import org.hibernate.query.sqm.tree.expression.SqmToDuration;
import org.hibernate.query.sqm.tree.expression.SqmTrimSpecification;
import org.hibernate.query.sqm.tree.expression.SqmTuple; import org.hibernate.query.sqm.tree.expression.SqmTuple;
import org.hibernate.query.sqm.tree.expression.SqmUnaryOperation; import org.hibernate.query.sqm.tree.expression.SqmUnaryOperation;
import org.hibernate.query.sqm.tree.expression.SqmDistinct;
import org.hibernate.query.sqm.tree.expression.SqmExtractUnit;
import org.hibernate.query.sqm.tree.expression.SqmStar;
import org.hibernate.query.sqm.tree.expression.SqmTrimSpecification;
import org.hibernate.query.sqm.tree.from.SqmAttributeJoin; import org.hibernate.query.sqm.tree.from.SqmAttributeJoin;
import org.hibernate.query.sqm.tree.from.SqmCrossJoin; import org.hibernate.query.sqm.tree.from.SqmCrossJoin;
import org.hibernate.query.sqm.tree.from.SqmEntityJoin; import org.hibernate.query.sqm.tree.from.SqmEntityJoin;
@ -676,8 +676,7 @@ public abstract class BaseSemanticQueryWalker implements SemanticQueryWalker<Obj
} }
@Override @Override
public Object visitCollate(SqmCollate<?> sqmCollate) { public Object visitCollation(SqmCollation sqmCollate) {
sqmCollate.getExpression().accept( this );
return sqmCollate; return sqmCollate;
} }

View File

@ -101,7 +101,7 @@ import org.hibernate.query.sqm.tree.SqmJoinType;
import org.hibernate.query.sqm.tree.domain.SqmCorrelatedRootJoin; import org.hibernate.query.sqm.tree.domain.SqmCorrelatedRootJoin;
import org.hibernate.query.sqm.tree.domain.SqmCorrelation; import org.hibernate.query.sqm.tree.domain.SqmCorrelation;
import org.hibernate.query.sqm.tree.domain.SqmPluralPartJoin; import org.hibernate.query.sqm.tree.domain.SqmPluralPartJoin;
import org.hibernate.query.sqm.tree.expression.SqmModifiedSubQueryExpression; import org.hibernate.query.sqm.tree.expression.*;
import org.hibernate.query.sqm.tree.insert.SqmInsertStatement; import org.hibernate.query.sqm.tree.insert.SqmInsertStatement;
import org.hibernate.sql.ast.tree.expression.ModifiedSubQueryExpression; import org.hibernate.sql.ast.tree.expression.ModifiedSubQueryExpression;
import org.hibernate.query.sqm.tree.domain.SqmTreatedRoot; import org.hibernate.query.sqm.tree.domain.SqmTreatedRoot;
@ -175,40 +175,6 @@ import org.hibernate.query.sqm.tree.domain.SqmMinIndexPath;
import org.hibernate.query.sqm.tree.domain.SqmPath; import org.hibernate.query.sqm.tree.domain.SqmPath;
import org.hibernate.query.sqm.tree.domain.SqmPluralValuedSimplePath; import org.hibernate.query.sqm.tree.domain.SqmPluralValuedSimplePath;
import org.hibernate.query.sqm.tree.domain.SqmTreatedPath; import org.hibernate.query.sqm.tree.domain.SqmTreatedPath;
import org.hibernate.query.sqm.tree.expression.Conversion;
import org.hibernate.query.sqm.tree.expression.JpaCriteriaParameter;
import org.hibernate.query.sqm.tree.expression.SqmAliasedNodeRef;
import org.hibernate.query.sqm.tree.expression.SqmAny;
import org.hibernate.query.sqm.tree.expression.SqmBinaryArithmetic;
import org.hibernate.query.sqm.tree.expression.SqmByUnit;
import org.hibernate.query.sqm.tree.expression.SqmCaseSearched;
import org.hibernate.query.sqm.tree.expression.SqmCaseSimple;
import org.hibernate.query.sqm.tree.expression.SqmCastTarget;
import org.hibernate.query.sqm.tree.expression.SqmCollate;
import org.hibernate.query.sqm.tree.expression.SqmCollectionSize;
import org.hibernate.query.sqm.tree.expression.SqmDistinct;
import org.hibernate.query.sqm.tree.expression.SqmDurationUnit;
import org.hibernate.query.sqm.tree.expression.SqmEnumLiteral;
import org.hibernate.query.sqm.tree.expression.SqmEvery;
import org.hibernate.query.sqm.tree.expression.SqmExpression;
import org.hibernate.query.sqm.tree.expression.SqmExtractUnit;
import org.hibernate.query.sqm.tree.expression.SqmFieldLiteral;
import org.hibernate.query.sqm.tree.expression.SqmFormat;
import org.hibernate.query.sqm.tree.expression.SqmFunction;
import org.hibernate.query.sqm.tree.expression.SqmJpaCriteriaParameterWrapper;
import org.hibernate.query.sqm.tree.expression.SqmLiteral;
import org.hibernate.query.sqm.tree.expression.SqmLiteralEntityType;
import org.hibernate.query.sqm.tree.expression.SqmLiteralNull;
import org.hibernate.query.sqm.tree.expression.SqmNamedParameter;
import org.hibernate.query.sqm.tree.expression.SqmParameter;
import org.hibernate.query.sqm.tree.expression.SqmParameterizedEntityType;
import org.hibernate.query.sqm.tree.expression.SqmPositionalParameter;
import org.hibernate.query.sqm.tree.expression.SqmStar;
import org.hibernate.query.sqm.tree.expression.SqmSummarization;
import org.hibernate.query.sqm.tree.expression.SqmToDuration;
import org.hibernate.query.sqm.tree.expression.SqmTrimSpecification;
import org.hibernate.query.sqm.tree.expression.SqmTuple;
import org.hibernate.query.sqm.tree.expression.SqmUnaryOperation;
import org.hibernate.query.sqm.tree.from.SqmAttributeJoin; import org.hibernate.query.sqm.tree.from.SqmAttributeJoin;
import org.hibernate.query.sqm.tree.from.SqmCrossJoin; import org.hibernate.query.sqm.tree.from.SqmCrossJoin;
import org.hibernate.query.sqm.tree.from.SqmEntityJoin; import org.hibernate.query.sqm.tree.from.SqmEntityJoin;
@ -281,7 +247,7 @@ import org.hibernate.sql.ast.tree.expression.BinaryArithmeticExpression;
import org.hibernate.sql.ast.tree.expression.CaseSearchedExpression; import org.hibernate.sql.ast.tree.expression.CaseSearchedExpression;
import org.hibernate.sql.ast.tree.expression.CaseSimpleExpression; import org.hibernate.sql.ast.tree.expression.CaseSimpleExpression;
import org.hibernate.sql.ast.tree.expression.CastTarget; import org.hibernate.sql.ast.tree.expression.CastTarget;
import org.hibernate.sql.ast.tree.expression.Collate; import org.hibernate.sql.ast.tree.expression.Collation;
import org.hibernate.sql.ast.tree.expression.ColumnReference; import org.hibernate.sql.ast.tree.expression.ColumnReference;
import org.hibernate.sql.ast.tree.expression.Distinct; import org.hibernate.sql.ast.tree.expression.Distinct;
import org.hibernate.sql.ast.tree.expression.Duration; import org.hibernate.sql.ast.tree.expression.Duration;
@ -3707,7 +3673,6 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
subQuerySpec.addSortSpecification( subQuerySpec.addSortSpecification(
new SortSpecification( new SortSpecification(
columnReference, columnReference,
null,
max ? SortOrder.DESCENDING : SortOrder.ASCENDING max ? SortOrder.DESCENDING : SortOrder.ASCENDING
) )
); );
@ -4559,11 +4524,8 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
} }
@Override @Override
public Object visitCollate(SqmCollate<?> sqmCollate) { public Object visitCollation(SqmCollation sqmCollation) {
return new Collate( return new Collation( sqmCollation.getLiteralValue() );
(Expression) sqmCollate.getExpression().accept( this ),
sqmCollate.getCollation()
);
} }
@Override @Override
@ -4628,10 +4590,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
@Override @Override
public Object visitFormat(SqmFormat sqmFormat) { public Object visitFormat(SqmFormat sqmFormat) {
return new Format( return new Format( sqmFormat.getLiteralValue() );
sqmFormat.getLiteralValue(),
(BasicValuedMapping) sqmFormat.getNodeType()
);
} }
@Override @Override

View File

@ -1,45 +0,0 @@
/*
* 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.tree.expression;
import org.hibernate.query.sqm.SemanticQueryWalker;
/**
* @author Christian Beikov
*/
public class SqmCollate<T> extends AbstractSqmExpression<T> {
private final SqmExpression<T> expression;
private final String collation;
public SqmCollate(SqmExpression<T> expression, String collation) {
super( expression.getNodeType(), expression.nodeBuilder() );
assert !(expression instanceof SqmTuple);
this.expression = expression;
this.collation = collation;
}
public SqmExpression<T> getExpression() {
return expression;
}
public String getCollation() {
return collation;
}
@Override
public <X> X accept(SemanticQueryWalker<X> walker) {
return walker.visitCollate( this );
}
@Override
public void appendHqlString(StringBuilder sb) {
expression.appendHqlString( sb );
sb.append( " collate " );
sb.append( collation );
}
}

View File

@ -0,0 +1,30 @@
/*
* 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.tree.expression;
import org.hibernate.query.sqm.NodeBuilder;
import org.hibernate.query.sqm.SemanticQueryWalker;
import org.hibernate.query.sqm.SqmExpressable;
/**
* @author Christian Beikov
*/
public class SqmCollation extends SqmLiteral<String> {
public SqmCollation(String value, SqmExpressable<String> inherentType, NodeBuilder nodeBuilder) {
super(value, inherentType, nodeBuilder);
}
@Override
public <R> R accept(SemanticQueryWalker<R> walker) {
return walker.visitCollation( this );
}
@Override
public void appendHqlString(StringBuilder sb) {
sb.append( getLiteralValue() );
}
}

View File

@ -16,7 +16,7 @@ import org.hibernate.sql.ast.tree.expression.BinaryArithmeticExpression;
import org.hibernate.sql.ast.tree.expression.CaseSearchedExpression; import org.hibernate.sql.ast.tree.expression.CaseSearchedExpression;
import org.hibernate.sql.ast.tree.expression.CaseSimpleExpression; import org.hibernate.sql.ast.tree.expression.CaseSimpleExpression;
import org.hibernate.sql.ast.tree.expression.CastTarget; import org.hibernate.sql.ast.tree.expression.CastTarget;
import org.hibernate.sql.ast.tree.expression.Collate; import org.hibernate.sql.ast.tree.expression.Collation;
import org.hibernate.sql.ast.tree.expression.ColumnReference; import org.hibernate.sql.ast.tree.expression.ColumnReference;
import org.hibernate.sql.ast.tree.expression.Distinct; import org.hibernate.sql.ast.tree.expression.Distinct;
import org.hibernate.sql.ast.tree.expression.Duration; import org.hibernate.sql.ast.tree.expression.Duration;
@ -149,7 +149,7 @@ public interface SqlAstWalker {
void visitTuple(SqlTuple tuple); void visitTuple(SqlTuple tuple);
void visitCollate(Collate collate); void visitCollation(Collation collation);
void visitParameter(JdbcParameter jdbcParameter); void visitParameter(JdbcParameter jdbcParameter);

View File

@ -85,7 +85,7 @@ import org.hibernate.sql.ast.tree.expression.BinaryArithmeticExpression;
import org.hibernate.sql.ast.tree.expression.CaseSearchedExpression; import org.hibernate.sql.ast.tree.expression.CaseSearchedExpression;
import org.hibernate.sql.ast.tree.expression.CaseSimpleExpression; import org.hibernate.sql.ast.tree.expression.CaseSimpleExpression;
import org.hibernate.sql.ast.tree.expression.CastTarget; import org.hibernate.sql.ast.tree.expression.CastTarget;
import org.hibernate.sql.ast.tree.expression.Collate; import org.hibernate.sql.ast.tree.expression.Collation;
import org.hibernate.sql.ast.tree.expression.ColumnReference; import org.hibernate.sql.ast.tree.expression.ColumnReference;
import org.hibernate.sql.ast.tree.expression.Distinct; import org.hibernate.sql.ast.tree.expression.Distinct;
import org.hibernate.sql.ast.tree.expression.Duration; import org.hibernate.sql.ast.tree.expression.Duration;
@ -4335,10 +4335,8 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
} }
@Override @Override
public void visitCollate(Collate collate) { public void visitCollation(Collation collation) {
collate.getExpression().accept( this ); appendSql( collation.getCollation() );
appendSql( " collate " );
appendSql( collate.getCollation() );
} }
@Override @Override

View File

@ -19,7 +19,7 @@ import org.hibernate.sql.ast.tree.expression.BinaryArithmeticExpression;
import org.hibernate.sql.ast.tree.expression.CaseSearchedExpression; import org.hibernate.sql.ast.tree.expression.CaseSearchedExpression;
import org.hibernate.sql.ast.tree.expression.CaseSimpleExpression; import org.hibernate.sql.ast.tree.expression.CaseSimpleExpression;
import org.hibernate.sql.ast.tree.expression.CastTarget; import org.hibernate.sql.ast.tree.expression.CastTarget;
import org.hibernate.sql.ast.tree.expression.Collate; import org.hibernate.sql.ast.tree.expression.Collation;
import org.hibernate.sql.ast.tree.expression.ColumnReference; import org.hibernate.sql.ast.tree.expression.ColumnReference;
import org.hibernate.sql.ast.tree.expression.Distinct; import org.hibernate.sql.ast.tree.expression.Distinct;
import org.hibernate.sql.ast.tree.expression.Duration; import org.hibernate.sql.ast.tree.expression.Duration;
@ -162,8 +162,7 @@ public class AbstractSqlAstWalker implements SqlAstWalker {
} }
@Override @Override
public void visitCollate(Collate collate) { public void visitCollation(Collation collation) {
collate.getExpression().accept( this );
} }
@Override @Override

View File

@ -1,106 +0,0 @@
/*
* 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.sql.ast.tree.expression;
import org.hibernate.mapping.IndexedConsumer;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.mapping.JdbcMappingContainer;
import org.hibernate.metamodel.mapping.SqlExpressable;
import org.hibernate.query.sqm.sql.internal.DomainResultProducer;
import org.hibernate.sql.ast.SqlAstWalker;
import org.hibernate.sql.ast.spi.SqlAstCreationState;
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.sql.results.graph.DomainResult;
import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.basic.BasicResult;
import org.hibernate.type.descriptor.java.JavaType;
/**
* @author Christian Beikov
*/
public class Collate implements Expression, SqlExpressable, SqlAstNode, DomainResultProducer {
private final Expression expression;
private final String collation;
public Collate(Expression expression, String collation) {
this.expression = expression;
this.collation = collation;
}
public Expression getExpression() {
return expression;
}
public String getCollation() {
return collation;
}
@Override
public JdbcMapping getJdbcMapping() {
if ( expression instanceof SqlExpressable ) {
return ( (SqlExpressable) expression ).getJdbcMapping();
}
if ( getExpressionType() instanceof SqlExpressable ) {
return ( (SqlExpressable) getExpressionType() ).getJdbcMapping();
}
if ( getExpressionType() != null ) {
final JdbcMappingContainer mappingContainer = getExpressionType();
assert mappingContainer.getJdbcTypeCount() == 1;
return mappingContainer.getJdbcMappings().get( 0 );
}
return null;
}
@Override
public JdbcMappingContainer getExpressionType() {
return expression.getExpressionType();
}
@Override
public void accept(SqlAstWalker sqlTreeWalker) {
sqlTreeWalker.visitCollate( this );
}
@Override
public DomainResult createDomainResult(
String resultVariable,
DomainResultCreationState creationState) {
final JavaType javaTypeDescriptor = expression.getExpressionType().getJdbcMappings().get( 0 ).getJavaTypeDescriptor();
return new BasicResult(
creationState.getSqlAstCreationState().getSqlExpressionResolver().resolveSqlSelection(
this,
javaTypeDescriptor,
creationState.getSqlAstCreationState().getCreationContext().getDomainModel().getTypeConfiguration()
).getValuesArrayPosition(),
resultVariable,
javaTypeDescriptor
);
}
@Override
public void applySqlSelections(DomainResultCreationState creationState) {
final SqlAstCreationState sqlAstCreationState = creationState.getSqlAstCreationState();
final SqlExpressionResolver sqlExpressionResolver = sqlAstCreationState.getSqlExpressionResolver();
sqlExpressionResolver.resolveSqlSelection(
this,
expression.getExpressionType().getJdbcMappings().get( 0 ).getJavaTypeDescriptor(),
sqlAstCreationState.getCreationContext().getDomainModel().getTypeConfiguration()
);
}
@Override
public int forEachJdbcType(int offset, IndexedConsumer<JdbcMapping> action) {
action.accept( offset, getJdbcMapping() );
return getJdbcTypeCount();
}
}

View File

@ -0,0 +1,44 @@
/*
* 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.sql.ast.tree.expression;
import org.hibernate.mapping.IndexedConsumer;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.mapping.SqlExpressable;
import org.hibernate.sql.ast.SqlAstWalker;
import org.hibernate.sql.ast.tree.SqlAstNode;
/**
* @author Christian Beikov
*/
public class Collation implements SqlExpressable, SqlAstNode {
private final String collation;
public Collation(String collation) {
this.collation = collation;
}
public String getCollation() {
return collation;
}
@Override
public void accept(SqlAstWalker walker) {
walker.visitCollation( this );
}
@Override
public int forEachJdbcType(int offset, IndexedConsumer<JdbcMapping> action) {
return getJdbcTypeCount();
}
@Override
public JdbcMapping getJdbcMapping() {
return null;
}
}

View File

@ -7,7 +7,6 @@
package org.hibernate.sql.ast.tree.expression; package org.hibernate.sql.ast.tree.expression;
import org.hibernate.mapping.IndexedConsumer; import org.hibernate.mapping.IndexedConsumer;
import org.hibernate.metamodel.mapping.BasicValuedMapping;
import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.mapping.SqlExpressable; import org.hibernate.metamodel.mapping.SqlExpressable;
import org.hibernate.sql.ast.SqlAstWalker; import org.hibernate.sql.ast.SqlAstWalker;
@ -20,11 +19,9 @@ import org.hibernate.sql.ast.tree.SqlAstNode;
*/ */
public class Format implements SqlExpressable, SqlAstNode { public class Format implements SqlExpressable, SqlAstNode {
private String format; private String format;
private BasicValuedMapping type;
public Format(String format, BasicValuedMapping type) { public Format(String format) {
this.format = format; this.format = format;
this.type = type;
} }
public String getFormat() { public String getFormat() {
@ -33,7 +30,7 @@ public class Format implements SqlExpressable, SqlAstNode {
@Override @Override
public JdbcMapping getJdbcMapping() { public JdbcMapping getJdbcMapping() {
return type.getJdbcMapping(); return null;
} }
@Override @Override
@ -43,7 +40,6 @@ public class Format implements SqlExpressable, SqlAstNode {
@Override @Override
public int forEachJdbcType(int offset, IndexedConsumer<JdbcMapping> action) { public int forEachJdbcType(int offset, IndexedConsumer<JdbcMapping> action) {
action.accept( offset, type.getJdbcMapping() );
return getJdbcTypeCount(); return getJdbcTypeCount();
} }
} }

View File

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

View File

@ -0,0 +1,83 @@
/*
* 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 org.hibernate.dialect.HSQLDialect;
import org.hibernate.dialect.MySQLDialect;
import org.hibernate.dialect.PostgreSQLDialect;
import org.hibernate.testing.orm.domain.StandardDomainModel;
import org.hibernate.testing.orm.domain.gambit.EntityOfBasics;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.RequiresDialect;
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.BeforeAll;
import org.junit.jupiter.api.Test;
import java.sql.Date;
import java.sql.Time;
import java.sql.Timestamp;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
/**
* @author Gavin King
*/
@ServiceRegistry
@DomainModel( standardModels = StandardDomainModel.GAMBIT )
@SessionFactory
public class CollateTests {
@BeforeAll
public void prepareData(SessionFactoryScope scope) {
scope.inTransaction(
em -> {
EntityOfBasics entity = new EntityOfBasics();
entity.setTheString("1234589");
entity.setId(123);
entity.setTheDate( new Date( 74, 2, 25 ) );
entity.setTheTime( new Time( 20, 10, 8 ) );
entity.setTheTimestamp( new Timestamp( 121, 4, 27, 13, 22, 50, 123456789 ) );
em.persist(entity);
}
);
}
@Test @RequiresDialect(PostgreSQLDialect.class)
public void testCollatePostgreSQL(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
session.createQuery("from EntityOfBasics e where e.theString is not null order by collate(e.theString as ucs_basic)").getResultList();
assertThat( session.createQuery("select collate('bar' as ucs_basic) < 'foo'").getSingleResult(), is(true) );
}
);
}
@Test @RequiresDialect(MySQLDialect.class)
public void testCollateMySQL(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
session.createQuery("from EntityOfBasics e order by collate(e.theString as utf8mb4_bin)").getResultList();
assertThat( session.createQuery("select collate('bar' as utf8mb4_bin) < 'foo'").getSingleResult(), is(true) );
}
);
}
@Test @RequiresDialect(HSQLDialect.class)
public void testCollateHSQL(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
session.createQuery("from EntityOfBasics e order by collate(e.theString as SQL_TEXT_UCC)").getResultList();
session.createQuery("from EntityOfBasics e order by collate(e.theString as English)").getResultList();
assertThat( session.createQuery("select collate('bar' as English) < 'foo'").getSingleResult(), is(true) );
}
);
}
}