-
Notifications
You must be signed in to change notification settings - Fork 658
Description
Describe the bug
A non-existent (in Android JDK) BatchUpdateException constructor is called by JDBC3Statement.executeLargeBatch().
The exception in question:
java.lang.NoSuchMethodError: No direct method <init>(Ljava/lang/String;Ljava/lang/String;I[JLjava/lang/Throwable;)V in class Ljava/sql/BatchUpdateException; or its super classes (declaration of 'java.sql.BatchUpdateException' appears in /system/framework/core-oj.jar)
The incompatibility is caused by 4102c1d that replaced int[] argument with long[] that is not supported by Android JDK (any version).
To Reproduce
- Create an empty Android App/Service project (any SDK level, confirmed with SDK 25) with Xerial SQLite.
- Run this sample code on a real Android JDK (as an instrumented unit test, or as a part of a production APK)
import org.junit.Test
import java.sql.DriverManager
class BatchInsertTest {
@Test
fun reproduceBatchInsertException() {
// Using in-memory db not to bother with files and paths.
// The problem reproduces in file-based db as well.
val connection = DriverManager.getConnection("jdbc:sqlite::memory:")
val statement = connection.createStatement()
statement.addBatch("AN INVALID SQL STATEMENT;")
// This call throws the aforementioned exception. See full stacktrace below.
statement.executeBatch()
}
}Expected behavior
The actual error should be correctly wrapped and passed up the stack trace:
org.sqlite.SQLiteException: [SQLITE_ERROR] SQL error or missing database (near "AN": syntax error)
Logs
The error with stacktrace:
java.lang.NoSuchMethodError: No direct method <init>(Ljava/lang/String;Ljava/lang/String;I[JLjava/lang/Throwable;)V in class Ljava/sql/BatchUpdateException; or its super classes (declaration of 'java.sql.BatchUpdateException' appears in /system/framework/core-oj.jar)
at org.sqlite.jdbc3.JDBC3Statement.executeLargeBatch(JDBC3Statement.java:245)
at org.sqlite.jdbc3.JDBC3Statement.executeBatch(JDBC3Statement.java:225)
at BatchInsertTest.reproduceBatchInsertException(BatchInsertTest.kt:15)
<...>
Environment (please complete the following information):
- OS: Android 7.1 & 12
- CPU architecture: arm64
- sqlite-jdbc version 3.46.1.0
The big picture
My intention is not to fix this particular problem, but to highlight a fundamental issue with compatibility between Xerial SQLite and Android JDK.
The only requirement for Android, stated by Xerial SQLite (in Supported Operating Systems section) is "API Level 24+".
This bug proves this statement to be wrong.
Since there's no defined backward compatibility guarantees for Android JDK, an assumption that everything that's available in Java will be available in Android JDK can create unexpected issues.
The question of compatibility with Android JDK should be treated with care.
A possible solution would be to analyze the code for compatibility with different Android SDK/JDK versions for every release.
In case there's something unavailable in Android SDK 24+ found to be used, either
a) a (preferably) code fix
or
b) a stipulation in documentation may be made.
It would be very handy to have a list of Xerial SQLite functionality that can be safely used in Android environments.
There's a plugin that can be considered for doing this automatically: https://github.com/xvik/gradle-animalsniffer-plugin.
If supplied with Android SDK 24 headers, it could search all the calls in Xerial project and highlight those that are not available.
The result may be:
a) Considered as a build failure -- to fix & provide full compatibility
b) Analyzed and published -- to provide clear picture