[jOOQ/jOOQ#2752] Allow for skipping preparing statement.
If after ExecuteListener::prepareStart, ExecuteContext::statement is available, use that statement instead of preparing a new one.
This commit is contained in:
parent
b29e2aeefc
commit
2da86fde7a
@ -383,6 +383,26 @@ public interface ExecuteListener extends EventListener, Serializable {
|
||||
* <li>{@link ExecuteContext#sql(String)}: The rendered <code>SQL</code>
|
||||
* statement that is about to be executed. You can modify this statement
|
||||
* freely.</li>
|
||||
* <li>{@link ExecuteContext#statement()}: The {@link PreparedStatement}
|
||||
* about to be executed. At this stage, no such statement is available yet,
|
||||
* but if provided, the execution lifecycle will skip preparing a statement.
|
||||
* This can be used e.g. to implement a transaction-bound prepared statement
|
||||
* cache.
|
||||
* <p>
|
||||
* A custom {@link PreparedStatement} needs to take into account
|
||||
* {@link Settings#getStatementType()}, and avoid bind variable markers for
|
||||
* {@link StatementType#STATIC_STATEMENT}.
|
||||
* <p>
|
||||
* Flags such as {@link Query#queryTimeout(int)},
|
||||
* {@link Query#poolable(boolean)}, {@link ResultQuery#maxRows(int)}, which
|
||||
* correspond to mutable flags on a {@link PreparedStatement}, are set by
|
||||
* jOOQ even if a listener provides the statement.
|
||||
* <p>
|
||||
* Flags such as {@link ResultQuery#resultSetConcurrency(int)},
|
||||
* {@link ResultQuery#resultSetHoldability(int)},
|
||||
* {@link ResultQuery#resultSetType(int)}, which correspond to immutable
|
||||
* flags that are set on the statement at statement creation are not set on
|
||||
* a statement provided by a listener.</li>
|
||||
* </ul>
|
||||
*/
|
||||
void prepareStart(ExecuteContext ctx);
|
||||
|
||||
@ -829,6 +829,7 @@ abstract class AbstractDMLQuery<R extends Record> extends AbstractRowCountQuery
|
||||
|
||||
|
||||
|
||||
|
||||
if (returning.isEmpty()) {
|
||||
super.prepare(ctx);
|
||||
}
|
||||
@ -881,7 +882,8 @@ abstract class AbstractDMLQuery<R extends Record> extends AbstractRowCountQuery
|
||||
// yet, or UPDATE .. RETURNING
|
||||
case MARIADB:
|
||||
case MYSQL:
|
||||
ctx.statement(connection.prepareStatement(ctx.sql(), Statement.RETURN_GENERATED_KEYS));
|
||||
if (ctx.statement() == null)
|
||||
ctx.statement(connection.prepareStatement(ctx.sql(), Statement.RETURN_GENERATED_KEYS));
|
||||
break;
|
||||
|
||||
// The default is to return all requested fields directly
|
||||
@ -897,27 +899,30 @@ abstract class AbstractDMLQuery<R extends Record> extends AbstractRowCountQuery
|
||||
|
||||
|
||||
|
||||
|
||||
case HSQLDB:
|
||||
default: {
|
||||
String[] names = new String[returningResolvedAsterisks.size()];
|
||||
RenderNameCase style = SettingsTools.getRenderNameCase(configuration().settings());
|
||||
if (ctx.statement() == null) {
|
||||
String[] names = new String[returningResolvedAsterisks.size()];
|
||||
RenderNameCase style = SettingsTools.getRenderNameCase(configuration().settings());
|
||||
|
||||
// [#2845] Field names should be passed to JDBC in the case
|
||||
// imposed by the user. For instance, if the user uses
|
||||
// PostgreSQL generated case-insensitive Fields (default to lower case)
|
||||
// and wants to query HSQLDB (default to upper case), they may choose
|
||||
// to overwrite casing using RenderNameCase.
|
||||
if (style == RenderNameCase.UPPER)
|
||||
for (int i = 0; i < names.length; i++)
|
||||
names[i] = returningResolvedAsterisks.get(i).getName().toUpperCase(renderLocale(configuration().settings()));
|
||||
else if (style == RenderNameCase.LOWER)
|
||||
for (int i = 0; i < names.length; i++)
|
||||
names[i] = returningResolvedAsterisks.get(i).getName().toLowerCase(renderLocale(configuration().settings()));
|
||||
else
|
||||
for (int i = 0; i < names.length; i++)
|
||||
names[i] = returningResolvedAsterisks.get(i).getName();
|
||||
// [#2845] Field names should be passed to JDBC in the case
|
||||
// imposed by the user. For instance, if the user uses
|
||||
// PostgreSQL generated case-insensitive Fields (default to lower case)
|
||||
// and wants to query HSQLDB (default to upper case), they may choose
|
||||
// to overwrite casing using RenderNameCase.
|
||||
if (style == RenderNameCase.UPPER)
|
||||
for (int i = 0; i < names.length; i++)
|
||||
names[i] = returningResolvedAsterisks.get(i).getName().toUpperCase(renderLocale(configuration().settings()));
|
||||
else if (style == RenderNameCase.LOWER)
|
||||
for (int i = 0; i < names.length; i++)
|
||||
names[i] = returningResolvedAsterisks.get(i).getName().toLowerCase(renderLocale(configuration().settings()));
|
||||
else
|
||||
for (int i = 0; i < names.length; i++)
|
||||
names[i] = returningResolvedAsterisks.get(i).getName();
|
||||
ctx.statement(connection.prepareStatement(ctx.sql(), names));
|
||||
}
|
||||
|
||||
ctx.statement(connection.prepareStatement(ctx.sql(), names));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -434,7 +434,8 @@ abstract class AbstractQuery extends AbstractQueryPart implements Query {
|
||||
* this method.
|
||||
*/
|
||||
protected void prepare(ExecuteContext ctx) throws SQLException {
|
||||
ctx.statement(ctx.connection().prepareStatement(ctx.sql()));
|
||||
if (ctx.statement() == null)
|
||||
ctx.statement(ctx.connection().prepareStatement(ctx.sql()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -238,34 +238,33 @@ abstract class AbstractResultQuery<R extends Record> extends AbstractQuery imple
|
||||
|
||||
@Override
|
||||
protected final void prepare(ExecuteContext ctx) throws SQLException {
|
||||
if (ctx.statement() == null) {
|
||||
|
||||
// [#1846] [#2265] [#2299] Users may explicitly specify how ResultSets
|
||||
// created by jOOQ behave. This will override any other default behaviour
|
||||
if (resultSetConcurrency != 0 || resultSetType != 0 || resultSetHoldability != 0) {
|
||||
int type = resultSetType != 0 ? resultSetType : ResultSet.TYPE_FORWARD_ONLY;
|
||||
int concurrency = resultSetConcurrency != 0 ? resultSetConcurrency : ResultSet.CONCUR_READ_ONLY;
|
||||
// [#1846] [#2265] [#2299] Users may explicitly specify how ResultSets
|
||||
// created by jOOQ behave. This will override any other default behaviour
|
||||
if (resultSetConcurrency != 0 || resultSetType != 0 || resultSetHoldability != 0) {
|
||||
int type = resultSetType != 0 ? resultSetType : ResultSet.TYPE_FORWARD_ONLY;
|
||||
int concurrency = resultSetConcurrency != 0 ? resultSetConcurrency : ResultSet.CONCUR_READ_ONLY;
|
||||
|
||||
// Sybase doesn't support holdability. Avoid setting it!
|
||||
if (resultSetHoldability == 0) {
|
||||
ctx.statement(ctx.connection().prepareStatement(ctx.sql(), type, concurrency));
|
||||
// Sybase doesn't support holdability. Avoid setting it!
|
||||
if (resultSetHoldability == 0)
|
||||
ctx.statement(ctx.connection().prepareStatement(ctx.sql(), type, concurrency));
|
||||
else
|
||||
ctx.statement(ctx.connection().prepareStatement(ctx.sql(), type, concurrency, resultSetHoldability));
|
||||
}
|
||||
|
||||
// Regular behaviour
|
||||
else {
|
||||
ctx.statement(ctx.connection().prepareStatement(ctx.sql(), type, concurrency, resultSetHoldability));
|
||||
ctx.statement(ctx.connection().prepareStatement(ctx.sql()));
|
||||
}
|
||||
}
|
||||
|
||||
// Regular behaviour
|
||||
else {
|
||||
ctx.statement(ctx.connection().prepareStatement(ctx.sql()));
|
||||
}
|
||||
|
||||
Tools.setFetchSize(ctx, fetchSize);
|
||||
|
||||
// [#1854] [#4753] Set the max number of rows for this result query
|
||||
int m = SettingsTools.getMaxRows(maxRows, ctx.settings());
|
||||
if (m != 0) {
|
||||
if (m != 0)
|
||||
ctx.statement().setMaxRows(m);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -504,7 +504,8 @@ public abstract class AbstractRoutine<T> extends AbstractNamed implements Routin
|
||||
listener.renderEnd(ctx);
|
||||
|
||||
listener.prepareStart(ctx);
|
||||
ctx.statement(connection.prepareCall(ctx.sql()));
|
||||
if (ctx.statement() == null)
|
||||
ctx.statement(connection.prepareCall(ctx.sql()));
|
||||
Tools.setFetchSize(ctx, 0);
|
||||
// [#1856] TODO: Add Statement flags like timeout here
|
||||
listener.prepareEnd(ctx);
|
||||
|
||||
@ -85,7 +85,8 @@ final class BatchMultiple extends AbstractBatch {
|
||||
// [#8968] Keep start() event inside of lifecycle management
|
||||
listener.start(ctx);
|
||||
|
||||
ctx.statement(new SettingsEnabledPreparedStatement(connection));
|
||||
if (ctx.statement() == null)
|
||||
ctx.statement(new SettingsEnabledPreparedStatement(connection));
|
||||
|
||||
String[] batchSQL = ctx.batchSQL();
|
||||
for (int i = 0; i < queries.length; i++) {
|
||||
|
||||
@ -205,7 +205,8 @@ final class BatchSingle extends AbstractBatch implements BatchBindStep {
|
||||
listener.renderEnd(ctx);
|
||||
|
||||
listener.prepareStart(ctx);
|
||||
ctx.statement(connection.prepareStatement(ctx.sql()));
|
||||
if (ctx.statement() == null)
|
||||
ctx.statement(connection.prepareStatement(ctx.sql()));
|
||||
listener.prepareEnd(ctx);
|
||||
|
||||
// [#9295] use query timeout from settings
|
||||
|
||||
Loading…
Reference in New Issue
Block a user