Adjusted Fix for Issue 56 - Using findIterate with MySQL streams the

entire result set at once.  This makes the fix specific to the
DatabasePlatform and findIterate() or findVisit().
This commit is contained in:
Rob Bygrave
2013-11-07 23:58:15 +13:00
parent b896e55af1
commit 9d8fe97de0
4 changed files with 35 additions and 6 deletions
@@ -63,6 +63,12 @@ public class DatabasePlatform {
protected boolean selectCountWithAlias;
/**
* If set then use the FORWARD ONLY hint when creating ResultSets for
* findIterate() and findVisit().
*/
protected boolean forwardOnlyHintOnFindIterate;
/**
* Instantiates a new database platform.
*/
@@ -199,6 +205,24 @@ public class DatabasePlatform {
return idInExpandedForm;
}
/**
* Return true if the ResultSet TYPE_FORWARD_ONLY Hint should be used on
* findIterate() and findVisit() PreparedStatements.
* <p>
* This specifically is required for MySql when processing large results.
* </p>
*/
public boolean isForwardOnlyHintOnFindIterate() {
return forwardOnlyHintOnFindIterate;
}
/**
* Set to true if the ResultSet TYPE_FORWARD_ONLY Hint should be used by default on findIterate PreparedStatements.
*/
public void setForwardOnlyHintOnFindIterate(boolean forwardOnlyHintOnFindIterate) {
this.forwardOnlyHintOnFindIterate = forwardOnlyHintOnFindIterate;
}
/**
* Return the DB identity/sequence features for this platform.
*
@@ -31,6 +31,7 @@ public class MySqlPlatform extends DatabasePlatform {
this.openQuote = "`";
this.closeQuote = "`";
this.forwardOnlyHintOnFindIterate = true;
this.booleanDbType = Types.BIT;
dbTypeMap.put(Types.BIT, new DbType("tinyint(1) default 0"));
@@ -346,8 +346,8 @@ public class CQuery<T> implements DbReadContext, CancelableQuery {
/**
* Prepare bind and execute query with Forward only hints.
*/
public boolean prepareBindExecuteQueryForwardOnly() throws SQLException {
return prepareBindExecuteQueryWithOption(true);
public boolean prepareBindExecuteQueryForwardOnly(boolean dbPlatformForwardOnlyHint) throws SQLException {
return prepareBindExecuteQueryWithOption(dbPlatformForwardOnlyHint);
}
/**
@@ -357,7 +357,7 @@ public class CQuery<T> implements DbReadContext, CancelableQuery {
return prepareBindExecuteQueryWithOption(false);
}
private boolean prepareBindExecuteQueryWithOption(boolean forward) throws SQLException {
private boolean prepareBindExecuteQueryWithOption(boolean forwardOnlyHint) throws SQLException {
synchronized (this) {
if (cancelled || query.isCancelled()) {
@@ -371,8 +371,9 @@ public class CQuery<T> implements DbReadContext, CancelableQuery {
// prepare
SpiTransaction t = request.getTransaction();
Connection conn = t.getInternalConnection();
if (forward) {
// Hints required for mysql for large resultset processing (Issue 56)
if (forwardOnlyHint) {
// Use forward only hints for large resultset processing (Issue 56, MySql specific)
pstmt = conn.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
} else {
pstmt = conn.prepareStatement(sql);
@@ -25,6 +25,8 @@ public class CQueryEngine {
private static final Logger logger = LoggerFactory.getLogger(CQueryEngine.class);
private final DatabasePlatform dbPlatform;
private final CQueryBuilder queryBuilder;
private final BackgroundExecutor backgroundExecutor;
@@ -33,6 +35,7 @@ public class CQueryEngine {
public CQueryEngine(DatabasePlatform dbPlatform, Binder binder, BackgroundExecutor backgroundExecutor) {
this.dbPlatform = dbPlatform;
this.backgroundExecutor = backgroundExecutor;
this.queryBuilder = new CQueryBuilder(backgroundExecutor, dbPlatform, binder);
}
@@ -122,7 +125,7 @@ public class CQueryEngine {
try {
if (!cquery.prepareBindExecuteQueryForwardOnly()) {
if (!cquery.prepareBindExecuteQueryForwardOnly(dbPlatform.isForwardOnlyHintOnFindIterate())) {
// query has been cancelled already
logger.trace("Future fetch already cancelled");
return null;