Details
-
Bug
-
Status: Closed (View Workflow)
-
Major
-
Resolution: Fixed
-
3.5.9
-
None
-
Connector/J 3.5.8 and 3.5.9, MariaDB server 11.8 (any server supporting bulk unit results, i.e. 11.5.1+), Java 21, default
connection options (useBulkStmtsForInserts=true).
Description
When a batch INSERT is executed on a PreparedStatement created with Statement.RETURN_GENERATED_KEYS, and the table's AUTO_INCREMENT counter is above Integer.MAX_VALUE (2,147,483,647), getGeneratedKeys() throws java.sql.SQLDataException: integer overflow. This makes generated-key retrieval unusable on any large table with a BIGINT AUTO_INCREMENT primary key and breaks frameworks that read keys after batch inserts (e.g. Spring Data JDBC saveAll).
Root cause: BasePreparedStatement.addAutoGeneratedIdIfPresent reads each auto-generated id from the bulk unit results with ResultSet.getInt(1) even though the id column is BIGINT: https://github.com/mariadb-corporation/mariadb-connector-j/blob/3.5.9/src/main/java/org/mariadb/jdbc/BasePreparedStatement.java#L2077-L2083
▎ private void addAutoGeneratedIdIfPresent(Result unitaryResults, List<String[]> insertIds)
▎ throws SQLException {
▎ int autoGeneratedId = unitaryResults.getInt(1); // <-- overflows for ids > 2^31-1
▎ if (autoGeneratedId != 0) {
▎ insertIds.add(new String[]
);
▎ }
▎ }
▎
Note the synthetic result set built from these values in createGeneratedKeysResultSet is already declared DataType.BIGINT
with ColumnFlags.UNSIGNED, so the values themselves are expected to exceed int range — only this intermediate getInt
truncates. Reading with getLong(1) (or getString(1) to preserve the full unsigned range) fixes it.
This path is only reached for bulk batch inserts with unit results (server 11.5.1+, useBulkStmtsForInserts=true); single inserts are unaffected. Workaround: useBulkStmtsForInserts=false.
Reproduction (fails on 3.5.8 and 3.5.9 against mariadb:11.8):
▎
▎ try (Connection con = DriverManager.getConnection("jdbc:mariadb://localhost:3306/test", "root", "pw");
▎ Statement st = con.createStatement()) {
▎ st.execute("CREATE TABLE t (id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, val VARCHAR(10))
▎ AUTO_INCREMENT=2147483646");
▎ try (PreparedStatement ps = con.prepareStatement("INSERT INTO t(val) VALUES
", Statement.RETURN_GENERATED_KEYS)) {
▎ for (int i = 0; i < 3; i++)
▎ ps.executeBatch();
▎ try (ResultSet rs = ps.getGeneratedKeys())
▎ }
▎ }
▎
▎ Exception in thread "main" java.sql.SQLDataException: integer overflow
▎ at org.mariadb.jdbc.client.column.SignedBigIntColumn.decodeIntBinary(SignedBigIntColumn.java:191)
▎ at org.mariadb.jdbc.client.result.rowdecoder.BinaryRowDecoder.decodeInt(BinaryRowDecoder.java:135)
▎ at org.mariadb.jdbc.client.result.Result.getInt(Result.java:525)
▎ at org.mariadb.jdbc.BasePreparedStatement.addAutoGeneratedIdIfPresent(BasePreparedStatement.java:2079)
▎ at org.mariadb.jdbc.BasePreparedStatement.processUnitaryResults(BasePreparedStatement.java:2073)
▎ at org.mariadb.jdbc.BasePreparedStatement.extractInsertIds(BasePreparedStatement.java:2052)
▎ at org.mariadb.jdbc.BasePreparedStatement.getGeneratedKeys(BasePreparedStatement.java:2026)
▎
▎ Expected: generated keys 2147483646, 2147483647, 2147483648. Actual: SQLDataException: integer overflow.
▎
▎ Related quirk in the same method: the if (autoGeneratedId != 0) guard silently drops a key that decodes to 0, which would
▎ misalign keys with batch rows — worth addressing in the same fix.