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