Fix some issues with collection-path related HQL functions minindex/maxindex/minelement/maxelement/elements/indices and group by item rendering problems
This commit is contained in:
parent
4acdf1ab3e
commit
ca22db14bb
|
@ -2006,7 +2006,7 @@ public class HQLTest extends BaseEntityManagerFunctionalTestCase {
|
|||
"where p.person = ph.person ", Object[].class )
|
||||
.getResultList();
|
||||
//end::hql-relational-comparisons-example[]
|
||||
assertEquals(3, phonePayments.size());
|
||||
assertEquals(2, phonePayments.size());
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -197,6 +197,7 @@ HOUR : [hH] [oO] [uU] [rR];
|
|||
IFNULL : [iI] [fF] [nN] [uU] [lL] [lL];
|
||||
IN : [iI] [nN];
|
||||
INDEX : [iI] [nN] [dD] [eE] [xX];
|
||||
INDICES : [iI] [nN] [dD] [iI] [cC] [eE] [sS];
|
||||
INNER : [iI] [nN] [nN] [eE] [rR];
|
||||
INSERT : [iI] [nN] [sS] [eE] [rR] [tT];
|
||||
INSTANT : [iI] [nN] [sS] [tT] [aA] [nN] [tT];
|
||||
|
|
|
@ -255,6 +255,7 @@ pathContinuation
|
|||
*
|
||||
* * TREAT( path )
|
||||
* * ELEMENTS( path )
|
||||
* * INDICES( path )
|
||||
* * VALUE( path )
|
||||
* * KEY( path )
|
||||
* * path[ selector ]
|
||||
|
@ -262,6 +263,7 @@ pathContinuation
|
|||
syntacticDomainPath
|
||||
: treatedNavigablePath
|
||||
| collectionElementNavigablePath
|
||||
| collectionIndexNavigablePath
|
||||
| mapKeyNavigablePath
|
||||
| dotIdentifierSequence indexedPathAccessFragment
|
||||
;
|
||||
|
@ -289,6 +291,10 @@ collectionElementNavigablePath
|
|||
: (VALUE | ELEMENTS) LEFT_PAREN path RIGHT_PAREN pathContinuation?
|
||||
;
|
||||
|
||||
collectionIndexNavigablePath
|
||||
: INDICES LEFT_PAREN path RIGHT_PAREN
|
||||
;
|
||||
|
||||
mapKeyNavigablePath
|
||||
: KEY LEFT_PAREN path RIGHT_PAREN pathContinuation?
|
||||
;
|
||||
|
@ -401,6 +407,7 @@ predicate
|
|||
| expression (NOT)? BETWEEN expression AND expression # BetweenPredicate
|
||||
| expression (NOT)? LIKE 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
|
||||
|
@ -421,7 +428,7 @@ comparisonOperator
|
|||
;
|
||||
|
||||
inList
|
||||
: ELEMENTS? LEFT_PAREN dotIdentifierSequence RIGHT_PAREN # PersistentCollectionReferenceInList
|
||||
: (ELEMENTS|INDICES) LEFT_PAREN dotIdentifierSequence RIGHT_PAREN # PersistentCollectionReferenceInList
|
||||
| LEFT_PAREN expression (COMMA expression)* RIGHT_PAREN # ExplicitTupleInList
|
||||
| LEFT_PAREN subQuery RIGHT_PAREN # SubQueryInList
|
||||
| parameter # ParamInList
|
||||
|
@ -713,11 +720,13 @@ countFunction
|
|||
everyFunction
|
||||
: (EVERY|ALL) LEFT_PAREN predicate RIGHT_PAREN filterClause?
|
||||
| (EVERY|ALL) LEFT_PAREN subQuery RIGHT_PAREN
|
||||
| (EVERY|ALL) (ELEMENTS|INDICES) LEFT_PAREN dotIdentifierSequence RIGHT_PAREN
|
||||
;
|
||||
|
||||
anyFunction
|
||||
: (ANY|SOME) LEFT_PAREN predicate RIGHT_PAREN filterClause?
|
||||
| (ANY|SOME) LEFT_PAREN subQuery RIGHT_PAREN
|
||||
| (ANY|SOME) (ELEMENTS|INDICES) LEFT_PAREN dotIdentifierSequence RIGHT_PAREN
|
||||
;
|
||||
|
||||
filterClause
|
||||
|
@ -1170,6 +1179,7 @@ identifier
|
|||
| IFNULL
|
||||
| IN
|
||||
| INDEX
|
||||
| INDICES
|
||||
| INNER
|
||||
| INSERT
|
||||
| INSTANT
|
||||
|
|
|
@ -3810,8 +3810,8 @@ public abstract class Dialect implements ConversionContext {
|
|||
return null;
|
||||
}
|
||||
|
||||
public boolean supportsSelectAliasInGroupByClause() {
|
||||
return false;
|
||||
public SelectItemReferenceStrategy getGroupBySelectItemReferenceStrategy() {
|
||||
return SelectItemReferenceStrategy.EXPRESSION;
|
||||
}
|
||||
|
||||
public SizeStrategy getSizeStrategy() {
|
||||
|
|
|
@ -429,8 +429,8 @@ public class H2Dialect extends Dialect {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsSelectAliasInGroupByClause() {
|
||||
return true;
|
||||
public SelectItemReferenceStrategy getGroupBySelectItemReferenceStrategy() {
|
||||
return SelectItemReferenceStrategy.ALIAS;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -499,8 +499,8 @@ public class MySQLDialect extends Dialect {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsSelectAliasInGroupByClause() {
|
||||
return true;
|
||||
public SelectItemReferenceStrategy getGroupBySelectItemReferenceStrategy() {
|
||||
return SelectItemReferenceStrategy.POSITION;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -646,8 +646,8 @@ public class PostgreSQLDialect extends Dialect {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsSelectAliasInGroupByClause() {
|
||||
return true;
|
||||
public SelectItemReferenceStrategy getGroupBySelectItemReferenceStrategy() {
|
||||
return SelectItemReferenceStrategy.POSITION;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* 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.dialect;
|
||||
|
||||
/**
|
||||
* Strategies for referring to a select item.
|
||||
*
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public enum SelectItemReferenceStrategy {
|
||||
/**
|
||||
* The default strategy i.e. render the expression again.
|
||||
*/
|
||||
EXPRESSION,
|
||||
/**
|
||||
* Refer to the item via its alias.
|
||||
*/
|
||||
ALIAS,
|
||||
/**
|
||||
* Refer to the item via its position.
|
||||
*/
|
||||
POSITION;
|
||||
}
|
|
@ -29,7 +29,6 @@ class ListAttributeImpl<X, E> extends AbstractPluralAttribute<X, List<E>, E> imp
|
|||
|
||||
//noinspection unchecked
|
||||
this.indexPathSource = (SqmPathSource<Integer>) SqmMappingModelHelper.resolveSqmKeyPathSource(
|
||||
getName(),
|
||||
builder.getListIndexOrMapKeyType(),
|
||||
BindableType.PLURAL_ATTRIBUTE
|
||||
);
|
||||
|
|
|
@ -30,7 +30,6 @@ class MapAttributeImpl<X, K, V> extends AbstractPluralAttribute<X, Map<K, V>, V>
|
|||
super( xceBuilder, metadataContext );
|
||||
|
||||
this.keyPathSource = SqmMappingModelHelper.resolveSqmKeyPathSource(
|
||||
CollectionPart.Nature.INDEX.getName(),
|
||||
xceBuilder.getListIndexOrMapKeyType(),
|
||||
BindableType.PLURAL_ATTRIBUTE
|
||||
);
|
||||
|
|
|
@ -747,6 +747,10 @@ public class MappingMetamodelImpl implements MappingMetamodel, MetamodelImplemen
|
|||
return (MappingModelExpressable) sqmExpressable;
|
||||
}
|
||||
|
||||
if ( sqmExpressable instanceof EntityDomainType<?> ) {
|
||||
return getEntityDescriptor( ( (EntityDomainType<?>) sqmExpressable ).getHibernateEntityName() );
|
||||
}
|
||||
|
||||
throw new UnsupportedOperationException( "Cannot determine proper mapping model expressable for " + sqmExpressable );
|
||||
}
|
||||
|
||||
|
|
|
@ -1693,8 +1693,8 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
HqlParser.JpaCollectionJoinContext ctx,
|
||||
SqmRoot<?> sqmRoot) {
|
||||
final HqlParser.IdentificationVariableDefContext identificationVariableDefContext;
|
||||
if ( ctx.getChildCount() > 1 ) {
|
||||
identificationVariableDefContext = (HqlParser.IdentificationVariableDefContext) ctx.getChild( 1 );
|
||||
if ( ctx.getChildCount() > 5 ) {
|
||||
identificationVariableDefContext = (HqlParser.IdentificationVariableDefContext) ctx.getChild( 5 );
|
||||
}
|
||||
else {
|
||||
identificationVariableDefContext = null;
|
||||
|
@ -2047,13 +2047,35 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
else if ( inListContext instanceof HqlParser.PersistentCollectionReferenceInListContext ) {
|
||||
if ( getCreationOptions().useStrictJpaCompliance() ) {
|
||||
throw new StrictJpaComplianceViolation( StrictJpaComplianceViolation.Type.HQL_COLLECTION_FUNCTION );
|
||||
}
|
||||
final HqlParser.PersistentCollectionReferenceInListContext collectionReferenceInListContext = (HqlParser.PersistentCollectionReferenceInListContext) inListContext;
|
||||
return new SqmInSubQueryPredicate<>(
|
||||
testExpression,
|
||||
createCollectionReferenceSubQuery(
|
||||
(HqlParser.DotIdentifierSequenceContext) collectionReferenceInListContext.getChild( 2 ),
|
||||
(TerminalNode) collectionReferenceInListContext.getChild( 0 )
|
||||
),
|
||||
negated,
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
else {
|
||||
// todo : handle PersistentCollectionReferenceInList labeled branch
|
||||
|
||||
throw new ParsingException( "Unexpected IN predicate type [" + ctx.getClass().getSimpleName() + "] : " + ctx.getText() );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPredicate visitExistsCollectionPartPredicate(HqlParser.ExistsCollectionPartPredicateContext ctx) {
|
||||
final SqmSubQuery<Object> subQuery = createCollectionReferenceSubQuery(
|
||||
(HqlParser.DotIdentifierSequenceContext) ctx.getChild( 3 ),
|
||||
null
|
||||
);
|
||||
return new SqmExistsPredicate( subQuery, creationContext.getNodeBuilder() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPredicate visitExistsPredicate(HqlParser.ExistsPredicateContext ctx) {
|
||||
final SqmExpression<?> expression = (SqmExpression<?>) ctx.getChild( 1 ).accept( this );
|
||||
|
@ -3764,15 +3786,14 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
final SqmPredicate filterExpression = getFilterExpression( ctx );
|
||||
final ParseTree argumentChild = ctx.getChild( 2 );
|
||||
if ( argumentChild instanceof HqlParser.SubQueryContext ) {
|
||||
SqmSubQuery<?> subquery = (SqmSubQuery<?>) argumentChild.accept(this);
|
||||
final SqmSubQuery<?> subquery = (SqmSubQuery<?>) argumentChild.accept( this );
|
||||
return new SqmEvery<>( subquery, creationContext.getNodeBuilder() );
|
||||
}
|
||||
|
||||
final SqmExpression<?> argument = (SqmExpression<?>) argumentChild.accept( this );
|
||||
|
||||
if ( argument instanceof SqmSubQuery<?> && ctx.getChild( ctx.getChildCount() - 1) instanceof HqlParser.FilterClauseContext ) {
|
||||
throw new SemanticException( "Quantified expression cannot have a filter clause!" );
|
||||
else if ( argumentChild instanceof HqlParser.PredicateContext ) {
|
||||
if ( getCreationOptions().useStrictJpaCompliance() ) {
|
||||
throw new StrictJpaComplianceViolation( StrictJpaComplianceViolation.Type.FUNCTION_CALL );
|
||||
}
|
||||
final SqmExpression<?> argument = (SqmExpression<?>) argumentChild.accept( this );
|
||||
|
||||
return getFunctionDescriptor( "every" ).generateAggregateSqmExpression(
|
||||
singletonList( argument ),
|
||||
|
@ -3782,21 +3803,33 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
creationContext.getJpaMetamodel().getTypeConfiguration()
|
||||
);
|
||||
}
|
||||
else {
|
||||
if ( getCreationOptions().useStrictJpaCompliance() ) {
|
||||
throw new StrictJpaComplianceViolation( StrictJpaComplianceViolation.Type.HQL_COLLECTION_FUNCTION );
|
||||
}
|
||||
return new SqmEvery<>(
|
||||
createCollectionReferenceSubQuery(
|
||||
(HqlParser.DotIdentifierSequenceContext) ctx.getChild( 3 ),
|
||||
(TerminalNode) ctx.getChild( 1 )
|
||||
),
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmExpression<?> visitAnyFunction(HqlParser.AnyFunctionContext ctx) {
|
||||
final SqmPredicate filterExpression = getFilterExpression( ctx );
|
||||
final ParseTree argumentChild = ctx.getChild( 2 );
|
||||
if ( argumentChild instanceof HqlParser.SubQueryContext ) {
|
||||
SqmSubQuery<?> subquery = (SqmSubQuery<?>) argumentChild.accept(this);
|
||||
final SqmSubQuery<?> subquery = (SqmSubQuery<?>) argumentChild.accept( this );
|
||||
return new SqmAny<>( subquery, creationContext.getNodeBuilder() );
|
||||
}
|
||||
|
||||
final SqmExpression<?> argument = (SqmExpression<?>) argumentChild.accept( this );
|
||||
|
||||
if ( argument instanceof SqmSubQuery<?> && ctx.getChild( ctx.getChildCount() - 1) instanceof HqlParser.FilterClauseContext ) {
|
||||
throw new SemanticException( "Quantified expression cannot have a filter clause!" );
|
||||
else if ( argumentChild instanceof HqlParser.PredicateContext ) {
|
||||
if ( getCreationOptions().useStrictJpaCompliance() ) {
|
||||
throw new StrictJpaComplianceViolation( StrictJpaComplianceViolation.Type.FUNCTION_CALL );
|
||||
}
|
||||
final SqmExpression<?> argument = (SqmExpression<?>) argumentChild.accept( this );
|
||||
|
||||
return getFunctionDescriptor( "any" ).generateAggregateSqmExpression(
|
||||
singletonList( argument ),
|
||||
|
@ -3806,6 +3839,71 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
creationContext.getJpaMetamodel().getTypeConfiguration()
|
||||
);
|
||||
}
|
||||
else {
|
||||
if ( getCreationOptions().useStrictJpaCompliance() ) {
|
||||
throw new StrictJpaComplianceViolation( StrictJpaComplianceViolation.Type.HQL_COLLECTION_FUNCTION );
|
||||
}
|
||||
return new SqmAny<>(
|
||||
createCollectionReferenceSubQuery(
|
||||
(HqlParser.DotIdentifierSequenceContext) ctx.getChild( 3 ),
|
||||
(TerminalNode) ctx.getChild( 1 )
|
||||
),
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private <X> SqmSubQuery<X> createCollectionReferenceSubQuery(
|
||||
HqlParser.DotIdentifierSequenceContext pathCtx,
|
||||
TerminalNode collectionReferenceCtx) {
|
||||
final SqmPath<?> pluralAttributePath = consumeDomainPath( pathCtx );
|
||||
final SqmPathSource<?> referencedPathSource = pluralAttributePath.getReferencedPathSource();
|
||||
|
||||
if ( !(referencedPathSource instanceof PluralPersistentAttribute ) ) {
|
||||
throw new PathException(
|
||||
"Illegal attempt to treat non-plural path as a plural path : " + pluralAttributePath.getNavigablePath()
|
||||
);
|
||||
}
|
||||
final PluralPersistentAttribute<?, ?, ?> attribute = (PluralPersistentAttribute<?, ?, ?>) referencedPathSource;
|
||||
final SqmSubQuery<?> subQuery = new SqmSubQuery<>(
|
||||
processingStateStack.getCurrent().getProcessingQuery(),
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
final SqmSelectClause selectClause = new SqmSelectClause( false, 1, creationContext.getNodeBuilder() );
|
||||
final SqmFromClause fromClause = new SqmFromClause( 1 );
|
||||
final SqmCorrelation<?, ?> correlation = ( (AbstractSqmFrom<?, ?>) pluralAttributePath.getLhs() ).createCorrelation();
|
||||
final SqmAttributeJoin<?, ?> collectionJoin = correlation.join( pluralAttributePath.getNavigablePath().getUnaliasedLocalName() );
|
||||
fromClause.addRoot( correlation.getCorrelatedRoot() );
|
||||
if ( collectionReferenceCtx == null ) {
|
||||
final SqmLiteral<Integer> literal = new SqmLiteral<>(
|
||||
1,
|
||||
StandardBasicTypes.INTEGER,
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
subQuery.applyInferableType( literal.getNodeType() );
|
||||
selectClause.setSelection( literal );
|
||||
}
|
||||
else {
|
||||
final SqmPathSource<?> pathSource;
|
||||
switch ( collectionReferenceCtx.getSymbol().getType() ) {
|
||||
case HqlParser.ELEMENTS:
|
||||
pathSource = attribute.getElementPathSource();
|
||||
break;
|
||||
case HqlParser.INDICES:
|
||||
pathSource = attribute.getIndexPathSource();
|
||||
break;
|
||||
default:
|
||||
throw new ParsingException( "Unexpected collection reference : " + collectionReferenceCtx.getText() );
|
||||
}
|
||||
subQuery.applyInferableType( pathSource.getSqmPathType() );
|
||||
selectClause.setSelection( pathSource.createSqmPath( collectionJoin ) );
|
||||
}
|
||||
final SqmQuerySpec<?> querySpec = subQuery.getQuerySpec();
|
||||
querySpec.setFromClause( fromClause );
|
||||
querySpec.setSelectClause( selectClause );
|
||||
//noinspection unchecked
|
||||
return (SqmSubQuery<X>) subQuery;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmExpression<?> visitAvgFunction(HqlParser.AvgFunctionContext ctx) {
|
||||
|
@ -4216,6 +4314,9 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
else if ( firstChild instanceof HqlParser.CollectionElementNavigablePathContext ) {
|
||||
return visitCollectionElementNavigablePath( (HqlParser.CollectionElementNavigablePathContext) firstChild );
|
||||
}
|
||||
else if ( firstChild instanceof HqlParser.CollectionIndexNavigablePathContext ) {
|
||||
return visitCollectionIndexNavigablePath( (HqlParser.CollectionIndexNavigablePathContext) firstChild );
|
||||
}
|
||||
else if ( firstChild instanceof HqlParser.MapKeyNavigablePathContext ) {
|
||||
return visitMapKeyNavigablePath( (HqlParser.MapKeyNavigablePathContext) firstChild );
|
||||
}
|
||||
|
@ -4384,6 +4485,30 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
}
|
||||
|
||||
|
||||
@Override
|
||||
public SqmPath<?> visitCollectionIndexNavigablePath(HqlParser.CollectionIndexNavigablePathContext ctx) {
|
||||
final SqmPath<?> pluralAttributePath = consumeDomainPath( (HqlParser.PathContext) ctx.getChild( 2 ) );
|
||||
final SqmPathSource<?> referencedPathSource = pluralAttributePath.getReferencedPathSource();
|
||||
|
||||
if ( !(referencedPathSource instanceof PluralPersistentAttribute ) ) {
|
||||
throw new PathException(
|
||||
"Illegal attempt to treat non-plural path as a plural path : " + pluralAttributePath.getNavigablePath()
|
||||
);
|
||||
}
|
||||
|
||||
final PluralPersistentAttribute<?, ?, ?> attribute = (PluralPersistentAttribute<?, ?, ?>) referencedPathSource;
|
||||
|
||||
if ( getCreationOptions().useStrictJpaCompliance() ) {
|
||||
if ( attribute.getCollectionClassification() != CollectionClassification.MAP ) {
|
||||
throw new StrictJpaComplianceViolation( StrictJpaComplianceViolation.Type.VALUE_FUNCTION_ON_NON_MAP );
|
||||
}
|
||||
}
|
||||
|
||||
return attribute.getIndexPathSource().createSqmPath(
|
||||
pluralAttributePath
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "rawtypes" })
|
||||
public SqmPath visitMapKeyNavigablePath(HqlParser.MapKeyNavigablePathContext ctx) {
|
||||
|
|
|
@ -19,7 +19,7 @@ public class StrictJpaComplianceViolation extends SemanticException {
|
|||
ALIASED_FETCH_JOIN( "aliased fetch join" ),
|
||||
UNMAPPED_POLYMORPHISM( "unmapped polymorphic reference" ),
|
||||
FUNCTION_CALL( "improper non-standard function call" ),
|
||||
HQL_COLLECTION_FUNCTION( "use of HQL collection functions (maxelement, minelement, maxindex, minindex)"),
|
||||
HQL_COLLECTION_FUNCTION( "use of HQL collection functions (maxelement, minelement, maxindex, minindex, elements, indices)"),
|
||||
VALUE_FUNCTION_ON_NON_MAP( "use of value() function for non-Map type" ),
|
||||
RESERVED_WORD_USED_AS_ALIAS( "use of reserved word as alias (identification variable or result variable)" ),
|
||||
INDEXED_ELEMENT_REFERENCE( "use of HQL indexed element reference syntax" ),
|
||||
|
|
|
@ -11,9 +11,11 @@ import javax.persistence.metamodel.Bindable;
|
|||
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.metamodel.mapping.CollectionPart;
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.metamodel.mapping.MappingModelExpressable;
|
||||
import org.hibernate.metamodel.mapping.ModelPart;
|
||||
import org.hibernate.metamodel.mapping.ModelPartContainer;
|
||||
import org.hibernate.metamodel.model.domain.AnyMappingDomainType;
|
||||
import org.hibernate.metamodel.model.domain.BasicDomainType;
|
||||
import org.hibernate.metamodel.model.domain.DomainType;
|
||||
|
@ -61,11 +63,13 @@ public class SqmMappingModelHelper {
|
|||
}
|
||||
|
||||
public static <J> SqmPathSource<J> resolveSqmKeyPathSource(
|
||||
String name,
|
||||
DomainType<J> valueDomainType,
|
||||
Bindable.BindableType jpaBindableType) {
|
||||
// todo (6.0): the key path source must create a special path for the key
|
||||
return resolveSqmPathSource( name, valueDomainType, jpaBindableType );
|
||||
return resolveSqmPathSource(
|
||||
CollectionPart.Nature.INDEX.getName(),
|
||||
valueDomainType,
|
||||
jpaBindableType
|
||||
);
|
||||
}
|
||||
|
||||
public static <J> SqmPathSource<J> resolveSqmPathSource(
|
||||
|
@ -149,7 +153,11 @@ public class SqmMappingModelHelper {
|
|||
// Plural path parts are not joined and thus also have no table group
|
||||
if ( sqmPath instanceof AbstractSqmSpecificPluralPartPath<?> ) {
|
||||
final TableGroup lhsTableGroup = tableGroupLocator.apply( sqmPath.getLhs().getLhs().getNavigablePath() );
|
||||
return lhsTableGroup.getModelPart().findSubPart( sqmPath.getReferencedPathSource().getPathName(), null );
|
||||
final ModelPartContainer pluralPart = (ModelPartContainer) lhsTableGroup.getModelPart().findSubPart(
|
||||
sqmPath.getLhs().getReferencedPathSource().getPathName(),
|
||||
null
|
||||
);
|
||||
return pluralPart.findSubPart( sqmPath.getReferencedPathSource().getPathName(), null );
|
||||
}
|
||||
|
||||
final TableGroup lhsTableGroup = tableGroupLocator.apply( sqmPath.getLhs().getNavigablePath() );
|
||||
|
|
|
@ -20,6 +20,7 @@ import org.hibernate.engine.spi.SessionFactoryImplementor;
|
|||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.metamodel.MappingMetamodel;
|
||||
import org.hibernate.metamodel.mapping.Bindable;
|
||||
import org.hibernate.metamodel.mapping.CollectionPart;
|
||||
import org.hibernate.metamodel.mapping.ConvertibleModelPart;
|
||||
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
|
@ -328,6 +329,9 @@ public class SqmUtil {
|
|||
if ( parameterType == null ) {
|
||||
throw new SqlTreeCreationException( "Unable to interpret mapping-model type for Query parameter : " + domainParam );
|
||||
}
|
||||
if ( parameterType instanceof CollectionPart && ( (CollectionPart) parameterType ).getPartMappingType() instanceof Bindable ) {
|
||||
parameterType = (Bindable) ( (CollectionPart) parameterType ).getPartMappingType();
|
||||
}
|
||||
|
||||
if ( parameterType instanceof EntityIdentifierMapping ) {
|
||||
final EntityIdentifierMapping identifierMapping = (EntityIdentifierMapping) parameterType;
|
||||
|
@ -336,6 +340,14 @@ public class SqmUtil {
|
|||
bindValue = identifierMapping.getIdentifier( bindValue, session );
|
||||
}
|
||||
}
|
||||
else if ( parameterType instanceof EntityMappingType ) {
|
||||
final EntityIdentifierMapping identifierMapping = ( (EntityMappingType) parameterType ).getIdentifierMapping();
|
||||
final EntityMappingType entityMapping = identifierMapping.findContainingEntityMapping();
|
||||
parameterType = identifierMapping;
|
||||
if ( entityMapping.getRepresentationStrategy().getInstantiator().isInstance( bindValue, session.getFactory() ) ) {
|
||||
bindValue = identifierMapping.getIdentifier( bindValue, session );
|
||||
}
|
||||
}
|
||||
else if ( parameterType instanceof ToOneAttributeMapping ) {
|
||||
ToOneAttributeMapping association = (ToOneAttributeMapping) parameterType;
|
||||
bindValue = association.getForeignKeyDescriptor().getAssociationKeyFromSide(
|
||||
|
|
|
@ -45,6 +45,7 @@ import org.hibernate.metamodel.MappingMetamodel;
|
|||
import org.hibernate.metamodel.mapping.Association;
|
||||
import org.hibernate.metamodel.mapping.AttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.BasicValuedMapping;
|
||||
import org.hibernate.metamodel.mapping.Bindable;
|
||||
import org.hibernate.metamodel.mapping.CollectionPart;
|
||||
import org.hibernate.metamodel.mapping.ConvertibleModelPart;
|
||||
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
|
||||
|
@ -52,6 +53,7 @@ import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
|
|||
import org.hibernate.metamodel.mapping.EntityAssociationMapping;
|
||||
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
|
||||
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.metamodel.mapping.EntityValuedModelPart;
|
||||
import org.hibernate.metamodel.mapping.EntityVersionMapping;
|
||||
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
|
||||
|
@ -2747,18 +2749,20 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
MappingModelExpressable valueMapping,
|
||||
BiConsumer<Integer,JdbcParameter> jdbcParameterConsumer) {
|
||||
sqmParameterMappingModelTypes.put( expression, valueMapping );
|
||||
|
||||
final Bindable bindable;
|
||||
if ( valueMapping instanceof Association ) {
|
||||
( (Association) valueMapping ).getForeignKeyDescriptor().forEachJdbcType(
|
||||
(index, jdbcMapping) -> jdbcParameterConsumer.accept( index, new JdbcParameterImpl( jdbcMapping ) )
|
||||
);
|
||||
bindable = ( (Association) valueMapping ).getForeignKeyDescriptor();
|
||||
}
|
||||
else if ( valueMapping instanceof EntityMappingType ) {
|
||||
bindable = ( (EntityMappingType) valueMapping ).getIdentifierMapping();
|
||||
}
|
||||
else {
|
||||
valueMapping.forEachJdbcType(
|
||||
bindable = valueMapping;
|
||||
}
|
||||
bindable.forEachJdbcType(
|
||||
(index, jdbcMapping) -> jdbcParameterConsumer.accept( index, new JdbcParameterImpl( jdbcMapping ) )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitPositionalParameterExpression(SqmPositionalParameter expression) {
|
||||
|
@ -4098,26 +4102,47 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
final CollectionPart collectionPart = index
|
||||
? mappingModelExpressable.getIndexDescriptor()
|
||||
: mappingModelExpressable.getElementDescriptor();
|
||||
final List<SqlAstNode> arguments = new ArrayList<>( 1 );
|
||||
final ModelPart modelPart;
|
||||
if ( collectionPart instanceof EntityAssociationMapping ) {
|
||||
modelPart = ( (EntityAssociationMapping) collectionPart ).getKeyTargetMatchPart();
|
||||
}
|
||||
else {
|
||||
modelPart = collectionPart;
|
||||
}
|
||||
final List<Expression> arguments = new ArrayList<>( 1 );
|
||||
final NavigablePath navigablePath = pluralPartPath.getNavigablePath();
|
||||
collectionPart.forEachSelectable(
|
||||
final int jdbcTypeCount = modelPart.getJdbcTypeCount();
|
||||
final List<Expression> tupleElements;
|
||||
if ( jdbcTypeCount == 1 ) {
|
||||
tupleElements = arguments;
|
||||
}
|
||||
else {
|
||||
tupleElements = new ArrayList<>( jdbcTypeCount );
|
||||
}
|
||||
modelPart.forEachSelectable(
|
||||
(selectionIndex, selectionMapping) -> {
|
||||
arguments.add(
|
||||
tupleElements.add(
|
||||
new ColumnReference(
|
||||
tableGroup.getTableReference( navigablePath, selectionMapping.getContainingTableExpression() ),
|
||||
tableGroup.getTableReference(
|
||||
navigablePath,
|
||||
selectionMapping.getContainingTableExpression()
|
||||
),
|
||||
selectionMapping,
|
||||
creationContext.getSessionFactory()
|
||||
)
|
||||
);
|
||||
}
|
||||
);
|
||||
if ( jdbcTypeCount != 1 ) {
|
||||
arguments.add( new SqlTuple( tupleElements, modelPart ) );
|
||||
}
|
||||
final Expression expression = new SelfRenderingAggregateFunctionSqlAstExpression(
|
||||
functionDescriptor.getName(),
|
||||
functionDescriptor::render,
|
||||
arguments,
|
||||
(List<SqlAstNode>) (List<?>) arguments,
|
||||
null,
|
||||
(AllowableFunctionReturnType<?>) collectionPart.getJdbcMappings().get( 0 ),
|
||||
collectionPart
|
||||
(AllowableFunctionReturnType<?>) modelPart.getJdbcMappings().get( 0 ),
|
||||
modelPart
|
||||
);
|
||||
subQuerySpec.getSelectClause().addSqlSelection( new SqlSelectionImpl( 1, 0, expression ) );
|
||||
|
||||
|
|
|
@ -85,7 +85,7 @@ public class EntityValuedPathInterpretation<T> extends AbstractSqmPathInterpreta
|
|||
final EntityIdentifierMapping identifierMapping = entityMappingType.getIdentifierMapping();
|
||||
final EntityDiscriminatorMapping discriminatorMapping = entityMappingType.getDiscriminatorMapping();
|
||||
final List<Expression> expressions = new ArrayList<>(
|
||||
mapping.getJdbcTypeCount() + identifierMapping.getJdbcTypeCount()
|
||||
entityMappingType.getJdbcTypeCount() + identifierMapping.getJdbcTypeCount()
|
||||
+ ( discriminatorMapping == null ? 0 : 1 )
|
||||
);
|
||||
final SelectableConsumer selectableConsumer = (selectionIndex, selectableMapping) -> {
|
||||
|
@ -111,8 +111,8 @@ public class EntityValuedPathInterpretation<T> extends AbstractSqmPathInterpreta
|
|||
if ( discriminatorMapping != null ) {
|
||||
discriminatorMapping.forEachSelectable( selectableConsumer );
|
||||
}
|
||||
mapping.forEachSelectable( selectableConsumer );
|
||||
sqlExpression = new SqlTuple( expressions, mapping );
|
||||
entityMappingType.forEachSelectable( selectableConsumer );
|
||||
sqlExpression = new SqlTuple( expressions, entityMappingType );
|
||||
}
|
||||
else if ( mapping instanceof EntityAssociationMapping ) {
|
||||
final EntityAssociationMapping associationMapping = (EntityAssociationMapping) mapping;
|
||||
|
|
|
@ -14,7 +14,6 @@ import org.hibernate.query.sqm.SqmPathSource;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public abstract class AbstractSqmSimplePath<T> extends AbstractSqmPath<T> implements SqmSimplePath<T> {
|
||||
private final NavigablePath navigablePath;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public AbstractSqmSimplePath(
|
||||
|
@ -32,17 +31,11 @@ public abstract class AbstractSqmSimplePath<T> extends AbstractSqmPath<T> implem
|
|||
SqmPath lhs,
|
||||
String explicitAlias,
|
||||
NodeBuilder nodeBuilder) {
|
||||
super( referencedPathSource, lhs, nodeBuilder );
|
||||
this.navigablePath = navigablePath;
|
||||
super( navigablePath, referencedPathSource, lhs, nodeBuilder );
|
||||
|
||||
setExplicitAlias( explicitAlias );
|
||||
}
|
||||
|
||||
@Override
|
||||
public NavigablePath getNavigablePath() {
|
||||
return navigablePath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendHqlString(StringBuilder sb) {
|
||||
if ( getLhs() != null ) {
|
||||
|
|
|
@ -16,7 +16,6 @@ import org.hibernate.query.PathException;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public abstract class AbstractSqmSpecificPluralPartPath<T> extends AbstractSqmPath<T> implements SqmPath<T> {
|
||||
private final NavigablePath navigablePath;
|
||||
private final SqmPath pluralDomainPath;
|
||||
private final PluralPersistentAttribute<?,?,T> pluralAttribute;
|
||||
|
||||
|
@ -33,7 +32,6 @@ public abstract class AbstractSqmSpecificPluralPartPath<T> extends AbstractSqmPa
|
|||
pluralDomainPath,
|
||||
pluralDomainPath.nodeBuilder()
|
||||
);
|
||||
this.navigablePath = navigablePath;
|
||||
this.pluralDomainPath = pluralDomainPath;
|
||||
this.pluralAttribute = referencedAttribute;
|
||||
}
|
||||
|
@ -48,11 +46,6 @@ public abstract class AbstractSqmSpecificPluralPartPath<T> extends AbstractSqmPa
|
|||
return pluralAttribute;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NavigablePath getNavigablePath() {
|
||||
return navigablePath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPath getLhs() {
|
||||
return pluralDomainPath;
|
||||
|
|
|
@ -17,7 +17,12 @@ public class SqmCorrelatedRoot<T> extends SqmRoot<T> implements SqmPathWrapper<T
|
|||
private final SqmRoot<T> correlationParent;
|
||||
|
||||
public SqmCorrelatedRoot(SqmRoot<T> correlationParent) {
|
||||
super( correlationParent.getReferencedPathSource(), null, correlationParent.nodeBuilder() );
|
||||
super(
|
||||
correlationParent.getNavigablePath(),
|
||||
correlationParent.getReferencedPathSource(),
|
||||
null,
|
||||
correlationParent.nodeBuilder()
|
||||
);
|
||||
this.correlationParent = correlationParent;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ import java.util.function.Function;
|
|||
import org.hibernate.LockMode;
|
||||
import org.hibernate.QueryException;
|
||||
import org.hibernate.dialect.RowLockStrategy;
|
||||
import org.hibernate.dialect.SelectItemReferenceStrategy;
|
||||
import org.hibernate.metamodel.mapping.EntityAssociationMapping;
|
||||
import org.hibernate.metamodel.mapping.ModelPart;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
|
@ -1480,7 +1481,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
|
|||
visitSelectClause( querySpec.getSelectClause() );
|
||||
visitFromClause( querySpec.getFromClause() );
|
||||
visitWhereClause( querySpec );
|
||||
visitGroupByClause( querySpec, dialect.supportsSelectAliasInGroupByClause() );
|
||||
visitGroupByClause( querySpec, dialect.getGroupBySelectItemReferenceStrategy() );
|
||||
visitHavingClause( querySpec );
|
||||
visitOrderBy( querySpec.getSortSpecifications() );
|
||||
visitOffsetFetchClause( querySpec );
|
||||
|
@ -1556,13 +1557,38 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
|
|||
return expression;
|
||||
}
|
||||
|
||||
protected final void visitGroupByClause(QuerySpec querySpec, boolean supportsSelectAliases) {
|
||||
protected Expression resolveExpressionToAlias(Expression expression) {
|
||||
int index = -1;
|
||||
if ( expression instanceof SqlSelectionExpression ) {
|
||||
index = ( (SqlSelectionExpression) expression ).getSelection().getValuesArrayPosition();
|
||||
}
|
||||
else if ( expression instanceof SqmPathInterpretation<?> ) {
|
||||
final Expression sqlExpression = ( (SqmPathInterpretation<?>) expression ).getSqlExpression();
|
||||
if ( sqlExpression instanceof SqlSelectionExpression ) {
|
||||
index = ( (SqlSelectionExpression) sqlExpression ).getSelection().getValuesArrayPosition();
|
||||
}
|
||||
}
|
||||
if ( index == -1 ) {
|
||||
return expression;
|
||||
}
|
||||
return new ColumnReference(
|
||||
(String) null,
|
||||
"c" + index,
|
||||
false,
|
||||
null,
|
||||
null,
|
||||
expression.getExpressionType().getJdbcMappings().get( 0 ),
|
||||
sessionFactory
|
||||
);
|
||||
}
|
||||
|
||||
protected final void visitGroupByClause(QuerySpec querySpec, SelectItemReferenceStrategy referenceStrategy) {
|
||||
final List<Expression> partitionExpressions = querySpec.getGroupByClauseExpressions();
|
||||
if ( !partitionExpressions.isEmpty() ) {
|
||||
try {
|
||||
clauseStack.push( Clause.GROUP );
|
||||
appendSql( " group by " );
|
||||
visitPartitionExpressions( partitionExpressions, supportsSelectAliases );
|
||||
visitPartitionExpressions( partitionExpressions, referenceStrategy );
|
||||
}
|
||||
finally {
|
||||
clauseStack.pop();
|
||||
|
@ -1575,7 +1601,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
|
|||
try {
|
||||
clauseStack.push( Clause.PARTITION );
|
||||
appendSql( "partition by " );
|
||||
visitPartitionExpressions( partitionExpressions, false );
|
||||
visitPartitionExpressions( partitionExpressions, SelectItemReferenceStrategy.EXPRESSION );
|
||||
}
|
||||
finally {
|
||||
clauseStack.pop();
|
||||
|
@ -1585,13 +1611,21 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
|
|||
|
||||
protected final void visitPartitionExpressions(
|
||||
List<Expression> partitionExpressions,
|
||||
boolean supportsSelectAliases) {
|
||||
if ( supportsSelectAliases ) {
|
||||
visitPartitionExpressions( partitionExpressions, expression -> expression );
|
||||
}
|
||||
else {
|
||||
visitPartitionExpressions( partitionExpressions, expression -> resolveAliasedExpression( expression ) );
|
||||
SelectItemReferenceStrategy referenceStrategy) {
|
||||
final Function<Expression, Expression> resolveAliasExpression;
|
||||
switch ( referenceStrategy ) {
|
||||
case POSITION:
|
||||
resolveAliasExpression = Function.identity();
|
||||
break;
|
||||
case ALIAS:
|
||||
resolveAliasExpression = this::resolveExpressionToAlias;
|
||||
break;
|
||||
case EXPRESSION:
|
||||
default:
|
||||
resolveAliasExpression = this::resolveAliasedExpression;
|
||||
break;
|
||||
}
|
||||
visitPartitionExpressions( partitionExpressions, resolveAliasExpression );
|
||||
}
|
||||
|
||||
protected final void visitPartitionExpressions(
|
||||
|
@ -2862,7 +2896,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
|
|||
protected void visitSqlSelections(SelectClause selectClause) {
|
||||
final List<SqlSelection> sqlSelections = selectClause.getSqlSelections();
|
||||
final int size = sqlSelections.size();
|
||||
if ( needsSelectAliases ) {
|
||||
if ( needsSelectAliases || needsSelectAliasesForGroupOrOrderByClause() ) {
|
||||
String separator = NO_SEPARATOR;
|
||||
for ( int i = 0; i < size; i++ ) {
|
||||
final SqlSelection sqlSelection = sqlSelections.get( i );
|
||||
|
@ -2887,6 +2921,40 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
|
|||
}
|
||||
}
|
||||
|
||||
private boolean needsSelectAliasesForGroupOrOrderByClause() {
|
||||
if ( dialect.getGroupBySelectItemReferenceStrategy() == SelectItemReferenceStrategy.ALIAS ) {
|
||||
final QuerySpec querySpec = (QuerySpec) getQueryPartStack().getCurrent();
|
||||
for ( Expression groupByClauseExpression : querySpec.getGroupByClauseExpressions() ) {
|
||||
if ( isSelectItemReference( groupByClauseExpression ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if ( querySpec.hasSortSpecifications() ) {
|
||||
for ( SortSpecification sortSpecification : querySpec.getSortSpecifications() ) {
|
||||
if ( isSelectItemReference( sortSpecification.getSortExpression() ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected final boolean isSelectItemReference(Expression expression) {
|
||||
final SqlTuple sqlTuple = SqlTupleContainer.getSqlTuple( expression );
|
||||
if ( sqlTuple != null ) {
|
||||
for ( Expression e : sqlTuple.getExpressions() ) {
|
||||
if ( e instanceof SqlSelectionExpression ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( expression instanceof SqlSelectionExpression ) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void renderRowNumberingSelectItems(SelectClause selectClause, QueryPart queryPart) {
|
||||
final FetchClauseType fetchClauseType = getFetchClauseTypeForRowNumbering( queryPart );
|
||||
if ( fetchClauseType != null ) {
|
||||
|
@ -4329,7 +4397,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
|
|||
.isEmpty() || subQuery.getHavingClauseRestrictions() != null ) {
|
||||
// If we have a group by or having clause, we have to move the tuple comparison emulation to the HAVING clause
|
||||
visitWhereClause( subQuery );
|
||||
visitGroupByClause( subQuery, false );
|
||||
visitGroupByClause( subQuery, SelectItemReferenceStrategy.EXPRESSION );
|
||||
|
||||
appendSql( " having " );
|
||||
clauseStack.push( Clause.HAVING );
|
||||
|
@ -4421,7 +4489,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
|
|||
visitSelectClause( subQuery.getSelectClause() );
|
||||
visitFromClause( subQuery.getFromClause() );
|
||||
visitWhereClause( subQuery );
|
||||
visitGroupByClause( subQuery, dialect.supportsSelectAliasInGroupByClause() );
|
||||
visitGroupByClause( subQuery, dialect.getGroupBySelectItemReferenceStrategy() );
|
||||
visitHavingClause( subQuery );
|
||||
|
||||
appendSql( " order by " );
|
||||
|
|
|
@ -7,8 +7,7 @@
|
|||
package org.hibernate.query;
|
||||
|
||||
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||
import org.hibernate.testing.DialectChecks;
|
||||
import org.hibernate.testing.RequiresDialectFeature;
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.jdbc.SQLStatementInterceptor;
|
||||
import org.junit.Test;
|
||||
|
||||
|
@ -30,7 +29,7 @@ import static org.junit.Assert.assertNotNull;
|
|||
* @author Jan-Willem Gmelig Meyling
|
||||
* @author Sayra Ranjha
|
||||
*/
|
||||
@RequiresDialectFeature(value = DialectChecks.SupportsSelectAliasInGroupByClause.class, jiraKey = "HHH-9301")
|
||||
@TestForIssue( jiraKey = "HHH-9301" )
|
||||
public class GroupByAliasTest extends BaseEntityManagerFunctionalTestCase {
|
||||
|
||||
public static final int MAX_COUNT = 15;
|
||||
|
|
|
@ -281,12 +281,6 @@ abstract public class DialectChecks {
|
|||
}
|
||||
}
|
||||
|
||||
public static class SupportsSelectAliasInGroupByClause implements DialectCheck {
|
||||
public boolean isMatch(Dialect dialect) {
|
||||
return dialect.supportsSelectAliasInGroupByClause();
|
||||
}
|
||||
}
|
||||
|
||||
public static class SupportsNClob implements DialectCheck {
|
||||
@Override
|
||||
public boolean isMatch(Dialect dialect) {
|
||||
|
|
Loading…
Reference in New Issue