[#1886] Query.bind() has no effect when Query.keepStatement(true)
and StatementType.STATIC_STATEMENT are combined
This commit is contained in:
parent
1b0d7c08b9
commit
5d1a98b49d
@ -40,6 +40,7 @@ import static junit.framework.Assert.assertFalse;
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
import static junit.framework.Assert.fail;
|
||||
import static org.jooq.SQLDialect.H2;
|
||||
import static org.jooq.impl.Factory.inline;
|
||||
import static org.jooq.impl.Factory.val;
|
||||
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
@ -60,6 +61,7 @@ import org.jooq.ResultQuery;
|
||||
import org.jooq.Select;
|
||||
import org.jooq.TableRecord;
|
||||
import org.jooq.UpdatableRecord;
|
||||
import org.jooq.conf.StatementType;
|
||||
import org.jooq.exception.DataAccessException;
|
||||
import org.jooq.impl.DefaultExecuteListener;
|
||||
import org.jooq.impl.Executor;
|
||||
@ -102,7 +104,7 @@ extends BaseTest<A, AP, B, S, B2S, BS, L, X, DATE, BOOL, D, T, U, UU, I, IPK, T7
|
||||
|
||||
// [#385] By default, new statements are created for every execution
|
||||
KeepStatementListener.reset();
|
||||
ResultQuery<Record1<Integer>> query = create.select(val(1));
|
||||
ResultQuery<Record2<Integer, Integer>> query = create.select(val(1), inline(2));
|
||||
assertEquals(1, query.fetchOne(0));
|
||||
assertEquals(2, query.bind(1, 2).fetchOne(0));
|
||||
|
||||
@ -116,21 +118,43 @@ extends BaseTest<A, AP, B, S, B2S, BS, L, X, DATE, BOOL, D, T, U, UU, I, IPK, T7
|
||||
KeepStatementListener.reset();
|
||||
query.keepStatement(true);
|
||||
assertEquals(2, query.fetchOne(0));
|
||||
|
||||
// [#1886] TODO: Fix this for StatementType.STATIC_STATEMENT
|
||||
assertEquals(3, query.bind(1, 3).fetchOne(0));
|
||||
|
||||
Cursor<Record1<Integer>> cursor = query.fetchLazy();
|
||||
Cursor<Record2<Integer, Integer>> cursor = query.fetchLazy();
|
||||
assertEquals(3, cursor.fetchOne().getValue(0));
|
||||
assertEquals(3, query.fetchOne(0));
|
||||
|
||||
// [#1886] The first underlying statement should've been closed when
|
||||
// using StatementType.STATIC_STATEMENT
|
||||
assertEquals(4, KeepStatementListener.statements.size());
|
||||
assertEquals(0, KeepStatementListener.closed);
|
||||
assertTrue(
|
||||
assertEquals(
|
||||
create().getSettings().getStatementType() == StatementType.PREPARED_STATEMENT,
|
||||
KeepStatementListener.statements.get(0) ==
|
||||
KeepStatementListener.statements.get(1));
|
||||
|
||||
// Statements #2, #3, #4 should be identical
|
||||
assertTrue(
|
||||
KeepStatementListener.statements.get(0) ==
|
||||
KeepStatementListener.statements.get(1) ==
|
||||
KeepStatementListener.statements.get(2));
|
||||
assertTrue(
|
||||
KeepStatementListener.statements.get(2) ==
|
||||
KeepStatementListener.statements.get(3));
|
||||
|
||||
// [#1886] Check if inline bind values are correctly changed
|
||||
KeepStatementListener.reset();
|
||||
assertEquals(3, query.fetchOne(0));
|
||||
assertEquals(3, query.bind(2, 4).fetchOne(0));
|
||||
assertEquals(4, query.bind(2, 4).fetchOne(1));
|
||||
|
||||
// All statements should be closed, as the inline bind value was changed
|
||||
assertEquals(3, KeepStatementListener.statements.size());
|
||||
assertEquals(0, KeepStatementListener.closed);
|
||||
assertTrue(
|
||||
KeepStatementListener.statements.get(0) !=
|
||||
KeepStatementListener.statements.get(1));
|
||||
assertTrue(
|
||||
KeepStatementListener.statements.get(1) !=
|
||||
KeepStatementListener.statements.get(2));
|
||||
|
||||
cursor.close();
|
||||
|
||||
@ -172,6 +172,14 @@ public interface Query extends QueryPart, Attachable {
|
||||
|
||||
/**
|
||||
* Bind a new value to a named parameter
|
||||
* <p>
|
||||
* [#1886] If the bind value with name <code>param</code> is inlined (
|
||||
* {@link Param#isInline()}) or if this query was created with
|
||||
* {@link StatementType#STATIC_STATEMENT} and there is an underlying
|
||||
* <code>PreparedStatement</code> kept open because of
|
||||
* {@link #keepStatement(boolean)}, the underlying
|
||||
* <code>PreparedStatement</code> will be closed automatically in order for
|
||||
* new bind values to have an effect.
|
||||
*
|
||||
* @param param The named parameter name. If this is a number, then this is
|
||||
* the same as calling {@link #bind(int, Object)}
|
||||
@ -185,6 +193,14 @@ public interface Query extends QueryPart, Attachable {
|
||||
|
||||
/**
|
||||
* Bind a new value to an indexed parameter
|
||||
* <p>
|
||||
* [#1886] If the bind value at <code>index</code> is inlined (
|
||||
* {@link Param#isInline()}) or if this query was created with
|
||||
* {@link StatementType#STATIC_STATEMENT} and there is an underlying
|
||||
* <code>PreparedStatement</code> kept open because of
|
||||
* {@link #keepStatement(boolean)}, the underlying
|
||||
* <code>PreparedStatement</code> will be closed automatically in order for
|
||||
* new bind values to have an effect.
|
||||
*
|
||||
* @param index The parameter index, starting with 1
|
||||
* @param value The new bind value.
|
||||
|
||||
@ -50,6 +50,8 @@ import org.jooq.ExecuteContext;
|
||||
import org.jooq.ExecuteListener;
|
||||
import org.jooq.Param;
|
||||
import org.jooq.Query;
|
||||
import org.jooq.conf.SettingsTools;
|
||||
import org.jooq.conf.StatementType;
|
||||
import org.jooq.exception.DetachedException;
|
||||
import org.jooq.tools.JooqLogger;
|
||||
|
||||
@ -123,6 +125,7 @@ abstract class AbstractQuery extends AbstractQueryPart implements Query, Attacha
|
||||
}
|
||||
|
||||
p.setConverted(value);
|
||||
closeIfNecessary(p);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@ -134,16 +137,46 @@ abstract class AbstractQuery extends AbstractQueryPart implements Query, Attacha
|
||||
*/
|
||||
@Override
|
||||
public Query bind(int index, Object value) {
|
||||
Param<?>[] array = getParams().values().toArray(new Param[0]);
|
||||
Param<?>[] params = getParams().values().toArray(new Param[0]);
|
||||
|
||||
if (index < 1 || index > array.length) {
|
||||
if (index < 1 || index > params.length) {
|
||||
throw new IllegalArgumentException("Index out of range for Query parameters : " + index);
|
||||
}
|
||||
|
||||
array[index - 1].setConverted(value);
|
||||
Param<?> param = params[index - 1];
|
||||
param.setConverted(value);
|
||||
closeIfNecessary(param);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the statement if necessary.
|
||||
* <p>
|
||||
* [#1886] If there is an open (cached) statement and its bind values are
|
||||
* inlined due to a {@link StatementType#STATIC_STATEMENT} setting, the
|
||||
* statement should be closed.
|
||||
*
|
||||
* @param param The param that was changed
|
||||
*/
|
||||
private final void closeIfNecessary(Param<?> param) {
|
||||
|
||||
// This is relevant when there is an open statement, only
|
||||
if (keepStatement() && statement != null) {
|
||||
|
||||
// When an inlined param is being changed, the previous statement
|
||||
// has to be closed, regardless if variable binding is performed
|
||||
if (param.isInline()) {
|
||||
close();
|
||||
}
|
||||
|
||||
// If all params are inlined, the previous statement always has to
|
||||
// be closed
|
||||
else if (SettingsTools.executeStaticStatements(getConfiguration().getSettings())) {
|
||||
close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses may override this for covariant result types
|
||||
* <p>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user