Fix to use mysqlResultSetOptimization with c3p0-provided connections.

This commit is contained in:
2024-06-28 09:10:16 -05:00
parent e788929d67
commit c509b6da38
3 changed files with 44 additions and 16 deletions

View File

@ -55,6 +55,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
import com.kingsrook.qqq.backend.core.utils.CollectionUtils; import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
import com.kingsrook.qqq.backend.core.utils.Pair; import com.kingsrook.qqq.backend.core.utils.Pair;
import com.kingsrook.qqq.backend.module.rdbms.jdbc.QueryManager; import com.kingsrook.qqq.backend.module.rdbms.jdbc.QueryManager;
import com.kingsrook.qqq.backend.module.rdbms.model.metadata.RDBMSBackendMetaData;
import static com.kingsrook.qqq.backend.core.logging.LogUtils.logPair; import static com.kingsrook.qqq.backend.core.logging.LogUtils.logPair;
@ -356,18 +357,29 @@ public class RDBMSQueryAction extends AbstractRDBMSAction implements QueryInterf
*******************************************************************************/ *******************************************************************************/
private PreparedStatement createStatement(Connection connection, String sql, QueryInput queryInput) throws SQLException private PreparedStatement createStatement(Connection connection, String sql, QueryInput queryInput) throws SQLException
{ {
if(connection.getClass().getName().startsWith("com.mysql")) /////////////////////////////////////////////////////////////////////////
// if we're allowed to use the mysqlResultSetOptimization, and we have //
// the query hint of "potentially large no of results", then check if //
// our backend is indeed mysql, and if so, then apply those settings. //
/////////////////////////////////////////////////////////////////////////
if(mysqlResultSetOptimizationEnabled && queryInput.hasQueryHint(QueryHint.POTENTIALLY_LARGE_NUMBER_OF_RESULTS))
{ {
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// RDBMSBackendMetaData rdbmsBackendMetaData = (RDBMSBackendMetaData) queryInput.getBackend();
// if we're allowed to use the mysqlResultSetOptimization, and we have the query hint of "expected large result set", then do it. //
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
if(mysqlResultSetOptimizationEnabled && queryInput.getQueryHints() != null && queryInput.getQueryHints().contains(QueryHint.POTENTIALLY_LARGE_NUMBER_OF_RESULTS)) // todo - remove "aurora" - it's a legacy value here for a staged rollout //
////////////////////////////////////////////////////////////////////////////
if(RDBMSBackendMetaData.VENDOR_MYSQL.equals(rdbmsBackendMetaData.getVendor()) || RDBMSBackendMetaData.VENDOR_AURORA_MYSQL.equals(rdbmsBackendMetaData.getVendor()) || "aurora".equals(rdbmsBackendMetaData.getVendor()))
{ {
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////
// mysql "optimization", presumably here - from Result Set section of https://dev.mysql.com/doc/connector-j/en/connector-j-reference-implementation-notes.html // // mysql "optimization", presumably here - from Result Set section of //
// without this change, we saw ~10 seconds of "wait" time, before results would start to stream out of a large query (e.g., > 1,000,000 rows). // // https://dev.mysql.com/doc/connector-j/en/connector-j-reference-implementation-notes.html without //
// this change, we saw ~10 seconds of "wait" time, before results would start to stream out of a //
// large query (e.g., > 1,000,000 rows). //
// with this change, we start to get results immediately, and the total runtime also seems lower... // // with this change, we start to get results immediately, and the total runtime also seems lower... //
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // perhaps more importantly, without this change, the whole result set goes into memory - but with //
// this change, it is streamed. //
//////////////////////////////////////////////////////////////////////////////////////////////////////
PreparedStatement statement = connection.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); PreparedStatement statement = connection.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
statement.setFetchSize(Integer.MIN_VALUE); statement.setFetchSize(Integer.MIN_VALUE);
return (statement); return (statement);

View File

@ -150,8 +150,11 @@ public class ConnectionManager
return switch(backend.getVendor()) return switch(backend.getVendor())
{ {
case "mysql", "aurora" -> "com.mysql.cj.jdbc.Driver"; ////////////////////////////////////////////////////////////////////////////
case "h2" -> "org.h2.Driver"; // todo - remove "aurora" - it's a legacy value here for a staged rollout //
////////////////////////////////////////////////////////////////////////////
case RDBMSBackendMetaData.VENDOR_MYSQL, RDBMSBackendMetaData.VENDOR_AURORA_MYSQL, "aurora" -> "com.mysql.cj.jdbc.Driver";
case RDBMSBackendMetaData.VENDOR_H2 -> "org.h2.Driver";
default -> throw (new IllegalStateException("We do not know what jdbc driver to use for vendor name [" + backend.getVendor() + "]. Try setting jdbcDriverClassName in your backend meta data.")); default -> throw (new IllegalStateException("We do not know what jdbc driver to use for vendor name [" + backend.getVendor() + "]. Try setting jdbcDriverClassName in your backend meta data."));
}; };
} }
@ -170,11 +173,17 @@ public class ConnectionManager
return switch(backend.getVendor()) return switch(backend.getVendor())
{ {
// TODO aws-mysql-jdbc driver not working when running on AWS ////////////////////////////////////////////////////////////////
// TODO aws-mysql-jdbc driver not working when running on AWS //
////////////////////////////////////////////////////////////////
// jdbcURL = "jdbc:mysql:aws://" + backend.getHostName() + ":" + backend.getPort() + "/" + backend.getDatabaseName() + "?rewriteBatchedStatements=true&zeroDateTimeBehavior=CONVERT_TO_NULL"; // jdbcURL = "jdbc:mysql:aws://" + backend.getHostName() + ":" + backend.getPort() + "/" + backend.getDatabaseName() + "?rewriteBatchedStatements=true&zeroDateTimeBehavior=CONVERT_TO_NULL";
case "aurora" -> "jdbc:mysql://" + backend.getHostName() + ":" + backend.getPort() + "/" + backend.getDatabaseName() + "?rewriteBatchedStatements=true&zeroDateTimeBehavior=convertToNull&useSSL=false";
case "mysql" -> "jdbc:mysql://" + backend.getHostName() + ":" + backend.getPort() + "/" + backend.getDatabaseName() + "?rewriteBatchedStatements=true&zeroDateTimeBehavior=convertToNull"; ////////////////////////////////////////////////////////////////////////////
case "h2" -> "jdbc:h2:" + backend.getHostName() + ":" + backend.getDatabaseName() + ";MODE=MySQL;DB_CLOSE_DELAY=-1"; // todo - remove "aurora" - it's a legacy value here for a staged rollout //
////////////////////////////////////////////////////////////////////////////
case RDBMSBackendMetaData.VENDOR_AURORA_MYSQL, "aurora" -> "jdbc:mysql://" + backend.getHostName() + ":" + backend.getPort() + "/" + backend.getDatabaseName() + "?rewriteBatchedStatements=true&zeroDateTimeBehavior=convertToNull&useSSL=false";
case RDBMSBackendMetaData.VENDOR_MYSQL -> "jdbc:mysql://" + backend.getHostName() + ":" + backend.getPort() + "/" + backend.getDatabaseName() + "?rewriteBatchedStatements=true&zeroDateTimeBehavior=convertToNull";
case RDBMSBackendMetaData.VENDOR_H2 -> "jdbc:h2:" + backend.getHostName() + ":" + backend.getDatabaseName() + ";MODE=MySQL;DB_CLOSE_DELAY=-1";
default -> throw new IllegalArgumentException("Unsupported rdbms backend vendor: " + backend.getVendor()); default -> throw new IllegalArgumentException("Unsupported rdbms backend vendor: " + backend.getVendor());
}; };
} }

View File

@ -49,6 +49,13 @@ public class RDBMSBackendMetaData extends QBackendMetaData
private RDBMSBackendMetaData readOnlyBackendMetaData; private RDBMSBackendMetaData readOnlyBackendMetaData;
///////////////////////////////////////////////////////////
// define well-known (and fully supported) vendor values //
///////////////////////////////////////////////////////////
public static final String VENDOR_MYSQL = "mysql";
public static final String VENDOR_H2 = "h2";
public static final String VENDOR_AURORA_MYSQL = "aurora-mysql";
/******************************************************************************* /*******************************************************************************