HHH-16931 replace the previous impl of createCountQuery()
This commit is contained in:
parent
1180be0a0f
commit
a562ab2462
|
@ -30,7 +30,7 @@ import java.sql.Timestamp;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
|
|
||||||
import static java.sql.Types.TIMESTAMP;
|
import static java.sql.Types.TIMESTAMP;
|
||||||
import static org.hibernate.generator.EventTypeSets.INSERT_ONLY;
|
import static org.hibernate.generator.EventTypeSets.INSERT_AND_UPDATE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Value generation strategy using the query {@link Dialect#getCurrentTimestampSelectString()}.
|
* Value generation strategy using the query {@link Dialect#getCurrentTimestampSelectString()}.
|
||||||
|
@ -74,7 +74,7 @@ public class SourceGeneration implements BeforeExecutionGenerator {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public EnumSet<EventType> getEventTypes() {
|
public EnumSet<EventType> getEventTypes() {
|
||||||
return INSERT_ONLY;
|
return INSERT_AND_UPDATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -27,9 +27,11 @@ import org.hibernate.query.sqm.FetchClauseType;
|
||||||
public interface JpaCriteriaQuery<T> extends CriteriaQuery<T>, JpaQueryableCriteria<T>, JpaSelectCriteria<T> {
|
public interface JpaCriteriaQuery<T> extends CriteriaQuery<T>, JpaQueryableCriteria<T>, JpaSelectCriteria<T> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wraps this query in a subquery and returns a count query based on that subquery in the from clause.
|
* A query that returns the number of results of this query.
|
||||||
*
|
*
|
||||||
* @since 6.4
|
* @since 6.4
|
||||||
|
*
|
||||||
|
* @see org.hibernate.query.SelectionQuery#getResultCount()
|
||||||
*/
|
*/
|
||||||
JpaCriteriaQuery<Long> createCountQuery();
|
JpaCriteriaQuery<Long> createCountQuery();
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.query.sqm.tree.select;
|
package org.hibernate.query.sqm.tree.select;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -21,7 +20,6 @@ import jakarta.persistence.criteria.ParameterExpression;
|
||||||
import jakarta.persistence.criteria.Predicate;
|
import jakarta.persistence.criteria.Predicate;
|
||||||
import jakarta.persistence.criteria.Selection;
|
import jakarta.persistence.criteria.Selection;
|
||||||
|
|
||||||
import org.hibernate.Internal;
|
|
||||||
import org.hibernate.query.sqm.FetchClauseType;
|
import org.hibernate.query.sqm.FetchClauseType;
|
||||||
import org.hibernate.query.criteria.JpaCriteriaQuery;
|
import org.hibernate.query.criteria.JpaCriteriaQuery;
|
||||||
import org.hibernate.query.criteria.JpaExpression;
|
import org.hibernate.query.criteria.JpaExpression;
|
||||||
|
@ -115,54 +113,6 @@ public class SqmSelectStatement<T> extends AbstractSqmSelectQuery<T> implements
|
||||||
this.parameters = parameters;
|
this.parameters = parameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* A query that returns the number of results of this query.
|
|
||||||
*
|
|
||||||
* @since 6.5
|
|
||||||
*/
|
|
||||||
@Internal
|
|
||||||
public SqmSelectStatement<Long> countQuery() {
|
|
||||||
final SqmSelectStatement<?> copy = copy( noParamCopyContext() );
|
|
||||||
final SqmQuerySpec<?> querySpec = copy.getQuerySpec();
|
|
||||||
final SqmQueryPart<?> queryPart = copy.getQueryPart();
|
|
||||||
//TODO: detect queries with no 'group by', but aggregate functions
|
|
||||||
// in 'select' list (we don't even need to hit the database to
|
|
||||||
// know they return exactly one row)
|
|
||||||
if ( queryPart.isSimpleQueryPart()
|
|
||||||
&& !querySpec.isDistinct()
|
|
||||||
&& querySpec.getGroupingExpressions().isEmpty() ) {
|
|
||||||
for ( SqmRoot<?> root : querySpec.getRootList() ) {
|
|
||||||
root.removeLeftFetchJoins();
|
|
||||||
}
|
|
||||||
querySpec.getSelectClause().setSelection( nodeBuilder().count() );
|
|
||||||
if ( querySpec.getFetch() == null && querySpec.getOffset() == null ) {
|
|
||||||
querySpec.setOrderByClause( null );
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
final SqmSelectStatement<Long> statement = (SqmSelectStatement<Long>) copy;
|
|
||||||
statement.setResultType( Long.class );
|
|
||||||
return statement;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
final JpaSelection<?> selection = querySpec.getSelection();
|
|
||||||
if ( selection.isCompoundSelection() ) {
|
|
||||||
char c = 'a';
|
|
||||||
for ( JpaSelection<?> item: selection.getSelectionItems() ) {
|
|
||||||
item.alias( Character.toString(++c) + '_' );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
selection.alias("a_");
|
|
||||||
}
|
|
||||||
final SqmSubQuery<?> subquery = new SqmSubQuery<>( copy, queryPart, null, nodeBuilder() );
|
|
||||||
final SqmSelectStatement<Long> query = nodeBuilder().createQuery(Long.class);
|
|
||||||
query.from( subquery );
|
|
||||||
query.select( nodeBuilder().count() );
|
|
||||||
return query;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmSelectStatement<T> copy(SqmCopyContext context) {
|
public SqmSelectStatement<T> copy(SqmCopyContext context) {
|
||||||
final SqmSelectStatement<T> existing = context.getCopy( this );
|
final SqmSelectStatement<T> existing = context.getCopy( this );
|
||||||
|
@ -511,83 +461,44 @@ public class SqmSelectStatement<T> extends AbstractSqmSelectQuery<T> implements
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmSelectStatement<Long> createCountQuery() {
|
public SqmSelectStatement<Long> createCountQuery() {
|
||||||
final SqmCopyContext copyContext = noParamCopyContext();
|
final SqmSelectStatement<?> copy = copy( noParamCopyContext() );
|
||||||
|
final SqmQuerySpec<?> querySpec = copy.getQuerySpec();
|
||||||
final SqmQueryPart<T> queryPart = getQueryPart().copy( copyContext );
|
final SqmQueryPart<?> queryPart = copy.getQueryPart();
|
||||||
resetSelections( queryPart );
|
//TODO: detect queries with no 'group by', but aggregate functions
|
||||||
if ( queryPart.getFetch() == null && queryPart.getOffset() == null ) {
|
// in 'select' list (we don't even need to hit the database to
|
||||||
queryPart.setOrderByClause( null );
|
// know they return exactly one row)
|
||||||
}
|
if ( queryPart.isSimpleQueryPart()
|
||||||
if ( queryPart.isSimpleQueryPart() ) {
|
&& !querySpec.isDistinct()
|
||||||
for ( SqmRoot<?> root : queryPart.getFirstQuerySpec().getRootList() ) {
|
&& querySpec.getGroupingExpressions().isEmpty() ) {
|
||||||
|
for ( SqmRoot<?> root : querySpec.getRootList() ) {
|
||||||
root.removeLeftFetchJoins();
|
root.removeLeftFetchJoins();
|
||||||
}
|
}
|
||||||
}
|
querySpec.getSelectClause().setSelection( nodeBuilder().count() );
|
||||||
|
if ( querySpec.getFetch() == null && querySpec.getOffset() == null ) {
|
||||||
|
querySpec.setOrderByClause( null );
|
||||||
|
}
|
||||||
|
|
||||||
final NodeBuilder nodeBuilder = nodeBuilder();
|
@SuppressWarnings("unchecked")
|
||||||
final Set<SqmParameter<?>> parameters = copyParameters( copyContext );
|
final SqmSelectStatement<Long> statement = (SqmSelectStatement<Long>) copy;
|
||||||
final SqmSelectStatement<Long> selectStatement = new SqmSelectStatement<>(
|
statement.setResultType( Long.class );
|
||||||
nodeBuilder,
|
return statement;
|
||||||
copyCteStatements( copyContext ),
|
|
||||||
Long.class,
|
|
||||||
CRITERIA,
|
|
||||||
parameters
|
|
||||||
);
|
|
||||||
final SqmSubQuery<Tuple> subquery = new SqmSubQuery<>( selectStatement, Tuple.class, nodeBuilder );
|
|
||||||
//noinspection unchecked
|
|
||||||
subquery.setQueryPart( (SqmQueryPart<Tuple>) queryPart );
|
|
||||||
final SqmQuerySpec<Long> querySpec = new SqmQuerySpec<>( nodeBuilder );
|
|
||||||
querySpec.setFromClause( new SqmFromClause( 1 ) );
|
|
||||||
querySpec.setSelectClause( new SqmSelectClause( false, 1, nodeBuilder ) );
|
|
||||||
selectStatement.setQueryPart( querySpec );
|
|
||||||
selectStatement.select( nodeBuilder.count() );
|
|
||||||
selectStatement.from( subquery );
|
|
||||||
return selectStatement;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Set<SqmParameter<?>> copyParameters(SqmCopyContext context) {
|
|
||||||
if ( parameters == null ) {
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
final Set<SqmParameter<?>> copied = new LinkedHashSet<>( parameters.size() );
|
final JpaSelection<?> selection = querySpec.getSelection();
|
||||||
for ( SqmParameter<?> parameter : parameters ) {
|
if ( selection.isCompoundSelection() ) {
|
||||||
copied.add( parameter.copy(context) );
|
char c = 'a';
|
||||||
|
for ( JpaSelection<?> item: selection.getSelectionItems() ) {
|
||||||
|
item.alias( Character.toString(++c) + '_' );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return copied;
|
else {
|
||||||
|
selection.alias("a_");
|
||||||
|
}
|
||||||
|
final SqmSubQuery<?> subquery = new SqmSubQuery<>( copy, queryPart, null, nodeBuilder() );
|
||||||
|
final SqmSelectStatement<Long> query = nodeBuilder().createQuery(Long.class);
|
||||||
|
query.from( subquery );
|
||||||
|
query.select( nodeBuilder().count() );
|
||||||
|
return query;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void resetSelections(SqmQueryPart<?> queryPart) {
|
|
||||||
if ( queryPart instanceof SqmQuerySpec<?> ) {
|
|
||||||
resetSelections( (SqmQuerySpec<?>) queryPart );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
final SqmQueryGroup<?> group = (SqmQueryGroup<?>) queryPart;
|
|
||||||
for ( SqmQueryPart<?> part : group.getQueryParts() ) {
|
|
||||||
resetSelections( part );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void resetSelections(SqmQuerySpec<?> querySpec) {
|
|
||||||
final NodeBuilder nodeBuilder = nodeBuilder();
|
|
||||||
final List<SqmSelection<?>> selections = querySpec.getSelectClause().getSelections();
|
|
||||||
final List<SqmSelectableNode<?>> subSelections = new ArrayList<>();
|
|
||||||
|
|
||||||
if ( selections.isEmpty() ) {
|
|
||||||
subSelections.add( (SqmSelectableNode<?>) nodeBuilder.literal( 1 ).alias( "c0" ) );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
for ( SqmSelection<?> selection : selections ) {
|
|
||||||
selection.getSelectableNode().visitSubSelectableNodes( e -> {
|
|
||||||
e.alias( "c" + subSelections.size() );
|
|
||||||
subSelections.add( e );
|
|
||||||
} );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
querySpec.getSelectClause().setSelection( (SqmSelectableNode<?>) nodeBuilder.tuple( subSelections ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue