Skip to content

Commit

Permalink
Backport #762 to Jaybird 5.0.5
Browse files Browse the repository at this point in the history
#762 Remove restriction to only allow calls to getResultSet if the result set was not returned yet
  • Loading branch information
mrotteveel committed Jun 14, 2024
1 parent ceff1cb commit 9ca9e30
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 54 deletions.
6 changes: 6 additions & 0 deletions src/docs/asciidoc/release_notes.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@ This feature was backported from Jaybird 6.
+
This improvement was backported from Jaybird 6.
* Fixed: `ResultSet.isBeforeFirst()` and `ResultSet.isAfterLast()` should always report `false` for an empty result set (https://github.com/FirebirdSQL/jaybird/issues/807[#807])
* Improvement: `Statement.getResultSet` no longer throws a `SQLException` with message "`Only one result set at a time/statement`" if the current result set has already been returned by `executeQuery` or a previous call to `getResultSet` (https://github.com/FirebirdSQL/jaybird/issues/762[#762])
+
Repeated calls to `getResultSet` will now return the current result set.
As part of this change implementations of `FirebirdStatement.getCurrentResultSet` now simply returns `getResultSet`, and the `getCurrentResultSet` method has been deprecated for removal in Jaybird 7.
+
This improvement was backported from Jaybird 6.
* ...
[#jaybird-5-0-4-changelog]
Expand Down
42 changes: 6 additions & 36 deletions src/main/org/firebirdsql/jdbc/FBCallableStatement.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ public class FBCallableStatement extends FBPreparedStatement implements Callable
static final String NATIVE_CALL_COMMAND = "EXECUTE PROCEDURE ";
static final String NATIVE_SELECT_COMMAND = "SELECT * FROM ";

private ResultSet currentRs;
private ResultSet singletonRs;

protected boolean selectableProcedure;
Expand Down Expand Up @@ -171,10 +170,7 @@ public boolean isSelectableProcedure() {
* @throws SQLException if something went wrong.
*/
protected void setRequiredTypes() throws SQLException {
if (singletonRs != null) {
setRequiredTypesInternal((FBResultSet) singletonRs);
}
setRequiredTypesInternal((FBResultSet) getCurrentResultSet());
setRequiredTypesInternal((FBResultSet) (singletonRs != null ? singletonRs : getResultSet()));
}

private void setRequiredTypesInternal(FBResultSet resultSet) throws SQLException {
Expand Down Expand Up @@ -246,16 +242,16 @@ public boolean execute() throws SQLException {
public ResultSet executeQuery() throws SQLException {
procedureCall.checkParameters();
try (LockCloseable ignored = withLock()) {
checkValidity();
notifyStatementStarted();
prepareFixedStatement(procedureCall.getSQL(isSelectableProcedure()));

if (!internalExecute(!isSelectableProcedure()))
throw new FBSQLException("No resultset for sql", SQLStateConstants.SQL_STATE_NO_RESULT_SET);

getResultSet();
setRequiredTypes();

return getCurrentResultSet();
ResultSet rs = getResultSet();
setRequiredTypesInternal((FBResultSet) rs);
return rs;
}
}

Expand Down Expand Up @@ -293,7 +289,6 @@ public int executeUpdate() throws SQLException {
// Execute statement internally. This method sets cached parameters. Rest of the processing is done by superclass.
@Override
protected boolean internalExecute(boolean sendOutParams) throws SQLException {
currentRs = null;
singletonRs = null;
int counter = 0;
for (FBProcedureParam param : procedureCall.getInputParams()) {
Expand Down Expand Up @@ -1107,14 +1102,6 @@ protected void assertHasData(ResultSet rs) throws SQLException {
}
}

// this method doesn't give an exception if it is called twice.
@Override
public ResultSet getCurrentResultSet() throws SQLException {
if (currentRs == null)
currentRs = super.getResultSet();
return currentRs;
}

/**
* Returns the result set for the singleton row of the callable statement and asserts it has data. If this is a
* selectable procedure, or there is no singleton row, it will return the normal result set.
Expand All @@ -1127,28 +1114,11 @@ public ResultSet getCurrentResultSet() throws SQLException {
* @throws SQLException For database access errors
*/
protected ResultSet getAndAssertSingletonResultSet() throws SQLException {
final ResultSet rs;
if (!isSelectableProcedure() && singletonRs != null) {
rs = singletonRs;
} else {
rs = getCurrentResultSet();
}
final ResultSet rs = !isSelectableProcedure() && singletonRs != null ? singletonRs : getResultSet();
assertHasData(rs);
return rs;
}

/**
* {@inheritDoc}
* <p>
* Calling this method twice with autocommit on and used will probably
* throw an inappropriate or uninformative exception.
* </p>
*/
@Override
public ResultSet getResultSet() throws SQLException {
return getCurrentResultSet();
}

@Override
public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException {
procedureCall.getInputParam(parameterIndex).setValue(x);
Expand Down
25 changes: 16 additions & 9 deletions src/main/org/firebirdsql/jdbc/FBStatement.java
Original file line number Diff line number Diff line change
Expand Up @@ -530,26 +530,26 @@ public ResultSet getResultSet() throws SQLException {
public ResultSet getResultSet(boolean metaDataQuery) throws SQLException {
if (fbStatement == null) {
throw new FBSQLException("No statement was executed.");
} else if (currentRs != null) {
return currentRs;
}

if (cursorName != null) {
fbStatement.setCursorName(cursorName);
}

if (currentRs != null) {
throw new FBSQLException("Only one result set at a time/statement.");
}

// A generated keys query does not produce a normal result set (but EXECUTE PROCEDURE or INSERT ... RETURNING without Statement.RETURN_GENERATED_KEYS do)
// TODO Behavior might not be correct for callable statement implementation
if (!isGeneratedKeyQuery() && currentStatementResult.isResultSet()) {
if (!isSingletonResult) {
currentRs = new FBResultSet(connection, this, fbStatement, resultSetListener, metaDataQuery, rsType,
rsConcurrency, rsHoldability, false);
if (cursorName != null) {
fbStatement.setCursorName(cursorName);
}
return currentRs = new FBResultSet(connection, this, fbStatement, resultSetListener, metaDataQuery,
rsType, rsConcurrency, rsHoldability, false);
} else if (!specialResult.isEmpty()) {
currentRs = createSpecialResultSet(resultSetListener);
return currentRs = createSpecialResultSet(resultSetListener);
}
return currentRs;
}
return null;
}
Expand Down Expand Up @@ -826,9 +826,16 @@ void closeResultSet(boolean notifyListener, CompletionReason completionReason) t
}
}

/**
* {@inheritDoc}
*
* @deprecated Use {@link #getResultSet()} instead, will be removed in Jaybird 7
*/
@SuppressWarnings("removal")
@Deprecated
@Override
public ResultSet getCurrentResultSet() throws SQLException {
return currentRs;
return getResultSet();
}

@Override
Expand Down
18 changes: 9 additions & 9 deletions src/main/org/firebirdsql/jdbc/FirebirdStatement.java
Original file line number Diff line number Diff line change
Expand Up @@ -80,17 +80,17 @@ public interface FirebirdStatement extends Statement {
* with this statement, otherwise <code>false</code>.
*/
boolean hasOpenResultSet();

/**
* Get current result set. Behaviour of this method is similar to the
* behavior of the {@link Statement#getResultSet()}, except that this method
* can be called as much as you like.
*
* @return instance of {@link ResultSet} representing current result set
* or <code>null</code> if it is not available.
*
* @throws SQLException if database access error happened.
* Get current result set. Behaviour of this method is similar to the behavior of the
* {@link Statement#getResultSet()}.
*
* @return instance of {@link ResultSet} representing current result set or {@code null} if it is not available.
* @throws SQLException
* if a database access error happens
* @deprecated Use {@link #getResultSet()} instead, will be removed in Jaybird 7
*/
@Deprecated
ResultSet getCurrentResultSet() throws SQLException;

/**
Expand Down
22 changes: 22 additions & 0 deletions src/test/org/firebirdsql/jdbc/FBStatementTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -1096,6 +1096,28 @@ void statementExecuteProcedureShouldNotTrim_729() throws Exception {
}
}

@Test
void getResultSetAfterExecuteQuery_sameResultSet() throws Exception {
try (Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("select 1 from rdb$database")) {
ResultSet sameRs = assertDoesNotThrow(stmt::getResultSet);

assertSame(rs, sameRs, "Expected ResultSet from getResultSet to be the same as from executeQuery");
}
}

@Test
void multipleGetResultSetCalls_sameResultSet() throws SQLException {
try (Statement stmt = con.createStatement()) {
assertTrue(stmt.execute("select 1 from rdb$database"), "Expected a result set as first result");

ResultSet rs = stmt.getResultSet();
ResultSet sameRs = assertDoesNotThrow(stmt::getResultSet);

assertSame(rs, sameRs, "Expected ResultSet from getResultSet to be the same as from previous getResultSet");
}
}

private void prepareTestData() throws SQLException {
executeCreateTable(con, CREATE_TABLE);

Expand Down

0 comments on commit 9ca9e30

Please sign in to comment.