From: <ste...@us...> - 2006-02-16 22:51:07
|
Update of /cvsroot/hibernate/Hibernate3/src/org/hibernate/hql/ast In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv13121/src/org/hibernate/hql/ast Modified Files: QueryTranslatorImpl.java Log Message: HHH-1411 & HHH-1412 : in-memory application of DISTINCT and firstRow/maxRows in conjunction with collection fetches Index: QueryTranslatorImpl.java =================================================================== RCS file: /cvsroot/hibernate/Hibernate3/src/org/hibernate/hql/ast/QueryTranslatorImpl.java,v retrieving revision 1.69 retrieving revision 1.70 diff -u -d -r1.69 -r1.70 --- QueryTranslatorImpl.java 9 Feb 2006 12:37:19 -0000 1.69 +++ QueryTranslatorImpl.java 16 Feb 2006 22:51:00 -0000 1.70 @@ -15,6 +15,7 @@ import org.hibernate.engine.QueryParameters; import org.hibernate.engine.SessionFactoryImplementor; import org.hibernate.engine.SessionImplementor; +import org.hibernate.engine.RowSelection; import org.hibernate.event.EventSource; import org.hibernate.hql.FilterTranslator; import org.hibernate.hql.antlr.HqlSqlTokenTypes; @@ -33,7 +34,7 @@ import org.hibernate.persister.entity.Queryable; import org.hibernate.type.Type; import org.hibernate.util.StringHelper; -import org.hibernate.util.ArrayHelper; +import org.hibernate.util.IdentitySet; import java.util.HashMap; import java.util.Iterator; @@ -313,7 +314,56 @@ throws HibernateException { // Delegate to the QueryLoader... errorIfDML(); - return queryLoader.list( session, queryParameters ); + QueryNode query = ( QueryNode ) sqlAst; + boolean hasLimit = queryParameters.getRowSelection().definesLimits(); + boolean needsDistincting = query.getSelectClause().isDistinct() || hasLimit; + boolean limitInMemory = hasLimit && containsCollectionFetches(); + + QueryParameters queryParametersToUse; + if ( limitInMemory ) { + log.warn( "firstResult/maxResults specified with collection fetch; applying in memory!" ); + RowSelection selection = new RowSelection(); + selection.setFetchSize( queryParameters.getRowSelection().getFetchSize() ); + selection.setTimeout( queryParameters.getRowSelection().getTimeout() ); + queryParametersToUse = queryParameters.createCopyUsing( selection ); + } + else { + queryParametersToUse = queryParameters; + } + + List results = queryLoader.list( session, queryParametersToUse ); + + if ( needsDistincting ) { + int includedCount = -1; + // NOTE : firstRow is zero-based + int first = queryParameters.getRowSelection().getFirstRow() == null + ? 0 + : queryParameters.getRowSelection().getFirstRow().intValue(); + int max = queryParameters.getRowSelection().getMaxRows() == null + ? -1 + : queryParameters.getRowSelection().getMaxRows().intValue(); + int size = results.size(); + List tmp = new ArrayList(); + IdentitySet distinction = new IdentitySet(); + for ( int i = 0; i < size; i++ ) { + final Object result = results.get( i ); + if ( !distinction.add( result ) ) { + continue; + } + includedCount++; + if ( includedCount < first ) { + continue; + } + tmp.add( result ); + // NOTE : ( max - 1 ) because first is zero-based while max is not... + if ( max >= 0 && ( includedCount - first ) >= ( max - 1 ) ) { + break; + } + } + results = tmp; + } + + return results; } /** |