return executePrepared();
}
}
private final int[] executePrepared() {
ExecuteContext ctx = new DefaultExecuteContext(configuration, new Query[] { query });
ExecuteListener listener = new ExecuteListeners(ctx);
Connection connection = ctx.connection();
// [#1371] fetch bind variables to restore them again, later
DataType<?>[] paramTypes = dataTypes(query.getParams().values().toArray(new Field[0]));
try {
listener.renderStart(ctx);
// [#1520] TODO: Should the number of bind values be checked, here?
ctx.sql(create.render(query));
listener.renderEnd(ctx);
listener.prepareStart(ctx);
ctx.statement(connection.prepareStatement(ctx.sql()));
listener.prepareEnd(ctx);
for (Object[] bindValues : allBindValues) {
listener.bindStart(ctx);
// [#1371] [#2139] Don't bind variables directly onto statement, bind them through the collected params
// list to preserve type information
// [#3547] The original query may have no Params specified - e.g. when it was constructed with
// plain SQL. In that case, infer the bind value type directly from the bind value
List<Field<?>> params = (paramTypes.length > 0)
? fields(bindValues, paramTypes)
: fields(bindValues);
visitAll(new DefaultBindContext(configuration, ctx.statement()), params);
listener.bindEnd(ctx);
ctx.statement().addBatch();
}
listener.executeStart(ctx);
int[] result = ctx.statement().executeBatch();
int[] batchRows = ctx.batchRows();
for (int i = 0; i < batchRows.length && i < result.length; i++)
batchRows[i] = result[i];
listener.executeEnd(ctx);
return result;
}
// [#3427] ControlFlowSignals must not be passed on to ExecuteListners
catch (ControlFlowSignal e) {
throw e;
}
catch (RuntimeException e) {
ctx.exception(e);
listener.exception(ctx);
throw ctx.exception();
}
catch (SQLException e) {
ctx.sqlException(e);
listener.exception(ctx);
throw ctx.exception();
}
finally {
Utils.safeClose(listener, ctx);
}
}