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;
}
/**
|