[hibernate-issues] [Hibernate-JIRA] Created: (HHH-3542) Polymorphic query with set first row and limit result set returns wrong results

Yevgeny Shakhnovich (JIRA) noreply at atlassian.com
Thu Oct 23 16:29:04 EDT 2008


Polymorphic query with set first row and limit result set returns wrong results
-------------------------------------------------------------------------------

                 Key: HHH-3542
                 URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-3542
             Project: Hibernate Core
          Issue Type: Bug
          Components: core
    Affects Versions: 3.2.0.ga
            Reporter: Yevgeny Shakhnovich


If we issue a polymorphic query with the specified first row and set max rows to retrieve, the query returns wrong results.
For example, you have two entities A and B implementing the same interface C. 
 Query query = session.createQuery("from C");
 query.setMaxResults(10);
 query.setFirstResult(10);
 List<Object[]> result = query.list(); // will return only two records despite of tables A and B have enough records

The bug is pretty simple: the same variable is used to count total number of records and included records.This is the excerpt from org.hibernate.engine.query.HQLQueryPlan.performList

                int includedCount = -1;
		translator_loop: for ( int i = 0; i < translators.length; i++ ) {
			List tmp = translators[i].list( session, queryParametersToUse );
			if ( needsLimit ) {
				// 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();
				final int size = tmp.size();
				for ( int x = 0; x < size; x++ ) {
					final Object result = tmp.get( x );
                                if ( !distinction.add( result ) ) {
						continue;
			        }
                                       // In example above first is 10 and max is 10 as well. 

                                        includedCount++;
					if ( includedCount < first ) { 
						continue;
					}

                                        // This point is reached only when includedCount is 10 or more
					combinedResults.add( result );
					if ( max >= 0 && includedCount > max ) {
						// break the outer loop !!!
						break translator_loop;
					}

The fix is also simple: add one more variable to keep the total number of records:

        int includedCount = 0;
        int recordCount = 0;
        translator_loop: for ( int i = 0; i < translators.length; i++ ) {
            List tmp = translators[i].list( session, queryParametersToUse );
            if ( needsLimit ) {
                // 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();
                final int size = tmp.size();
                for ( int x = 0; x < size; x++ ) {
                    final Object result = tmp.get( x );
                    if ( !distinction.add( result ) ) {
                        continue;
                    }
                    /* includedCount should include only what was really included */
                    if ( recordCount++ < first) {
                        continue;
                    }
                    includedCount++;
                    combinedResults.add( result );
                    if ( max >= 0 && includedCount >= max ) {
                        // break the outer loop !!!
                        break translator_loop;
                    }
                }
            }
            else {
                combinedResults.addAll( tmp );
            }
        }




 

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://opensource.atlassian.com/projects/hibernate/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira

        



More information about the hibernate-issues mailing list