Skip to content

Commit

Permalink
#817 Frontport to Jaybird 6: #816 ResultSet wasNull throws exception …
Browse files Browse the repository at this point in the history
…on insert row
  • Loading branch information
mrotteveel committed Sep 17, 2024
1 parent 16d4166 commit 3f769ec
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 41 deletions.
42 changes: 9 additions & 33 deletions src/main/org/firebirdsql/jdbc/FBResultSet.java
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@ public class FBResultSet implements ResultSet, FirebirdResultSet, FBObjectListen
protected RowValue row;

private boolean wasNull;
private boolean wasNullValid;

private final FBField[] fields;
private final List<FBCloseableField> closeableFields = new ArrayList<>();
Expand Down Expand Up @@ -297,12 +296,10 @@ protected void checkScrollable() throws SQLException {
* if something wrong happened.
*/
protected void closeFields() throws SQLException {
// TODO See if we can apply completion reason logic (eg no need to close blob on commit)
wasNullValid = false;

// if there are no fields to close, then nothing to do
if (closeableFields.isEmpty())
return;
// TODO See if we can apply completion reason logic (e.g. no need to close blob on commit)
wasNull = false;
// if there are no fields to close, then nothing else to do
if (closeableFields.isEmpty()) return;

var chain = new SQLExceptionChainBuilder();
// close current fields, so that resources are freed.
Expand Down Expand Up @@ -383,12 +380,7 @@ void close(boolean notifyListener, CompletionReason completionReason) throws SQL

@Override
public boolean wasNull() throws SQLException {
if (!wasNullValid) {
throw new SQLException("Get a column before testing null");
}
if (row == null) {
throw new SQLException("No row available for wasNull");
}
checkOpen();
return wasNull;
}

Expand Down Expand Up @@ -530,11 +522,8 @@ public Reader getNCharacterStream(int columnIndex) throws SQLException {
* If there is an error accessing the field
*/
public FBField getField(int columnIndex) throws SQLException {
final FBField field = getField(columnIndex, true);

wasNullValid = true;
wasNull = row == null || row.getFieldData(columnIndex - 1) == null;

FBField field = getField(columnIndex, true);
wasNull = field.isNull();
return field;
}

Expand All @@ -553,11 +542,7 @@ public FBField getField(int columnIndex, boolean checkRowPosition) throws SQLExc
SQLStateConstants.SQL_STATE_INVALID_DESC_FIELD_ID);
}

if (rowUpdater != null) {
return rowUpdater.getField(columnIndex - 1);
} else {
return fields[columnIndex - 1];
}
return rowUpdater != null ? rowUpdater.getField(columnIndex - 1) : fields[columnIndex - 1];
}

/**
Expand All @@ -569,19 +554,10 @@ public FBField getField(int columnIndex, boolean checkRowPosition) throws SQLExc
* if the field cannot be retrieved
*/
public FBField getField(String columnName) throws SQLException {
checkOpen();
if (row == null && rowUpdater == null) {
throw new SQLException("The result set is not in a row, use next", SQLStateConstants.SQL_STATE_NO_ROW_AVAIL);
}
requireNonEmpty(columnName);

try {
int fieldNum = colNames.computeIfAbsent(columnName,
SQLExceptionThrowingFunction.toFunction(this::findColumn));
final FBField field = rowUpdater != null ? rowUpdater.getField(fieldNum - 1) : fields[fieldNum - 1];
wasNullValid = true;
wasNull = row == null || row.getFieldData(fieldNum - 1) == null;
return field;
return getField(fieldNum);
} catch (UncheckedSQLException e) {
throw e.getCause();
}
Expand Down
56 changes: 48 additions & 8 deletions src/test/org/firebirdsql/jdbc/FBResultSetTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -1467,6 +1467,20 @@ void testIsBeforeFirst_isAfterLast_emptyResultSet_bug807(int resultSetType, int
}
}

static Stream<Arguments> testIsBeforeFirst_isAfterLast_emptyResultSet_bug807() {
Stream<Arguments> defaultArguments = Stream.of(
Arguments.of(TYPE_FORWARD_ONLY, CONCUR_READ_ONLY, SCROLLABLE_CURSOR_EMULATED),
Arguments.of(TYPE_FORWARD_ONLY, CONCUR_UPDATABLE, SCROLLABLE_CURSOR_EMULATED),
Arguments.of(TYPE_SCROLL_INSENSITIVE, CONCUR_READ_ONLY, SCROLLABLE_CURSOR_EMULATED),
Arguments.of(TYPE_SCROLL_INSENSITIVE, CONCUR_UPDATABLE, SCROLLABLE_CURSOR_EMULATED));
if (getDefaultSupportInfo().supportsScrollableCursors()) {
return Stream.concat(defaultArguments, Stream.of(
Arguments.of(TYPE_SCROLL_INSENSITIVE, CONCUR_READ_ONLY, SCROLLABLE_CURSOR_SERVER),
Arguments.of(TYPE_SCROLL_INSENSITIVE, CONCUR_UPDATABLE, SCROLLABLE_CURSOR_SERVER)));
}
return defaultArguments;
}

/**
* Rationale: see <a href="https://github.com/FirebirdSQL/jaybird/blob/master/devdoc/jdp/jdp-2024-03-do-not-close-result-set-after-last-row-in-auto-commit.adoc">jdp-2024-03: Do not close result set after last row in auto-commit</a>
*/
Expand All @@ -1483,16 +1497,42 @@ void testNextAfterLastRowShouldNotCloseResultSet(boolean autoCommit) throws Exce
}
}

static Stream<Arguments> testIsBeforeFirst_isAfterLast_emptyResultSet_bug807() {
Stream<Arguments> defaultArguments = Stream.of(
Arguments.of(TYPE_FORWARD_ONLY, CONCUR_READ_ONLY, SCROLLABLE_CURSOR_EMULATED),
Arguments.of(TYPE_FORWARD_ONLY, CONCUR_UPDATABLE, SCROLLABLE_CURSOR_EMULATED),
Arguments.of(TYPE_SCROLL_INSENSITIVE, CONCUR_READ_ONLY, SCROLLABLE_CURSOR_EMULATED),
Arguments.of(TYPE_SCROLL_INSENSITIVE, CONCUR_UPDATABLE, SCROLLABLE_CURSOR_EMULATED));
@ParameterizedTest
@MethodSource
void wasNull_onInsertRow(int resultSetType, String scrollableCursorPropertyValue) throws Exception {
try (var connection = createConnection(scrollableCursorPropertyValue)) {
executeCreateTable(connection, "create table t1 (i int primary key, v varchar(10))");

try (var pstmt = connection.prepareStatement("insert into t1 values(?, ?)")) {
for (int i = 1; i <= 10; i++) {
pstmt.setInt(1, i);
pstmt.setString(2, i + " s");
pstmt.addBatch();
}
pstmt.executeBatch();
}

try (var stmt = connection.createStatement(resultSetType, CONCUR_UPDATABLE);
var rs = stmt.executeQuery("select i, v from t1")) {
rs.moveToInsertRow();
rs.updateNull(1);
rs.updateString(2, "11 s");

assertNull(rs.getObject(1), "column 1");
assertTrue(rs.wasNull(), "column 1");
assertEquals("11 s", rs.getObject(2), "column 2");
assertFalse(rs.wasNull(), "column 2");
}
}
}

static Stream<Arguments> wasNull_onInsertRow() {
var defaultArguments = Stream.of(
Arguments.of(TYPE_FORWARD_ONLY, SCROLLABLE_CURSOR_EMULATED),
Arguments.of(TYPE_SCROLL_INSENSITIVE, SCROLLABLE_CURSOR_EMULATED));
if (getDefaultSupportInfo().supportsScrollableCursors()) {
return Stream.concat(defaultArguments, Stream.of(
Arguments.of(TYPE_SCROLL_INSENSITIVE, CONCUR_READ_ONLY, SCROLLABLE_CURSOR_SERVER),
Arguments.of(TYPE_SCROLL_INSENSITIVE, CONCUR_UPDATABLE, SCROLLABLE_CURSOR_SERVER)));
Arguments.of(TYPE_SCROLL_INSENSITIVE, SCROLLABLE_CURSOR_SERVER)));
}
return defaultArguments;
}
Expand Down

0 comments on commit 3f769ec

Please sign in to comment.