Skip to content

Commit

Permalink
#788 Fix executeBatch() of statement without parameters throws isc_ba…
Browse files Browse the repository at this point in the history
…tch_param
  • Loading branch information
mrotteveel committed Mar 13, 2024
1 parent 70f27d1 commit 1ecccac
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 5 deletions.
4 changes: 4 additions & 0 deletions src/docs/asciidoc/release_notes.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ For known issues, consult <<known-issues>>.

The following has been changed or fixed since Jaybird 5.0.4:

* Fixed: `PreparedStatement.executeBatch()` of statement without parameters throws "`Statement used in batch must have parameters [SQLState:07001, ISC error code:335545186]`" on Firebird 4.0 or higher (https://github.com/FirebirdSQL/jaybird/issues/788[#788])
+
Given the Firebird server-side batch facility doesn't support executing parameterless statements, the implementation now falls back to emulated batch execution for this case.
* ...
[#jaybird-5-0-4-changelog]
Expand Down Expand Up @@ -611,6 +614,7 @@ Jaybird always emulates batch support for `CallableStatement`.
The implementation might be rewritten in a future Jaybird version, if there is sufficient interest.
As a workaround, use `execute procedure` or `++{call procedure_name(...)}++` from a `PreparedStatement`.
* Requesting generated-keys will fall back to emulated behaviour as server-side batches do not support returning values produced by the `RETURNING` clause.
* Using parameterless statements will fall back to emulated behaviour (since Jaybird 5.0.5) as server-side batches do not support executing parameterless statements.
* The server-side batch update feature in Firebird 4.0 and higher has additional facilities to send `BLOB` values as part of the batch update.
This is not yet used by Jaybird.
Expand Down
15 changes: 12 additions & 3 deletions src/main/org/firebirdsql/jdbc/FBPreparedStatement.java
Original file line number Diff line number Diff line change
Expand Up @@ -601,9 +601,7 @@ private Batch requireBatch() throws SQLException {

// NOTE: This is not used for FBCallableStatement!
private Batch createBatch() throws SQLException {
if (connection != null && connection.isUseServerBatch()
&& fbStatement != null && fbStatement.supportBatchUpdates()
&& !isGeneratedKeyQuery()) {
if (canExecuteUsingServerBatch()) {
return new ServerBatch(
FbBatchConfig.of(FbBatchConfig.HALT_AT_FIRST_ERROR, FbBatchConfig.UPDATE_COUNTS,
FbBatchConfig.SERVER_DEFAULT_DETAILED_ERRORS, connection.getServerBatchBufferSize()),
Expand All @@ -613,6 +611,17 @@ private Batch createBatch() throws SQLException {
}
}

private boolean canExecuteUsingServerBatch() {
// enabled for connection
return connection != null && connection.isUseServerBatch()
// supported by statement implementation
&& fbStatement != null && fbStatement.supportBatchUpdates()
// server batch execution throws isc_batch_param when executing a statement without parameters
&& fbStatement.getParameterDescriptor().getCount() != 0
// server batch execution cannot produce rows from RETURNING
&& !isGeneratedKeyQuery();
}

@Override
public void addBatch() throws SQLException {
checkValidity();
Expand Down
28 changes: 26 additions & 2 deletions src/test/org/firebirdsql/jdbc/FBPreparedStatementTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,10 @@
import static org.junit.jupiter.api.Assumptions.assumeTrue;

/**
* @author <a href="mailto:[email protected]">Roman Rokytskyy</a>
* @author <a href="mailto:[email protected]">Mark Rotteveel</a>
* Tests for {@link FBPreparedStatement}.
*
* @author Roman Rokytskyy
* @author Mark Rotteveel
*/
class FBPreparedStatementTest {

Expand Down Expand Up @@ -1430,6 +1432,28 @@ void preparedStatementExecuteProcedureShouldNotTrim_729() throws Exception {
}
}

/**
* Test for <a href="https://github.com/FirebirdSQL/jaybird/issues/788">jaybird#788</a>
*/
@ParameterizedTest(name = "[{index}] useServerBatch = {0}")
@ValueSource(booleans = { true, false })
void executeBatchWithoutParameters(boolean useServerBatch) throws Exception {
executeCreateTable(con, CREATE_TABLE);

Properties props = FBTestProperties.getDefaultPropertiesForConnection();
props.setProperty(PropertyNames.useServerBatch, String.valueOf(useServerBatch));
try (Connection con = DriverManager.getConnection(FBTestProperties.getUrl(), props);
PreparedStatement pstmt = con.prepareStatement("insert into test default values")) {
pstmt.addBatch();
assertDoesNotThrow(pstmt::executeBatch);
}
try (Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("select count(*) from test")) {
assertTrue(rs.next(), "expected a row");
assertEquals(1, rs.getInt(1), "Expected one row in table test");
}
}

private void prepareTestData() throws SQLException {
con.setAutoCommit(false);
try (PreparedStatement pstmt = con.prepareStatement(INSERT_DATA)) {
Expand Down

0 comments on commit 1ecccac

Please sign in to comment.