HHH-18850 fix count queries with 'distinct' and 'order by'
This commit is contained in:
parent
7cdab319fb
commit
9a219c2c30
|
@ -6,13 +6,15 @@ package org.hibernate.query.sqm.tree.select;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmAliasedNodeRef;
|
import org.hibernate.query.sqm.tree.expression.SqmAliasedNodeRef;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
||||||
|
|
||||||
|
import static java.util.Collections.emptyList;
|
||||||
|
import static java.util.Collections.unmodifiableList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
|
@ -69,12 +71,7 @@ public class SqmOrderByClause implements Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<SqmSortSpecification> getSortSpecifications() {
|
public List<SqmSortSpecification> getSortSpecifications() {
|
||||||
if ( sortSpecifications == null ) {
|
return sortSpecifications == null ? emptyList() : unmodifiableList( sortSpecifications );
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return Collections.unmodifiableList( sortSpecifications );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSortSpecifications(List<SqmSortSpecification> sortSpecifications) {
|
public void setSortSpecifications(List<SqmSortSpecification> sortSpecifications) {
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.query.sqm.tree.select;
|
package org.hibernate.query.sqm.tree.select;
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.hibernate.query.common.FetchClauseType;
|
import org.hibernate.query.common.FetchClauseType;
|
||||||
|
@ -16,6 +15,8 @@ import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||||
import org.hibernate.query.sqm.tree.SqmVisitableNode;
|
import org.hibernate.query.sqm.tree.SqmVisitableNode;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
||||||
|
|
||||||
|
import static java.util.Collections.emptyList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines the ordering and fetch/offset part of a query which is shared with query groups.
|
* Defines the ordering and fetch/offset part of a query which is shared with query groups.
|
||||||
*
|
*
|
||||||
|
@ -127,11 +128,7 @@ public abstract class SqmQueryPart<T> implements SqmVisitableNode, JpaQueryPart<
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<SqmSortSpecification> getSortSpecifications() {
|
public List<SqmSortSpecification> getSortSpecifications() {
|
||||||
if ( getOrderByClause() == null ) {
|
return getOrderByClause() == null ? emptyList() : getOrderByClause().getSortSpecifications();
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
return getOrderByClause().getSortSpecifications();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -549,6 +549,9 @@ public class SqmSelectStatement<T> extends AbstractSqmSelectQuery<T> implements
|
||||||
final SqmSelectStatement<Long> query = nodeBuilder().createQuery( Long.class );
|
final SqmSelectStatement<Long> query = nodeBuilder().createQuery( Long.class );
|
||||||
query.from( subquery );
|
query.from( subquery );
|
||||||
query.select( nodeBuilder().count() );
|
query.select( nodeBuilder().count() );
|
||||||
|
if ( subquery.getFetch() == null && subquery.getOffset() == null ) {
|
||||||
|
subquery.getQueryPart().setOrderByClause( null );
|
||||||
|
}
|
||||||
return query;
|
return query;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
*
|
* Copyright Red Hat Inc. and Hibernate Authors
|
||||||
* 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.id.idClass;
|
package org.hibernate.orm.test.id.idClass;
|
||||||
|
|
||||||
|
|
|
@ -84,6 +84,48 @@ public class CountQueryTests {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@JiraKey( "HHH-18850" )
|
||||||
|
public void testForHHH18850(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
HibernateCriteriaBuilder cb = session.getCriteriaBuilder();
|
||||||
|
JpaCriteriaQuery<Contract> cq = cb.createQuery( Contract.class );
|
||||||
|
cq.distinct( true );
|
||||||
|
Root<Contract> root = cq.from( Contract.class );
|
||||||
|
cq.select( root );
|
||||||
|
cq.orderBy( cb.asc( root.get( "customerName" ) ) );
|
||||||
|
TypedQuery<Long> query = session.createQuery( cq.createCountQuery() );
|
||||||
|
try {
|
||||||
|
// Leads to NPE on pre-6.5 versions
|
||||||
|
query.getSingleResult();
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
fail( e );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
HibernateCriteriaBuilder cb = session.getCriteriaBuilder();
|
||||||
|
JpaCriteriaQuery<Contract> cq = cb.createQuery( Contract.class );
|
||||||
|
cq.distinct( false );
|
||||||
|
Root<Contract> root = cq.from( Contract.class );
|
||||||
|
cq.select( root );
|
||||||
|
cq.orderBy( cb.desc( root.get( "customerName" ) ) );
|
||||||
|
TypedQuery<Long> query = session.createQuery( cq.createCountQuery() );
|
||||||
|
try {
|
||||||
|
// Leads to NPE on pre-6.5 versions
|
||||||
|
query.getSingleResult();
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
fail( e );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@JiraKey("HHH-17410")
|
@JiraKey("HHH-17410")
|
||||||
public void testBasic(SessionFactoryScope scope) {
|
public void testBasic(SessionFactoryScope scope) {
|
||||||
|
|
Loading…
Reference in New Issue