diff --git a/src/main/org/firebirdsql/jdbc/FBObjectListener.java b/src/main/org/firebirdsql/jdbc/FBObjectListener.java index ba7e08157..3f6f25b7c 100644 --- a/src/main/org/firebirdsql/jdbc/FBObjectListener.java +++ b/src/main/org/firebirdsql/jdbc/FBObjectListener.java @@ -20,6 +20,8 @@ import org.firebirdsql.gds.ng.fields.RowValue; import org.firebirdsql.util.InternalApi; +import org.jspecify.annotations.NullMarked; +import org.jspecify.annotations.Nullable; import java.sql.ResultSet; import java.sql.SQLException; @@ -37,6 +39,7 @@ private FBObjectListener() { // no instances } + @NullMarked public interface FetcherListener { /** @@ -50,7 +53,7 @@ public interface FetcherListener { * @param newRow * new row */ - default void rowChanged(FBFetcher fetcher, RowValue newRow) throws SQLException { + default void rowChanged(FBFetcher fetcher, @Nullable RowValue newRow) throws SQLException { // do nothing } @@ -59,6 +62,7 @@ default void rowChanged(FBFetcher fetcher, RowValue newRow) throws SQLException /** * Listener for the events generated by the result set. */ + @NullMarked public interface ResultSetListener { /** diff --git a/src/main/org/firebirdsql/jdbc/FBUpdatableFetcher.java b/src/main/org/firebirdsql/jdbc/FBUpdatableFetcher.java index a1b137503..32952a47e 100644 --- a/src/main/org/firebirdsql/jdbc/FBUpdatableFetcher.java +++ b/src/main/org/firebirdsql/jdbc/FBUpdatableFetcher.java @@ -19,6 +19,8 @@ package org.firebirdsql.jdbc; import org.firebirdsql.gds.ng.fields.RowValue; +import org.jspecify.annotations.NullMarked; +import org.jspecify.annotations.Nullable; import java.sql.SQLException; import java.sql.SQLNonTransientException; @@ -44,13 +46,14 @@ * * @since 5 */ +@NullMarked final class FBUpdatableFetcher implements FBFetcher { private final FBFetcher fetcher; private final RowValue deletedRowMarker; private FBObjectListener.FetcherListener fetcherListener; - private Map modifiedRows = new HashMap<>(); + private Map modifiedRows = new HashMap<>(); private int position; private List insertedRows = new ArrayList<>(); @@ -100,7 +103,7 @@ private boolean notifyInsertedRow(int position) throws SQLException { return notifyRow(position, rowValue); } - private boolean notifyRow(int position, RowValue originalRowValue) throws SQLException { + private boolean notifyRow(int position, @Nullable RowValue originalRowValue) throws SQLException { RowValue rowValue = modifiedRows.getOrDefault(position, originalRowValue); fetcherListener.rowChanged(fetcher, rowValue); return rowValue != null; @@ -356,10 +359,10 @@ public boolean rowDeleted() throws SQLException { private static final class InternalFetcherListener implements FBObjectListener.FetcherListener { - RowValue lastReceivedRow; + @Nullable RowValue lastReceivedRow; @Override - public void rowChanged(FBFetcher fetcher, RowValue newRow) { + public void rowChanged(FBFetcher fetcher, @Nullable RowValue newRow) { lastReceivedRow = newRow; } diff --git a/src/test/org/firebirdsql/jdbc/FBServerScrollFetcherTest.java b/src/test/org/firebirdsql/jdbc/FBServerScrollFetcherTest.java index 5fefca159..2885333c5 100644 --- a/src/test/org/firebirdsql/jdbc/FBServerScrollFetcherTest.java +++ b/src/test/org/firebirdsql/jdbc/FBServerScrollFetcherTest.java @@ -544,7 +544,7 @@ execute block (records INTEGER = ?) } private int extractId(RowValue rowValue) { - return db.getDatatypeCoder().decodeInt(rowValue.getFieldData(0)); + return rowValue != null ? db.getDatatypeCoder().decodeInt(rowValue.getFieldData(0)) : Integer.MIN_VALUE; } } \ No newline at end of file diff --git a/src/test/org/firebirdsql/jdbc/SimpleFetcherListener.java b/src/test/org/firebirdsql/jdbc/SimpleFetcherListener.java index 875e1b3a5..bc2c3e234 100644 --- a/src/test/org/firebirdsql/jdbc/SimpleFetcherListener.java +++ b/src/test/org/firebirdsql/jdbc/SimpleFetcherListener.java @@ -19,6 +19,8 @@ package org.firebirdsql.jdbc; import org.firebirdsql.gds.ng.fields.RowValue; +import org.jspecify.annotations.NullMarked; +import org.jspecify.annotations.Nullable; import java.util.ArrayList; import java.util.List; @@ -26,16 +28,17 @@ import static org.junit.jupiter.api.Assertions.assertTrue; +@NullMarked final class SimpleFetcherListener implements FBObjectListener.FetcherListener { - final List receivedRows = new ArrayList<>(); + final List<@Nullable RowValue> receivedRows = new ArrayList<>(); @Override - public void rowChanged(FBFetcher fetcher, RowValue newRow) { + public void rowChanged(FBFetcher fetcher, @Nullable RowValue newRow) { receivedRows.add(newRow); } - void assertRow(int rowIndex, Consumer assertion) { + void assertRow(int rowIndex, Consumer<@Nullable RowValue> assertion) { assertTrue(0 <= rowIndex && rowIndex < receivedRows.size(), () -> "row index out of range: " + rowIndex); assertion.accept(receivedRows.get(rowIndex)); }