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 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()}.
|
||||
|
@ -74,7 +74,7 @@ public class SourceGeneration implements BeforeExecutionGenerator {
|
|||
*/
|
||||
@Override
|
||||
public EnumSet<EventType> getEventTypes() {
|
||||
return INSERT_ONLY;
|
||||
return INSERT_AND_UPDATE;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -27,9 +27,11 @@ import org.hibernate.query.sqm.FetchClauseType;
|
|||
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
|
||||
*
|
||||
* @see org.hibernate.query.SelectionQuery#getResultCount()
|
||||
*/
|
||||
JpaCriteriaQuery<Long> createCountQuery();
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
*/
|
||||
package org.hibernate.query.sqm.tree.select;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
|
@ -21,7 +20,6 @@ import jakarta.persistence.criteria.ParameterExpression;
|
|||
import jakarta.persistence.criteria.Predicate;
|
||||
import jakarta.persistence.criteria.Selection;
|
||||
|
||||
import org.hibernate.Internal;
|
||||
import org.hibernate.query.sqm.FetchClauseType;
|
||||
import org.hibernate.query.criteria.JpaCriteriaQuery;
|
||||
import org.hibernate.query.criteria.JpaExpression;
|
||||
|
@ -115,54 +113,6 @@ public class SqmSelectStatement<T> extends AbstractSqmSelectQuery<T> implements
|
|||
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
|
||||
public SqmSelectStatement<T> copy(SqmCopyContext context) {
|
||||
final SqmSelectStatement<T> existing = context.getCopy( this );
|
||||
|
@ -511,83 +461,44 @@ public class SqmSelectStatement<T> extends AbstractSqmSelectQuery<T> implements
|
|||
|
||||
@Override
|
||||
public SqmSelectStatement<Long> createCountQuery() {
|
||||
final SqmCopyContext copyContext = noParamCopyContext();
|
||||
|
||||
final SqmQueryPart<T> queryPart = getQueryPart().copy( copyContext );
|
||||
resetSelections( queryPart );
|
||||
if ( queryPart.getFetch() == null && queryPart.getOffset() == null ) {
|
||||
queryPart.setOrderByClause( null );
|
||||
}
|
||||
if ( queryPart.isSimpleQueryPart() ) {
|
||||
for ( SqmRoot<?> root : queryPart.getFirstQuerySpec().getRootList() ) {
|
||||
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 );
|
||||
}
|
||||
|
||||
final NodeBuilder nodeBuilder = nodeBuilder();
|
||||
final Set<SqmParameter<?>> parameters = copyParameters( copyContext );
|
||||
final SqmSelectStatement<Long> selectStatement = new SqmSelectStatement<>(
|
||||
nodeBuilder,
|
||||
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;
|
||||
@SuppressWarnings("unchecked")
|
||||
final SqmSelectStatement<Long> statement = (SqmSelectStatement<Long>) copy;
|
||||
statement.setResultType( Long.class );
|
||||
return statement;
|
||||
}
|
||||
else {
|
||||
final Set<SqmParameter<?>> copied = new LinkedHashSet<>( parameters.size() );
|
||||
for ( SqmParameter<?> parameter : parameters ) {
|
||||
copied.add( parameter.copy(context) );
|
||||
final JpaSelection<?> selection = querySpec.getSelection();
|
||||
if ( selection.isCompoundSelection() ) {
|
||||
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