Skip to content

Commit

Permalink
Query#scroll support
Browse files Browse the repository at this point in the history
  + HHH-14308: Add generic type parameter to ScrollableResults
  • Loading branch information
sebersole committed Nov 4, 2020
1 parent 1b7017f commit abeb637
Show file tree
Hide file tree
Showing 29 changed files with 1,038 additions and 395 deletions.
Expand Up @@ -59,6 +59,13 @@ public interface ScrollableResults<R> extends AutoCloseable, Closeable {
*/
boolean scroll(int positions);

/**
* Moves the result cursor to the specified position.
*
* @return {@code true} if there is a result at the new location
*/
boolean position(int position);

/**
* Go to the last result.
*
Expand Down
Expand Up @@ -16,7 +16,8 @@
import org.hibernate.sql.results.spi.RowReader;

/**
* Base implementation of the ScrollableResults interface.
* Base implementation of the ScrollableResults interface intended for sharing between
* {@link ScrollableResultsImpl} and {@link FetchingScrollableResultsImpl}
*
* @author Steve Ebersole
*/
Expand Down Expand Up @@ -91,7 +92,9 @@ public final void close() {
return;
}

getJdbcValues().finishUp( persistenceContext );
rowReader.finishUp( jdbcValuesSourceProcessingState );
jdbcValues.finishUp( persistenceContext );

getPersistenceContext().getJdbcCoordinator().afterStatementExecution();

this.closed = true;
Expand Down
Expand Up @@ -45,6 +45,11 @@ public boolean scroll(int positions) {
return false;
}

@Override
public boolean position(int position) {
return false;
}

@Override
public boolean last() {
return true;
Expand Down
Expand Up @@ -155,6 +155,11 @@ else if ( positions < 0 ) {
return more;
}

@Override
public boolean position(int position) {
throw new NotYetImplementedFor6Exception( getClass() );
}

@Override
public boolean last() {
throw new NotYetImplementedFor6Exception( getClass() );
Expand Down
Expand Up @@ -6,14 +6,11 @@
*/
package org.hibernate.internal;

import java.sql.SQLException;

import org.hibernate.HibernateException;
import org.hibernate.JDBCException;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.sql.results.jdbc.internal.JdbcValuesSourceProcessingStateStandardImpl;
import org.hibernate.sql.results.internal.RowProcessingStateStandardImpl;
import org.hibernate.sql.results.jdbc.internal.JdbcValuesSourceProcessingStateStandardImpl;
import org.hibernate.sql.results.jdbc.spi.JdbcValues;
import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingOptions;
import org.hibernate.sql.results.spi.RowReader;
Expand Down Expand Up @@ -49,82 +46,55 @@ protected R getCurrentRow() {
}

@Override
public boolean scroll(int i) {
throw new NotYetImplementedFor6Exception();

// todo (6.0) : need these scrollable ResultSet "re-positioning"-style methods on the JdbcValues stuff

// try {
// final boolean result = getResultSet().relative( i );
// prepareCurrentRow( result );
// return result;
// }
// catch (SQLException sqle) {
// throw convert( sqle, "could not advance using scroll()" );
// }
public boolean next() {
final boolean result = getRowProcessingState().next();
prepareCurrentRow( result );
return result;
}

protected JDBCException convert(SQLException sqle, String message) {
return getPersistenceContext().getJdbcServices().getSqlExceptionHelper().convert( sqle, message );
@Override
public boolean previous() {
final boolean result = getRowProcessingState().previous();
prepareCurrentRow( result );
return result;
}

@Override
public boolean first() {
throw new NotYetImplementedFor6Exception();

// todo (6.0) : need these scrollable ResultSet "re-positioning"-style methods on the JdbcValues stuff

// try {
// final boolean result = getResultSet().first();
// prepareCurrentRow( result );
// return result;
// }
// catch (SQLException sqle) {
// throw convert( sqle, "could not advance using first()" );
// }
public boolean scroll(int i) {
final boolean hasResult = getRowProcessingState().scroll( i );
prepareCurrentRow( hasResult );
return hasResult;
}

@Override
public boolean last() {
throw new NotYetImplementedFor6Exception();

// todo (6.0) : need these scrollable ResultSet "re-positioning"-style methods on the JdbcValues stuff

// try {
// final boolean result = getResultSet().last();
// prepareCurrentRow( result );
// return result;
// }
// catch (SQLException sqle) {
// throw convert( sqle, "could not advance using last()" );
// }
public boolean position(int position) {
final boolean hasResult = getRowProcessingState().position( position );
prepareCurrentRow( hasResult );
return hasResult;
}

@Override
public boolean next() {
try {
final boolean result = getJdbcValues().next( getRowProcessingState() );
prepareCurrentRow( result );
return result;
}
catch (SQLException sqle) {
throw convert( sqle, "could not advance using next()" );
}
public boolean first() {
final boolean hasResult = getRowProcessingState().first();
prepareCurrentRow( hasResult );
return hasResult;
}

@Override
public boolean previous() {
throw new NotYetImplementedFor6Exception();
public boolean last() {
final boolean hasResult = getRowProcessingState().last();
prepareCurrentRow( hasResult );
return hasResult;

// todo (6.0) : need these scrollable ResultSet "re-positioning"-style methods on the JdbcValues stuff

// try {
// final boolean result = getResultSet().previous();
// final boolean result = getResultSet().last();
// prepareCurrentRow( result );
// return result;
// }
// catch (SQLException sqle) {
// throw convert( sqle, "could not advance using previous()" );
// throw convert( sqle, "could not advance using last()" );
// }
}

Expand Down Expand Up @@ -186,36 +156,12 @@ public boolean isLast() {

@Override
public int getRowNumber() throws HibernateException {
throw new NotYetImplementedFor6Exception();

// todo (6.0) : need these scrollable ResultSet "re-positioning"-style methods on the JdbcValues stuff

// try {
// return getResultSet().getRow() - 1;
// }
// catch (SQLException sqle) {
// throw convert( sqle, "exception calling getRow()" );
// }
return getRowProcessingState().getPosition();
}

@Override
public boolean setRowNumber(int rowNumber) throws HibernateException {
throw new NotYetImplementedFor6Exception();

// todo (6.0) : need these scrollable ResultSet "re-positioning"-style methods on the JdbcValues stuff

// if ( rowNumber >= 0 ) {
// rowNumber++;
// }
//
// try {
// final boolean result = getResultSet().absolute( rowNumber );
// prepareCurrentRow( result );
// return result;
// }
// catch (SQLException sqle) {
// throw convert( sqle, "could not advance using absolute()" );
// }
return position( rowNumber );
}

private void prepareCurrentRow(boolean underlyingScrollSuccessful) {
Expand All @@ -224,15 +170,10 @@ private void prepareCurrentRow(boolean underlyingScrollSuccessful) {
return;
}

try {
currentRow = getRowReader().readRow(
getRowProcessingState(),
getProcessingOptions()
);
}
catch (SQLException e) {
throw convert( e, "Unable to read row as part of ScrollableResult handling" );
}
currentRow = getRowReader().readRow(
getRowProcessingState(),
getProcessingOptions()
);

afterScrollOperation();
}
Expand Down
Expand Up @@ -14,6 +14,7 @@
*
* @author Steve Ebersole
*/
@FunctionalInterface
public interface ReturningWork<T> {
/**
* Execute the discrete work encapsulated by this work instance using the supplied connection.
Expand All @@ -25,5 +26,5 @@ public interface ReturningWork<T> {
* @throws SQLException Thrown during execution of the underlying JDBC interaction.
* @throws org.hibernate.HibernateException Generally indicates a wrapped SQLException.
*/
public T execute(Connection connection) throws SQLException;
T execute(Connection connection) throws SQLException;
}
1 change: 1 addition & 0 deletions hibernate-core/src/main/java/org/hibernate/jdbc/Work.java
Expand Up @@ -14,6 +14,7 @@
*
* @author Steve Ebersole
*/
@FunctionalInterface
public interface Work {
/**
* Execute the discrete work encapsulated by this work instance using the supplied connection.
Expand Down
Expand Up @@ -747,7 +747,7 @@ protected List<R> doList() {
}

@Override
protected ScrollableResultsImplementor doScroll(ScrollMode scrollMode) {
public ScrollableResultsImplementor scroll(ScrollMode scrollMode) {
throw new UnsupportedOperationException( "Query#scroll is not valid for ProcedureCall/StoredProcedureQuery" );
}

Expand Down
27 changes: 11 additions & 16 deletions hibernate-core/src/main/java/org/hibernate/query/Query.java
Expand Up @@ -32,6 +32,7 @@
import org.hibernate.ScrollMode;
import org.hibernate.ScrollableResults;
import org.hibernate.SharedSessionContract;
import org.hibernate.dialect.Dialect;
import org.hibernate.graph.GraphSemantic;
import org.hibernate.graph.RootGraph;
import org.hibernate.metamodel.model.domain.AllowableParameterType;
Expand Down Expand Up @@ -99,29 +100,23 @@ default Query<R> applyLoadGraph(RootGraph graph) {
}

/**
* Return the query results as <tt>ScrollableResults</tt>. The
* scrollability of the returned results depends upon JDBC driver
* support for scrollable <tt>ResultSet</tt>s.<br>
* Returns scrollable access to the query results.
*
* @see ScrollableResults
* This form calls {@link #scroll(ScrollMode)} using {@link Dialect#defaultScrollMode()}
*
* @return the result iterator
* @apiNote The exact behavior of this method depends somewhat
* on the JDBC driver's {@link java.sql.ResultSet} scrolling support
*/
ScrollableResults scroll();
ScrollableResults<R> scroll();

/**
* Return the query results as ScrollableResults. The scrollability of the returned results
* depends upon JDBC driver support for scrollable ResultSets.
*
* @param scrollMode The scroll mode
*
* @return the result iterator
*
* @see ScrollableResults
* @see ScrollMode
* Returns scrollable access to the query results. The capabilities of the
* returned ScrollableResults depend on the specified ScrollMode.
*
* @apiNote The exact behavior of this method depends somewhat
* on the JDBC driver's {@link java.sql.ResultSet} scrolling support
*/
ScrollableResults scroll(ScrollMode scrollMode);
ScrollableResults<R> scroll(ScrollMode scrollMode);

/**
* Return the query results as a <tt>List</tt>. If the query contains
Expand Down
Expand Up @@ -11,7 +11,6 @@
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
Expand Down Expand Up @@ -44,6 +43,7 @@
import org.hibernate.QueryParameterException;
import org.hibernate.ScrollMode;
import org.hibernate.TypeMismatchException;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.query.spi.EntityGraphQueryHint;
import org.hibernate.engine.spi.ExceptionConverter;
import org.hibernate.engine.spi.QueryParameters;
Expand Down Expand Up @@ -1390,51 +1390,25 @@ protected void afterQuery() {
}

@Override
public ScrollableResultsImplementor scroll() {
return scroll( getSession().getJdbcServices().getJdbcEnvironment().getDialect().defaultScrollMode() );
public ScrollableResultsImplementor<R> scroll() {
final Dialect dialect = getSession().getJdbcServices().getJdbcEnvironment().getDialect();
return scroll( dialect.defaultScrollMode() );
}

@Override
public ScrollableResultsImplementor scroll(ScrollMode scrollMode) {
beforeQuery();
try {
return doScroll( scrollMode );
}
finally {
afterQuery();
}
}

protected ScrollableResultsImplementor doScroll(ScrollMode scrollMode) {
throw new NotYetImplementedFor6Exception( getClass() );

// if ( getMaxResults() == 0 ) {
// return EmptyScrollableResults.INSTANCE;
// }
//
// final String query = getQueryParameterBindings().expandListValuedParameters( getQueryString(), getSession() );
// QueryParameters queryParameters = makeQueryParametersForExecution( query );
// queryParameters.setScrollMode( scrollMode );
// return getSession().scroll( query, queryParameters );
}

@Override
@SuppressWarnings("unchecked")
public Stream<R> stream() {
if (getMaxResults() == 0){
final Spliterator<R> spliterator = Spliterators.emptySpliterator();
return StreamSupport.stream( spliterator, false );
}
final ScrollableResultsImplementor scrollableResults = scroll( ScrollMode.FORWARD_ONLY );
final ScrollableResultsImplementor<R> scrollableResults = scroll( ScrollMode.FORWARD_ONLY );
final ScrollableResultsIterator<R> iterator = new ScrollableResultsIterator<>( scrollableResults );
final Spliterator<R> spliterator = Spliterators.spliteratorUnknownSize( iterator, Spliterator.NONNULL );

final Stream<R> stream = new StreamDecorator(
return new StreamDecorator<>(
StreamSupport.stream( spliterator, false ),
scrollableResults::close
);

return stream;
}

@Override
Expand Down

0 comments on commit abeb637

Please sign in to comment.