HHH-1804 HHH-5096 : FetchingScrollableResultsImpl throws SQLException when empty; last() does not move cursor if it is after last
git-svn-id: https://svn.jboss.org/repos/hibernate/core/branches/Branch_3_3@19216 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
parent
19887a4ed6
commit
8b412b9191
|
@ -23,6 +23,7 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.hql.ast.tree;
|
package org.hibernate.hql.ast.tree;
|
||||||
|
|
||||||
|
import org.hibernate.type.OneToOneType;
|
||||||
import org.hibernate.type.Type;
|
import org.hibernate.type.Type;
|
||||||
import org.hibernate.Hibernate;
|
import org.hibernate.Hibernate;
|
||||||
import org.hibernate.TypeMismatchException;
|
import org.hibernate.TypeMismatchException;
|
||||||
|
@ -80,8 +81,8 @@ public class BinaryLogicOperatorNode extends HqlSqlWalkerNode implements BinaryO
|
||||||
// resolve an expected type
|
// resolve an expected type
|
||||||
SessionFactoryImplementor sessionFactory = getSessionFactoryHelper().getFactory();
|
SessionFactoryImplementor sessionFactory = getSessionFactoryHelper().getFactory();
|
||||||
if ( lhsType != null && rhsType != null ) {
|
if ( lhsType != null && rhsType != null ) {
|
||||||
int lhsColumnSpan = lhsType.getColumnSpan( sessionFactory );
|
int lhsColumnSpan = getColumnSpan( lhsType, sessionFactory );
|
||||||
if ( lhsColumnSpan != rhsType.getColumnSpan( sessionFactory ) ) {
|
if ( lhsColumnSpan != getColumnSpan( rhsType, sessionFactory ) ) {
|
||||||
throw new TypeMismatchException(
|
throw new TypeMismatchException(
|
||||||
"left and right hand sides of a binary logic operator were incompatibile [" +
|
"left and right hand sides of a binary logic operator were incompatibile [" +
|
||||||
lhsType.getName() + " : "+ rhsType.getName() + "]"
|
lhsType.getName() + " : "+ rhsType.getName() + "]"
|
||||||
|
@ -97,6 +98,14 @@ public class BinaryLogicOperatorNode extends HqlSqlWalkerNode implements BinaryO
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int getColumnSpan(Type type, SessionFactoryImplementor sfi) {
|
||||||
|
int columnSpan = type.getColumnSpan( sfi );
|
||||||
|
if ( columnSpan == 0 && type instanceof OneToOneType ) {
|
||||||
|
columnSpan = ( ( OneToOneType ) type ).getIdentifierOrUniqueKeyType( sfi ).getColumnSpan( sfi );
|
||||||
|
}
|
||||||
|
return columnSpan;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mutate the subtree relating to a row-value-constructor to instead use
|
* Mutate the subtree relating to a row-value-constructor to instead use
|
||||||
* a series of ANDed predicates. This allows multi-column type comparisons
|
* a series of ANDed predicates. This allows multi-column type comparisons
|
||||||
|
|
|
@ -75,6 +75,12 @@ public class FetchingScrollableResultsImpl extends AbstractScrollableResults {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( isResultSetEmpty() ) {
|
||||||
|
currentRow = null;
|
||||||
|
currentPosition = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
Object row = getLoader().loadSequentialRowsForward(
|
Object row = getLoader().loadSequentialRowsForward(
|
||||||
getResultSet(),
|
getResultSet(),
|
||||||
getSession(),
|
getSession(),
|
||||||
|
@ -183,13 +189,16 @@ public class FetchingScrollableResultsImpl extends AbstractScrollableResults {
|
||||||
public boolean last() throws HibernateException {
|
public boolean last() throws HibernateException {
|
||||||
boolean more = false;
|
boolean more = false;
|
||||||
if ( maxPosition != null ) {
|
if ( maxPosition != null ) {
|
||||||
|
if ( currentPosition > maxPosition.intValue() ) {
|
||||||
|
more = previous();
|
||||||
|
}
|
||||||
for ( int i = currentPosition; i < maxPosition.intValue(); i++ ) {
|
for ( int i = currentPosition; i < maxPosition.intValue(); i++ ) {
|
||||||
more = next();
|
more = next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
try {
|
try {
|
||||||
if ( getResultSet().isAfterLast() ) {
|
if ( isResultSetEmpty() || getResultSet().isAfterLast() ) {
|
||||||
// should not be able to reach last without maxPosition being set
|
// should not be able to reach last without maxPosition being set
|
||||||
// unless there are no results
|
// unless there are no results
|
||||||
return false;
|
return false;
|
||||||
|
@ -313,4 +322,18 @@ public class FetchingScrollableResultsImpl extends AbstractScrollableResults {
|
||||||
}
|
}
|
||||||
return scroll( rowNumber - currentPosition );
|
return scroll( rowNumber - currentPosition );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isResultSetEmpty() {
|
||||||
|
try {
|
||||||
|
return currentPosition == 0 && ! getResultSet().isBeforeFirst() && ! getResultSet().isAfterLast();
|
||||||
|
}
|
||||||
|
catch( SQLException e ) {
|
||||||
|
throw JDBCExceptionHelper.convert(
|
||||||
|
getSession().getFactory().getSQLExceptionConverter(),
|
||||||
|
e,
|
||||||
|
"Could not determine if resultset is empty due to exception calling isBeforeFirst or isAfterLast()"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -391,6 +391,32 @@ public class ASTParserLoadingTest extends FunctionalTestCase {
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testEntityAndOneToOneReturnedByQuery() {
|
||||||
|
Session s = openSession();
|
||||||
|
s.beginTransaction();
|
||||||
|
Human h = new Human();
|
||||||
|
h.setName( new Name( "Gail", null, "Badner" ) );
|
||||||
|
s.save( h );
|
||||||
|
User u = new User();
|
||||||
|
u.setUserName( "gbadner" );
|
||||||
|
u.setHuman( h );
|
||||||
|
s.save( u );
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
|
||||||
|
s = openSession();
|
||||||
|
s.beginTransaction();
|
||||||
|
Object [] result = ( Object [] ) s.createQuery( "from User u, Human h where u.human = h" ).uniqueResult();
|
||||||
|
assertNotNull( result );
|
||||||
|
assertEquals( u.getUserName(), ( ( User ) result[ 0 ] ).getUserName() );
|
||||||
|
assertEquals( h.getName().getFirst(), ( ( Human ) result[ 1 ] ).getName().getFirst() );
|
||||||
|
assertSame( ( ( User ) result[ 0 ] ).getHuman(), result[ 1 ] );
|
||||||
|
s.createQuery( "delete User" ).executeUpdate();
|
||||||
|
s.createQuery( "delete Human" ).executeUpdate();
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
}
|
||||||
|
|
||||||
public void testNestedComponentIsNull() {
|
public void testNestedComponentIsNull() {
|
||||||
// (1) From MapTest originally...
|
// (1) From MapTest originally...
|
||||||
// (2) Was then moved into HQLTest...
|
// (2) Was then moved into HQLTest...
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
// $Id: ScrollableCollectionFetchingTest.java 10977 2006-12-12 23:28:04Z steve.ebersole@jboss.com $
|
// $Id: ScrollableCollectionFetchingTest.java 10977 2006-12-12 23:28:04Z steve.ebersole@jboss.com $
|
||||||
package org.hibernate.test.hql;
|
package org.hibernate.test.hql;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import junit.framework.Test;
|
import junit.framework.Test;
|
||||||
|
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
|
@ -47,6 +49,195 @@ public class ScrollableCollectionFetchingTest extends FunctionalTestCase {
|
||||||
s.close();
|
s.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testScrollingJoinFetchesEmptyResultSet() {
|
||||||
|
Session s = openSession();
|
||||||
|
Transaction txn = s.beginTransaction();
|
||||||
|
|
||||||
|
assertTrue(s
|
||||||
|
.createQuery( "from Animal a left join fetch a.offspring where a.description like :desc order by a.id" )
|
||||||
|
.setString( "desc", "root%" )
|
||||||
|
.list()
|
||||||
|
.isEmpty() );
|
||||||
|
|
||||||
|
ScrollableResults results = s
|
||||||
|
.createQuery( "from Animal a left join fetch a.offspring where a.description like :desc order by a.id" )
|
||||||
|
.setString( "desc", "root%" )
|
||||||
|
.scroll();
|
||||||
|
|
||||||
|
assertFalse( results.isFirst() );
|
||||||
|
assertFalse( results.isLast() );
|
||||||
|
|
||||||
|
assertFalse( results.next() );
|
||||||
|
assertFalse( results.isFirst() );
|
||||||
|
assertFalse( results.isLast() );
|
||||||
|
|
||||||
|
assertFalse( results.previous() );
|
||||||
|
assertFalse( results.isFirst() );
|
||||||
|
assertFalse( results.isLast() );
|
||||||
|
|
||||||
|
results.beforeFirst();
|
||||||
|
assertFalse( results.isFirst() );
|
||||||
|
assertFalse( results.isLast() );
|
||||||
|
assertFalse( results.next() );
|
||||||
|
|
||||||
|
assertFalse( results.first() );
|
||||||
|
assertFalse( results.isFirst() );
|
||||||
|
assertFalse( results.isLast() );
|
||||||
|
assertFalse( results.next() );
|
||||||
|
|
||||||
|
results.afterLast();
|
||||||
|
assertFalse( results.isFirst() );
|
||||||
|
assertFalse( results.isLast() );
|
||||||
|
assertFalse( results.next() );
|
||||||
|
|
||||||
|
assertFalse( results.last() );
|
||||||
|
assertFalse( results.isFirst() );
|
||||||
|
assertFalse( results.isLast() );
|
||||||
|
assertFalse( results.next() );
|
||||||
|
|
||||||
|
for ( int i=1; i<3; i++ ) {
|
||||||
|
assertFalse( results.scroll( i ) );
|
||||||
|
assertFalse( results.isFirst() );
|
||||||
|
assertFalse( results.isLast() );
|
||||||
|
|
||||||
|
assertFalse( results.scroll( - i ) );
|
||||||
|
assertFalse( results.isFirst() );
|
||||||
|
assertFalse( results.isLast() );
|
||||||
|
|
||||||
|
assertFalse( results.setRowNumber( i ) );
|
||||||
|
assertFalse( results.isFirst() );
|
||||||
|
assertFalse( results.isLast() );
|
||||||
|
|
||||||
|
assertFalse( results.setRowNumber( - i ) );
|
||||||
|
assertFalse( results.isFirst() );
|
||||||
|
assertFalse( results.isLast() );
|
||||||
|
}
|
||||||
|
|
||||||
|
txn.commit();
|
||||||
|
s.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testScrollingJoinFetchesSingleRowResultSet() {
|
||||||
|
Session s = openSession();
|
||||||
|
Transaction txn = s.beginTransaction();
|
||||||
|
|
||||||
|
Animal mother = new Animal();
|
||||||
|
mother.setDescription( "root-1" );
|
||||||
|
|
||||||
|
Animal daughter = new Animal();
|
||||||
|
daughter.setDescription( "daughter" );
|
||||||
|
|
||||||
|
daughter.setMother( mother );
|
||||||
|
mother.addOffspring( daughter );
|
||||||
|
|
||||||
|
s.save( mother );
|
||||||
|
s.save( daughter );
|
||||||
|
|
||||||
|
txn.commit();
|
||||||
|
s.close();
|
||||||
|
|
||||||
|
s = openSession();
|
||||||
|
txn = s.beginTransaction();
|
||||||
|
|
||||||
|
assertNotNull(s
|
||||||
|
.createQuery( "from Animal a left join fetch a.offspring where a.description like :desc order by a.id" )
|
||||||
|
.setString( "desc", "root%" )
|
||||||
|
.uniqueResult() );
|
||||||
|
|
||||||
|
ScrollableResults results = s
|
||||||
|
.createQuery( "from Animal a left join fetch a.offspring where a.description like :desc order by a.id" )
|
||||||
|
.setString( "desc", "root%" )
|
||||||
|
.scroll();
|
||||||
|
|
||||||
|
assertFalse( results.isFirst() );
|
||||||
|
assertFalse( results.isLast() );
|
||||||
|
assertFalse( results.previous() );
|
||||||
|
|
||||||
|
assertTrue( results.next() );
|
||||||
|
assertTrue( results.isFirst() );
|
||||||
|
assertTrue( results.isLast() );
|
||||||
|
|
||||||
|
assertFalse( results.next() );
|
||||||
|
assertFalse( results.isFirst() );
|
||||||
|
assertFalse( results.isLast() );
|
||||||
|
|
||||||
|
assertTrue( results.previous() );
|
||||||
|
assertTrue( results.isFirst() );
|
||||||
|
assertTrue( results.isLast() );
|
||||||
|
|
||||||
|
assertFalse( results.previous() );
|
||||||
|
assertFalse( results.isFirst() );
|
||||||
|
assertFalse( results.isLast() );
|
||||||
|
|
||||||
|
assertTrue( results.next() );
|
||||||
|
assertTrue( results.isFirst() );
|
||||||
|
assertTrue( results.isLast() );
|
||||||
|
|
||||||
|
results.beforeFirst();
|
||||||
|
assertFalse( results.isFirst() );
|
||||||
|
assertFalse( results.isLast() );
|
||||||
|
assertFalse( results.previous() );
|
||||||
|
|
||||||
|
assertTrue( results.first() );
|
||||||
|
assertTrue( results.isFirst() );
|
||||||
|
assertTrue( results.isLast() );
|
||||||
|
assertFalse( results.next() );
|
||||||
|
|
||||||
|
results.afterLast();
|
||||||
|
assertFalse( results.isFirst() );
|
||||||
|
assertFalse( results.isLast() );
|
||||||
|
assertFalse( results.next() );
|
||||||
|
|
||||||
|
assertTrue( results.last() );
|
||||||
|
assertTrue( results.isFirst() );
|
||||||
|
assertTrue( results.isLast() );
|
||||||
|
assertFalse( results.next() );
|
||||||
|
|
||||||
|
assertTrue( results.first() );
|
||||||
|
assertTrue( results.isFirst() );
|
||||||
|
assertTrue( results.isLast() );
|
||||||
|
|
||||||
|
for ( int i=1; i<3; i++ ) {
|
||||||
|
assertTrue( results.setRowNumber( 1 ) );
|
||||||
|
assertTrue( results.isFirst() );
|
||||||
|
assertTrue( results.isLast() );
|
||||||
|
|
||||||
|
assertFalse( results.scroll( i ) );
|
||||||
|
assertFalse( results.isFirst() );
|
||||||
|
assertFalse( results.isLast() );
|
||||||
|
|
||||||
|
assertTrue( results.setRowNumber( 1 ) );
|
||||||
|
assertTrue( results.isFirst() );
|
||||||
|
assertTrue( results.isLast() );
|
||||||
|
|
||||||
|
assertFalse( results.scroll( - i ) );
|
||||||
|
assertFalse( results.isFirst() );
|
||||||
|
assertFalse( results.isLast() );
|
||||||
|
|
||||||
|
if ( i != 1 ) {
|
||||||
|
assertFalse( results.setRowNumber( i ) );
|
||||||
|
assertFalse( results.isFirst() );
|
||||||
|
assertFalse( results.isLast() );
|
||||||
|
|
||||||
|
assertFalse( results.setRowNumber( - i ) );
|
||||||
|
assertFalse( results.isFirst() );
|
||||||
|
assertFalse( results.isLast() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
txn.commit();
|
||||||
|
s.close();
|
||||||
|
|
||||||
|
s = openSession();
|
||||||
|
txn = s.beginTransaction();
|
||||||
|
|
||||||
|
s.createQuery( "delete Animal where not description like 'root%'" ).executeUpdate();
|
||||||
|
s.createQuery( "delete Animal" ).executeUpdate();
|
||||||
|
|
||||||
|
txn.commit();
|
||||||
|
s.close();
|
||||||
|
}
|
||||||
|
|
||||||
public void testScrollingJoinFetchesForward() {
|
public void testScrollingJoinFetchesForward() {
|
||||||
if ( ! supportsResultSetPositionQueryMethodsOnForwardOnlyCursor() ) {
|
if ( ! supportsResultSetPositionQueryMethodsOnForwardOnlyCursor() ) {
|
||||||
return;
|
return;
|
||||||
|
|
Loading…
Reference in New Issue