diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fc70939577..79105c3924 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -98,9 +98,11 @@ jobs: name: spinnaker-exe.jar path: SpiNNaker-front-end/target/spinnaker-exe.jar retention-days: 5 + continue-on-error: true - name: Submit Dependency Snapshot if: matrix.java == 17 uses: advanced-security/maven-dependency-submission-action@v3 + continue-on-error: true validate: needs: compile diff --git a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/GeneratesID.java b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/GeneratesID.java index 518bff578e..63a674b06c 100644 --- a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/GeneratesID.java +++ b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/GeneratesID.java @@ -21,14 +21,27 @@ import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.Target; +import java.sql.Statement; +import java.sql.PreparedStatement; + +import uk.ac.manchester.spinnaker.utils.UsedInJavadocOnly; /** * Used to document that some DML is expected to generate an ID. + *

+ * NB: Do not use with SQLite from 3.43 onwards. The + * Xerial driver removed support for + * {@link Statement#getGeneratedKeys()} in version 3.43.0; use a + * {@code RETURNING} clause instead, and handle via + * {@link PreparedStatement#executeQuery()} instead of + * {@link PreparedStatement#executeUpdate()}. This limitation only applies to + * that driver. * * @author Donal Fellows */ @Retention(SOURCE) @Target(FIELD) @Documented +@UsedInJavadocOnly({PreparedStatement.class, Statement.class}) public @interface GeneratesID { } diff --git a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQL.java b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQL.java index f818f56d96..987b2d3720 100644 --- a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQL.java +++ b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQL.java @@ -15,7 +15,6 @@ */ package uk.ac.manchester.spinnaker.storage.sqlite; -import uk.ac.manchester.spinnaker.storage.GeneratesID; import uk.ac.manchester.spinnaker.storage.Parameter; import uk.ac.manchester.spinnaker.storage.Parameters; import uk.ac.manchester.spinnaker.storage.ResultColumn; @@ -37,9 +36,10 @@ private SQL() { @Parameter("x") @Parameter("y") @Parameter("processor") - @GeneratesID + @ResultColumn("core_id") static final String INSERT_LOCATION = - "INSERT INTO core(x, y, processor) VALUES(?, ?, ?)"; + "INSERT INTO core(x, y, processor) VALUES(?, ?, ?) " + + "RETURNING core_id"; /** Find an existing (x,y,p) record. */ @Parameter("x") @@ -53,10 +53,10 @@ private SQL() { @Parameter("core_id") @Parameter("local_region_index") @Parameter("address") - @GeneratesID + @ResultColumn("region_id") static final String INSERT_REGION = "INSERT INTO " + "region(core_id, local_region_index, address)" - + " VALUES (?, ?, ?)"; + + " VALUES (?, ?, ?) RETURNING region_id"; /** Find an existing region record. */ @Parameter("core_id") @@ -85,10 +85,10 @@ private SQL() { @Parameter("region_id") @Parameter("content_to_add") @Parameter("content_len") - @GeneratesID + @ResultColumn("extra_id") static final String ADD_EXTRA_CONTENT = "INSERT INTO region_extra(region_id, content, content_len) " - + "VALUES (?, CAST(? AS BLOB), ?)"; + + "VALUES (?, CAST(? AS BLOB), ?) RETURNING extra_id"; /** * Discover whether region in the main region table is available for storing diff --git a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteBufferStorage.java b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteBufferStorage.java index 7f5af17783..b77069d2e2 100644 --- a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteBufferStorage.java +++ b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteBufferStorage.java @@ -17,7 +17,6 @@ import static java.lang.System.arraycopy; import static java.lang.System.currentTimeMillis; -import static java.sql.Statement.RETURN_GENERATED_KEYS; import static org.slf4j.LoggerFactory.getLogger; import static uk.ac.manchester.spinnaker.storage.sqlite.SQL.ADD_CONTENT; import static uk.ac.manchester.spinnaker.storage.sqlite.SQL.ADD_EXTRA_CONTENT; @@ -81,14 +80,17 @@ private static int getRecordingCore(Connection conn, CoreLocation core) } } } - try (var s = conn.prepareStatement(INSERT_LOCATION, - RETURN_GENERATED_KEYS)) { + try (var s = conn.prepareStatement(INSERT_LOCATION)) { // x, y, processor setArguments(s, core.getX(), core.getY(), core.getP()); - s.executeUpdate(); - return getLastKey(s).orElseThrow(() -> new IllegalStateException( - "could not make or find recording region core record")); + try (var rs = s.executeQuery()) { + while (rs.next()) { + return rs.getInt("core_id"); + } + } } + throw new IllegalStateException( + "could not make or find recording region core record"); } private static int getRecordingRegion(Connection conn, int coreID, @@ -102,15 +104,18 @@ private static int getRecordingRegion(Connection conn, int coreID, } } } - try (var s = conn.prepareStatement(INSERT_REGION, - RETURN_GENERATED_KEYS)) { + try (var s = conn.prepareStatement(INSERT_REGION)) { // core_id, local_region_index, address setArguments(s, coreID, region.regionIndex, region.startAddress.address); - s.executeUpdate(); - return getLastKey(s).orElseThrow(() -> new IllegalStateException( - "could not make or find recording region record")); + try (var rs = s.executeQuery()) { + while (rs.next()) { + return rs.getInt("region_id"); + } + } } + throw new IllegalStateException( + "could not make or find recording region record"); } private void appendRecordingContents(Connection conn, int regionID, @@ -132,7 +137,7 @@ private void appendRecordingContents(Connection conn, int regionID, private static byte[] read(ByteArrayInputStream chunk, int chunkLen) throws SQLException { - byte[] buffer = new byte[chunkLen]; + var buffer = new byte[chunkLen]; int len; try { len = IOUtils.read(chunk, buffer, 0, chunkLen); @@ -144,7 +149,7 @@ private static byte[] read(ByteArrayInputStream chunk, int chunkLen) } else if (len <= 0) { return new byte[0]; } - byte[] nb = new byte[len]; + var nb = new byte[len]; arraycopy(buffer, 0, nb, 0, len); return nb; } @@ -169,13 +174,18 @@ private void prepareExtraContent(Connection conn, int regionID, } } - private void addExtraContentRow(Connection conn, int regionID, int chunkLen, + private int addExtraContentRow(Connection conn, int regionID, int chunkLen, ByteArrayInputStream chunk) throws SQLException { try (var s = conn.prepareStatement(ADD_EXTRA_CONTENT)) { // region_id, content setArguments(s, regionID, read(chunk, chunkLen), chunkLen); - s.executeUpdate(); + try (var rs = s.executeQuery()) { + while (rs.next()) { + return rs.getInt("extra_id"); + } + } } + throw new IllegalStateException("no row inserted"); } private boolean useMainTable(Connection conn, int regionID) diff --git a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteConnectionManager.java b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteConnectionManager.java index 384f960e2b..d0543f9cc2 100644 --- a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteConnectionManager.java +++ b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteConnectionManager.java @@ -21,8 +21,6 @@ import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; -import java.sql.Statement; -import java.util.Optional; import org.slf4j.Logger; import org.sqlite.SQLiteException; @@ -79,25 +77,6 @@ protected static void setArguments(PreparedStatement statement, } } - /** - * Get the last key generated by an executing statement. - * - * @param statement - * The statement. - * @return The generated key, if there was one. - * @throws SQLException - * If the statement isn't open. - */ - protected static Optional getLastKey(Statement statement) - throws SQLException { - try (var keys = statement.getGeneratedKeys()) { - while (keys.next()) { - return Optional.of(keys.getInt(1)); - } - } - return Optional.empty(); - } - /** * A wrapped piece of code that produces a result. * diff --git a/pom.xml b/pom.xml index 9d63dff4e0..be4766c98c 100644 --- a/pom.xml +++ b/pom.xml @@ -57,13 +57,13 @@ limitations under the License. 4.0.2 2.15.2 2.14 - 3.42.0.0 + 3.43.0.0 22.0.1 5.4.2 1.0.5 2.7.3 2.21.1 - 4.7.4 + 4.7.5 8.1.0 1.19.0 2.1.1