Merge changes I83c953c5,I1fe0e1a8 into androidx-main
* changes:
Reorganize sqlite-bundled source sets names to match room-runtime pattern.
Add an open() overload that receives open flags to bundled driver.
diff --git a/sqlite/integration-tests/driver-conformance-test/build.gradle b/sqlite/integration-tests/driver-conformance-test/build.gradle
index cd02e2c..fd7b912 100644
--- a/sqlite/integration-tests/driver-conformance-test/build.gradle
+++ b/sqlite/integration-tests/driver-conformance-test/build.gradle
@@ -40,8 +40,10 @@
commonTest {
dependencies {
implementation(project(":sqlite:sqlite"))
+ implementation(project(":sqlite:sqlite-bundled"))
implementation(libs.kotlinStdlib)
implementation(libs.kotlinTest)
+ implementation(libs.kotlinCoroutinesTest)
implementation(project(":kruth:kruth"))
}
}
@@ -49,8 +51,6 @@
dependsOn(commonTest)
dependencies {
implementation(project(":sqlite:sqlite-framework"))
- implementation(project(":sqlite:sqlite-bundled"))
-
implementation(libs.kotlinTestJunit)
implementation(libs.testRunner)
implementation(libs.testCore)
@@ -59,8 +59,6 @@
jvmTest {
dependsOn(commonTest)
dependencies {
- implementation(project(":sqlite:sqlite-bundled"))
-
implementation(libs.kotlinTestJunit)
}
}
@@ -68,7 +66,6 @@
dependsOn(commonTest)
dependencies {
implementation(project(":sqlite:sqlite-framework"))
- implementation(project(":sqlite:sqlite-bundled"))
}
}
targets.configureEach { target ->
diff --git a/sqlite/integration-tests/driver-conformance-test/src/androidInstrumentedTest/kotlin/androidx/sqlite/driver/test/BundledSQLiteDriverTest.kt b/sqlite/integration-tests/driver-conformance-test/src/androidInstrumentedTest/kotlin/androidx/sqlite/driver/test/BundledSQLiteDriverTest.kt
index 1772073..fca79a9 100644
--- a/sqlite/integration-tests/driver-conformance-test/src/androidInstrumentedTest/kotlin/androidx/sqlite/driver/test/BundledSQLiteDriverTest.kt
+++ b/sqlite/integration-tests/driver-conformance-test/src/androidInstrumentedTest/kotlin/androidx/sqlite/driver/test/BundledSQLiteDriverTest.kt
@@ -16,14 +16,38 @@
package androidx.sqlite.driver.test
-import androidx.sqlite.SQLiteDriver
+import androidx.kruth.assertThat
import androidx.sqlite.driver.bundled.BundledSQLiteDriver
+import androidx.test.platform.app.InstrumentationRegistry
+import kotlin.test.AfterTest
+import kotlin.test.BeforeTest
class BundledSQLiteDriverTest : BaseBundledConformanceTest() {
+ private val instrumentation = InstrumentationRegistry.getInstrumentation()
+ private val file = instrumentation.targetContext.getDatabasePath("test.db")
+
override val driverType = TestDriverType.BUNDLED
- override fun getDriver(): SQLiteDriver {
+ override fun getDatabaseFileName(): String = file.path
+
+ override fun getDriver(): BundledSQLiteDriver {
return BundledSQLiteDriver()
}
+
+ @BeforeTest
+ fun before() {
+ assertThat(file).isNotNull()
+ file.parentFile?.mkdirs()
+ deleteDatabaseFile()
+ }
+
+ @AfterTest
+ fun after() {
+ deleteDatabaseFile()
+ }
+
+ private fun deleteDatabaseFile() {
+ instrumentation.targetContext.deleteDatabase(file.name)
+ }
}
diff --git a/sqlite/integration-tests/driver-conformance-test/src/commonTest/kotlin/androidx/sqlite/driver/test/BaseBundledConformanceTest.kt b/sqlite/integration-tests/driver-conformance-test/src/commonTest/kotlin/androidx/sqlite/driver/test/BaseBundledConformanceTest.kt
index e0656d7..8941c3c 100644
--- a/sqlite/integration-tests/driver-conformance-test/src/commonTest/kotlin/androidx/sqlite/driver/test/BaseBundledConformanceTest.kt
+++ b/sqlite/integration-tests/driver-conformance-test/src/commonTest/kotlin/androidx/sqlite/driver/test/BaseBundledConformanceTest.kt
@@ -17,11 +17,25 @@
package androidx.sqlite.driver.test
import androidx.kruth.assertThat
+import androidx.sqlite.driver.bundled.BundledSQLiteDriver
+import androidx.sqlite.driver.bundled.SQLITE_OPEN_CREATE
+import androidx.sqlite.driver.bundled.SQLITE_OPEN_FULLMUTEX
+import androidx.sqlite.driver.bundled.SQLITE_OPEN_READWRITE
+import androidx.sqlite.execSQL
import androidx.sqlite.use
import kotlin.test.Test
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.IO
+import kotlinx.coroutines.coroutineScope
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.test.runTest
abstract class BaseBundledConformanceTest : BaseConformanceTest() {
+ abstract fun getDatabaseFileName(): String
+
+ abstract override fun getDriver(): BundledSQLiteDriver
+
@Test
fun readSQLiteVersion() {
val connection = getDriver().open(":memory:")
@@ -38,6 +52,37 @@
}
}
+ @Test
+ fun openWithFullMutexFlag() = runTest {
+ val connection =
+ getDriver()
+ .open(
+ fileName = getDatabaseFileName(),
+ flags = SQLITE_OPEN_READWRITE or SQLITE_OPEN_CREATE or SQLITE_OPEN_FULLMUTEX
+ )
+ connection.execSQL("CREATE TABLE Test (col)")
+ // Concurrently use the connection, due to being opened with the full mutex flag, it should
+ // be safe.
+ coroutineScope {
+ repeat(20) { i ->
+ launch(Dispatchers.IO) {
+ connection.prepare("INSERT INTO Test (col) VALUES (?)").use {
+ it.bindInt(1, i)
+ it.step()
+ }
+ }
+ }
+ }
+ connection.close()
+ }
+
+ @Test
+ fun threadSafeMode() {
+ // Validate bundled SQLite is compiled with SQLITE_THREADSAFE = 2
+ val driver = BundledSQLiteDriver()
+ assertThat(driver.threadingMode).isEqualTo(2)
+ }
+
companion object {
const val EXPECTED_SQLITE_VERSION = "3.46.0"
}
diff --git a/sqlite/integration-tests/driver-conformance-test/src/jvmTest/kotlin/androidx/sqlite/driver/test/BundledSQLiteDriverTest.kt b/sqlite/integration-tests/driver-conformance-test/src/jvmTest/kotlin/androidx/sqlite/driver/test/BundledSQLiteDriverTest.kt
index 1772073..d134a65 100644
--- a/sqlite/integration-tests/driver-conformance-test/src/jvmTest/kotlin/androidx/sqlite/driver/test/BundledSQLiteDriverTest.kt
+++ b/sqlite/integration-tests/driver-conformance-test/src/jvmTest/kotlin/androidx/sqlite/driver/test/BundledSQLiteDriverTest.kt
@@ -16,14 +16,19 @@
package androidx.sqlite.driver.test
-import androidx.sqlite.SQLiteDriver
import androidx.sqlite.driver.bundled.BundledSQLiteDriver
+import kotlin.io.path.createTempFile
+import kotlin.io.path.pathString
class BundledSQLiteDriverTest : BaseBundledConformanceTest() {
override val driverType = TestDriverType.BUNDLED
- override fun getDriver(): SQLiteDriver {
+ override fun getDatabaseFileName(): String {
+ return createTempFile("test.db").also { it.toFile().deleteOnExit() }.pathString
+ }
+
+ override fun getDriver(): BundledSQLiteDriver {
return BundledSQLiteDriver()
}
}
diff --git a/sqlite/integration-tests/driver-conformance-test/src/nativeTest/kotlin/androidx/sqlite/driver/test/BundledSQLiteDriverTest.kt b/sqlite/integration-tests/driver-conformance-test/src/nativeTest/kotlin/androidx/sqlite/driver/test/BundledSQLiteDriverTest.kt
index 1772073..e34f6dc 100644
--- a/sqlite/integration-tests/driver-conformance-test/src/nativeTest/kotlin/androidx/sqlite/driver/test/BundledSQLiteDriverTest.kt
+++ b/sqlite/integration-tests/driver-conformance-test/src/nativeTest/kotlin/androidx/sqlite/driver/test/BundledSQLiteDriverTest.kt
@@ -16,14 +16,37 @@
package androidx.sqlite.driver.test
-import androidx.sqlite.SQLiteDriver
import androidx.sqlite.driver.bundled.BundledSQLiteDriver
+import kotlin.random.Random
+import kotlin.test.AfterTest
+import kotlin.test.BeforeTest
+import platform.posix.remove
class BundledSQLiteDriverTest : BaseBundledConformanceTest() {
+ private val filename = "/tmp/test-${Random.nextInt()}.db"
+
override val driverType = TestDriverType.BUNDLED
- override fun getDriver(): SQLiteDriver {
+ override fun getDatabaseFileName(): String = filename
+
+ override fun getDriver(): BundledSQLiteDriver {
return BundledSQLiteDriver()
}
+
+ @BeforeTest
+ fun before() {
+ deleteDatabaseFile()
+ }
+
+ @AfterTest
+ fun after() {
+ deleteDatabaseFile()
+ }
+
+ private fun deleteDatabaseFile() {
+ remove(filename)
+ remove("$filename-wal")
+ remove("$filename-shm")
+ }
}
diff --git a/sqlite/sqlite-bundled/api/api_lint.ignore b/sqlite/sqlite-bundled/api/api_lint.ignore
index 2f12705..499ebfc 100644
--- a/sqlite/sqlite-bundled/api/api_lint.ignore
+++ b/sqlite/sqlite-bundled/api/api_lint.ignore
@@ -1,3 +1,5 @@
// Baseline format: 1.0
AcronymName: androidx.sqlite.driver.bundled.BundledSQLiteDriver:
Acronyms should not be capitalized in class names: was `BundledSQLiteDriver`, should this be `BundledSqLiteDriver`?
+AcronymName: androidx.sqlite.driver.bundled.BundledSQLiteKt:
+ Acronyms should not be capitalized in class names: was `BundledSQLiteKt`, should this be `BundledSqLiteKt`?
diff --git a/sqlite/sqlite-bundled/api/current.txt b/sqlite/sqlite-bundled/api/current.txt
index a0f2650..e7dfc96 100644
--- a/sqlite/sqlite-bundled/api/current.txt
+++ b/sqlite/sqlite-bundled/api/current.txt
@@ -4,6 +4,18 @@
public final class BundledSQLiteDriver implements androidx.sqlite.SQLiteDriver {
ctor public BundledSQLiteDriver();
method public androidx.sqlite.SQLiteConnection open(String fileName);
+ method public androidx.sqlite.SQLiteConnection open(String fileName, int flags);
+ }
+
+ public final class BundledSQLiteKt {
+ field public static final int SQLITE_OPEN_CREATE = 4; // 0x4
+ field public static final int SQLITE_OPEN_FULLMUTEX = 65536; // 0x10000
+ field public static final int SQLITE_OPEN_MEMORY = 128; // 0x80
+ field public static final int SQLITE_OPEN_NOFOLLOW = 16777216; // 0x1000000
+ field public static final int SQLITE_OPEN_NOMUTEX = 32768; // 0x8000
+ field public static final int SQLITE_OPEN_READONLY = 1; // 0x1
+ field public static final int SQLITE_OPEN_READWRITE = 2; // 0x2
+ field public static final int SQLITE_OPEN_URI = 64; // 0x40
}
}
diff --git a/sqlite/sqlite-bundled/api/restricted_current.txt b/sqlite/sqlite-bundled/api/restricted_current.txt
index a0f2650..da05ac9 100644
--- a/sqlite/sqlite-bundled/api/restricted_current.txt
+++ b/sqlite/sqlite-bundled/api/restricted_current.txt
@@ -3,7 +3,21 @@
public final class BundledSQLiteDriver implements androidx.sqlite.SQLiteDriver {
ctor public BundledSQLiteDriver();
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public int getThreadingMode();
method public androidx.sqlite.SQLiteConnection open(String fileName);
+ method public androidx.sqlite.SQLiteConnection open(String fileName, int flags);
+ property @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public final int threadingMode;
+ }
+
+ public final class BundledSQLiteKt {
+ field public static final int SQLITE_OPEN_CREATE = 4; // 0x4
+ field public static final int SQLITE_OPEN_FULLMUTEX = 65536; // 0x10000
+ field public static final int SQLITE_OPEN_MEMORY = 128; // 0x80
+ field public static final int SQLITE_OPEN_NOFOLLOW = 16777216; // 0x1000000
+ field public static final int SQLITE_OPEN_NOMUTEX = 32768; // 0x8000
+ field public static final int SQLITE_OPEN_READONLY = 1; // 0x1
+ field public static final int SQLITE_OPEN_READWRITE = 2; // 0x2
+ field public static final int SQLITE_OPEN_URI = 64; // 0x40
}
}
diff --git a/sqlite/sqlite-bundled/build.gradle b/sqlite/sqlite-bundled/build.gradle
index 46c940d..cbf5231 100644
--- a/sqlite/sqlite-bundled/build.gradle
+++ b/sqlite/sqlite-bundled/build.gradle
@@ -155,7 +155,7 @@
)
// add our JNI sources, i.e. the SQLite bindings
nativeCompilation.sources.from(
- fileTree("src/androidJvmCommonMain/jni").matching { include "**/*.cpp" }
+ fileTree("src/jvmAndroidMain/jni").matching { include "**/*.cpp" }
)
// statically include the output of SQLite compilation
nativeCompilation.include(sqliteCompilation)
@@ -198,7 +198,7 @@
// commonMain
// ┌───────────────────────────────────────────┐
// ▼ ▼
- // androidJvmCommonMain nativeMain
+ // jvmAndroidMain nativeMain
// ┌────────────────┐ ┌──────────┬────────────┐
// │ │ │ │ │
// ▼ ▼ ▼ ▼ ▼
@@ -209,15 +209,14 @@
api(project(":sqlite:sqlite"))
}
}
- androidJvmCommonMain {
- // common code between android and jvm
+ jvmAndroidMain {
dependsOn(commonMain)
}
jvmMain {
- dependsOn(androidJvmCommonMain)
+ dependsOn(jvmAndroidMain)
}
androidMain {
- dependsOn(androidJvmCommonMain)
+ dependsOn(jvmAndroidMain)
}
nativeMain {
dependsOn(commonMain)
diff --git a/sqlite/sqlite-bundled/src/androidJvmCommonMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteDriver.androidJvmCommon.kt b/sqlite/sqlite-bundled/src/androidJvmCommonMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteDriver.androidJvmCommon.kt
deleted file mode 100644
index 792d47c..0000000
--- a/sqlite/sqlite-bundled/src/androidJvmCommonMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteDriver.androidJvmCommon.kt
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-@file:JvmName("BundledSQLiteDriverKt")
-
-package androidx.sqlite.driver.bundled
-
-import androidx.sqlite.SQLiteConnection
-import androidx.sqlite.SQLiteDriver
-
-/**
- * A [SQLiteDriver] that uses a bundled version of SQLite included as a native component of the
- * library.
- */
-// TODO(b/313895287): Explore usability of @FastNative and @CriticalNative for the external
-// functions.
-actual class BundledSQLiteDriver : SQLiteDriver {
- override fun open(fileName: String): SQLiteConnection {
- val address = nativeOpen(fileName)
- return BundledSQLiteConnection(address)
- }
-
- private companion object {
- init {
- NativeLibraryLoader.loadLibrary("sqliteJni")
- }
- }
-}
-
-private external fun nativeOpen(name: String): Long
diff --git a/sqlite/sqlite-bundled/src/commonMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLite.kt b/sqlite/sqlite-bundled/src/commonMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLite.kt
new file mode 100644
index 0000000..7f6e4ea
--- /dev/null
+++ b/sqlite/sqlite-bundled/src/commonMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLite.kt
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.sqlite.driver.bundled
+
+import androidx.annotation.IntDef
+import androidx.annotation.RestrictTo
+
+const val SQLITE_OPEN_READONLY = 0x00000001
+const val SQLITE_OPEN_READWRITE = 0x00000002
+const val SQLITE_OPEN_CREATE = 0x00000004
+const val SQLITE_OPEN_URI = 0x00000040
+const val SQLITE_OPEN_MEMORY = 0x00000080
+const val SQLITE_OPEN_NOMUTEX = 0x00008000
+const val SQLITE_OPEN_FULLMUTEX = 0x00010000
+const val SQLITE_OPEN_NOFOLLOW = 0x01000000
+
+/** The flags constant that can be used with [BundledSQLiteDriver.open]. */
+@IntDef(
+ flag = true,
+ value =
+ [
+ SQLITE_OPEN_READONLY,
+ SQLITE_OPEN_READWRITE,
+ SQLITE_OPEN_CREATE,
+ SQLITE_OPEN_URI,
+ SQLITE_OPEN_MEMORY,
+ SQLITE_OPEN_NOMUTEX,
+ SQLITE_OPEN_FULLMUTEX,
+ SQLITE_OPEN_NOFOLLOW
+ ]
+)
+@Retention(AnnotationRetention.SOURCE)
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+expect annotation class OpenFlag()
diff --git a/sqlite/sqlite-bundled/src/commonMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteDriver.kt b/sqlite/sqlite-bundled/src/commonMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteDriver.kt
index 86e016cf..b55c476 100644
--- a/sqlite/sqlite-bundled/src/commonMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteDriver.kt
+++ b/sqlite/sqlite-bundled/src/commonMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteDriver.kt
@@ -16,10 +16,31 @@
package androidx.sqlite.driver.bundled
+import androidx.annotation.RestrictTo
+import androidx.sqlite.SQLiteConnection
import androidx.sqlite.SQLiteDriver
/**
* A [SQLiteDriver] that uses a bundled version of SQLite included as a native component of this
* library.
*/
-expect class BundledSQLiteDriver() : SQLiteDriver
+expect class BundledSQLiteDriver() : SQLiteDriver {
+
+ /**
+ * The thread safe mode SQLite was compiled with.
+ *
+ * See also [SQLite In Multi-Threaded Applications](https://www.sqlite.org/threadsafe.html)
+ */
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX) val threadingMode: Int
+
+ /**
+ * Opens a new database connection.
+ *
+ * See also [Opening A New Database Connection](https://www.sqlite.org/c3ref/open.html)
+ *
+ * @param fileName Name of the database file.
+ * @param flags Connection open flags.
+ * @return the database connection.
+ */
+ fun open(fileName: String, @OpenFlag flags: Int): SQLiteConnection
+}
diff --git a/sqlite/sqlite-bundled/src/androidJvmCommonMain/jni/README.md b/sqlite/sqlite-bundled/src/jvmAndroidMain/jni/README.md
similarity index 100%
rename from sqlite/sqlite-bundled/src/androidJvmCommonMain/jni/README.md
rename to sqlite/sqlite-bundled/src/jvmAndroidMain/jni/README.md
diff --git a/sqlite/sqlite-bundled/src/androidJvmCommonMain/jni/sqlite_bindings.cpp b/sqlite/sqlite-bundled/src/jvmAndroidMain/jni/sqlite_bindings.cpp
similarity index 97%
rename from sqlite/sqlite-bundled/src/androidJvmCommonMain/jni/sqlite_bindings.cpp
rename to sqlite/sqlite-bundled/src/jvmAndroidMain/jni/sqlite_bindings.cpp
index da884f2..ffc8b89 100644
--- a/sqlite/sqlite-bundled/src/androidJvmCommonMain/jni/sqlite_bindings.cpp
+++ b/sqlite/sqlite-bundled/src/jvmAndroidMain/jni/sqlite_bindings.cpp
@@ -41,14 +41,21 @@
return false;
}
+extern "C" JNIEXPORT jint JNICALL
+Java_androidx_sqlite_driver_bundled_BundledSQLiteDriverKt_nativeThreadSafeMode(
+ JNIEnv* env,
+ jclass clazz) {
+ return sqlite3_threadsafe();
+}
+
extern "C" JNIEXPORT jlong JNICALL
Java_androidx_sqlite_driver_bundled_BundledSQLiteDriverKt_nativeOpen(
JNIEnv* env,
jclass clazz,
- jstring name) {
+ jstring name,
+ int openFlags) {
const char *path = env->GetStringUTFChars(name, nullptr);
sqlite3 *db;
- int openFlags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
int rc = sqlite3_open_v2(path, &db, openFlags, nullptr);
env->ReleaseStringUTFChars(name, path);
if (rc != SQLITE_OK) {
diff --git a/sqlite/sqlite-bundled/src/jvmAndroidMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLite.jvmAndroid.kt b/sqlite/sqlite-bundled/src/jvmAndroidMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLite.jvmAndroid.kt
new file mode 100644
index 0000000..1717770
--- /dev/null
+++ b/sqlite/sqlite-bundled/src/jvmAndroidMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLite.jvmAndroid.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.sqlite.driver.bundled
+
+import androidx.annotation.IntDef
+import androidx.annotation.RestrictTo
+
+/** The flags constant that can be used with [BundledSQLiteDriver.open]. */
+@IntDef(
+ flag = true,
+ value =
+ [
+ SQLITE_OPEN_READONLY,
+ SQLITE_OPEN_READWRITE,
+ SQLITE_OPEN_CREATE,
+ SQLITE_OPEN_URI,
+ SQLITE_OPEN_MEMORY,
+ SQLITE_OPEN_NOMUTEX,
+ SQLITE_OPEN_FULLMUTEX,
+ SQLITE_OPEN_NOFOLLOW
+ ]
+)
+@Retention(AnnotationRetention.SOURCE)
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+actual annotation class OpenFlag
+
+internal object ResultCode {
+ const val SQLITE_MISUSE = 21
+}
diff --git a/sqlite/sqlite-bundled/src/androidJvmCommonMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteConnection.androidJvmCommon.kt b/sqlite/sqlite-bundled/src/jvmAndroidMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteConnection.jvmAndroid.kt
similarity index 100%
rename from sqlite/sqlite-bundled/src/androidJvmCommonMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteConnection.androidJvmCommon.kt
rename to sqlite/sqlite-bundled/src/jvmAndroidMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteConnection.jvmAndroid.kt
diff --git a/sqlite/sqlite-bundled/src/jvmAndroidMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteDriver.jvmAndroid.kt b/sqlite/sqlite-bundled/src/jvmAndroidMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteDriver.jvmAndroid.kt
new file mode 100644
index 0000000..de1e6eb
--- /dev/null
+++ b/sqlite/sqlite-bundled/src/jvmAndroidMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteDriver.jvmAndroid.kt
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+@file:JvmName("BundledSQLiteDriverKt")
+
+package androidx.sqlite.driver.bundled
+
+import androidx.annotation.RestrictTo
+import androidx.sqlite.SQLiteConnection
+import androidx.sqlite.SQLiteDriver
+
+/**
+ * A [SQLiteDriver] that uses a bundled version of SQLite included as a native component of the
+ * library.
+ */
+// TODO(b/313895287): Explore usability of @FastNative and @CriticalNative for the external
+// functions.
+actual class BundledSQLiteDriver : SQLiteDriver {
+
+ /**
+ * The thread safe mode SQLite was compiled with.
+ *
+ * See also [SQLite In Multi-Threaded Applications](https://www.sqlite.org/threadsafe.html)
+ */
+ @get:RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+ actual val threadingMode: Int
+ get() = nativeThreadSafeMode()
+
+ override fun open(fileName: String): SQLiteConnection {
+ return open(fileName, SQLITE_OPEN_READWRITE or SQLITE_OPEN_CREATE)
+ }
+
+ /**
+ * Opens a new database connection.
+ *
+ * See also [Opening A New Database Connection](https://www.sqlite.org/c3ref/open.html)
+ *
+ * @param fileName Name of the database file.
+ * @param flags Connection open flags.
+ * @return the database connection.
+ */
+ actual fun open(fileName: String, @OpenFlag flags: Int): SQLiteConnection {
+ val address = nativeOpen(fileName, flags)
+ return BundledSQLiteConnection(address)
+ }
+
+ private companion object {
+ init {
+ NativeLibraryLoader.loadLibrary("sqliteJni")
+ }
+ }
+}
+
+private external fun nativeThreadSafeMode(): Int
+
+private external fun nativeOpen(name: String, openFlags: Int): Long
diff --git a/sqlite/sqlite-bundled/src/androidJvmCommonMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteStatement.androidJvmCommon.kt b/sqlite/sqlite-bundled/src/jvmAndroidMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteStatement.jvmAndroid.kt
similarity index 100%
rename from sqlite/sqlite-bundled/src/androidJvmCommonMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteStatement.androidJvmCommon.kt
rename to sqlite/sqlite-bundled/src/jvmAndroidMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteStatement.jvmAndroid.kt
diff --git a/sqlite/sqlite-bundled/src/androidJvmCommonMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLite.androidJvmCommon.kt b/sqlite/sqlite-bundled/src/nativeMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLite.nativeCommon.kt
similarity index 90%
rename from sqlite/sqlite-bundled/src/androidJvmCommonMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLite.androidJvmCommon.kt
rename to sqlite/sqlite-bundled/src/nativeMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLite.nativeCommon.kt
index 7708fba..d3d1d5d 100644
--- a/sqlite/sqlite-bundled/src/androidJvmCommonMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLite.androidJvmCommon.kt
+++ b/sqlite/sqlite-bundled/src/nativeMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLite.nativeCommon.kt
@@ -16,6 +16,4 @@
package androidx.sqlite.driver.bundled
-internal object ResultCode {
- const val SQLITE_MISUSE = 21
-}
+actual typealias OpenFlag = androidx.sqlite.driver.OpenFlag
diff --git a/sqlite/sqlite-bundled/src/nativeMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteConnection.nativeCommon.kt b/sqlite/sqlite-bundled/src/nativeMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteConnection.native.kt
similarity index 100%
rename from sqlite/sqlite-bundled/src/nativeMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteConnection.nativeCommon.kt
rename to sqlite/sqlite-bundled/src/nativeMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteConnection.native.kt
diff --git a/sqlite/sqlite-bundled/src/nativeMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteDriver.nativeCommon.kt b/sqlite/sqlite-bundled/src/nativeMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteDriver.native.kt
similarity index 100%
rename from sqlite/sqlite-bundled/src/nativeMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteDriver.nativeCommon.kt
rename to sqlite/sqlite-bundled/src/nativeMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteDriver.native.kt
diff --git a/sqlite/sqlite-bundled/src/nativeMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteStatement.nativeCommon.kt b/sqlite/sqlite-bundled/src/nativeMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteStatement.native.kt
similarity index 100%
rename from sqlite/sqlite-bundled/src/nativeMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteStatement.nativeCommon.kt
rename to sqlite/sqlite-bundled/src/nativeMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteStatement.native.kt
diff --git a/sqlite/sqlite-bundled/src/nativeMain/kotlin/androidx/sqlite/driver/bundled/NativeLibraryLoader.nativeCommon.kt b/sqlite/sqlite-bundled/src/nativeMain/kotlin/androidx/sqlite/driver/bundled/NativeLibraryLoader.native.kt
similarity index 100%
rename from sqlite/sqlite-bundled/src/nativeMain/kotlin/androidx/sqlite/driver/bundled/NativeLibraryLoader.nativeCommon.kt
rename to sqlite/sqlite-bundled/src/nativeMain/kotlin/androidx/sqlite/driver/bundled/NativeLibraryLoader.native.kt
diff --git a/sqlite/sqlite-framework/src/nativeMain/kotlin/androidx/sqlite/driver/NativeSQLite.kt b/sqlite/sqlite-framework/src/nativeMain/kotlin/androidx/sqlite/driver/NativeSQLite.kt
index d2592a2..d5e7d1d 100644
--- a/sqlite/sqlite-framework/src/nativeMain/kotlin/androidx/sqlite/driver/NativeSQLite.kt
+++ b/sqlite/sqlite-framework/src/nativeMain/kotlin/androidx/sqlite/driver/NativeSQLite.kt
@@ -16,13 +16,42 @@
package androidx.sqlite.driver
+import androidx.annotation.IntDef
+import androidx.annotation.RestrictTo
import cnames.structs.sqlite3
import kotlinx.cinterop.CPointer
import kotlinx.cinterop.UShortVar
import kotlinx.cinterop.reinterpret
import kotlinx.cinterop.toKStringFromUtf16
+import sqlite3.SQLITE_OPEN_CREATE
+import sqlite3.SQLITE_OPEN_FULLMUTEX
+import sqlite3.SQLITE_OPEN_MEMORY
+import sqlite3.SQLITE_OPEN_NOFOLLOW
+import sqlite3.SQLITE_OPEN_NOMUTEX
+import sqlite3.SQLITE_OPEN_READONLY
+import sqlite3.SQLITE_OPEN_READWRITE
+import sqlite3.SQLITE_OPEN_URI
import sqlite3.sqlite3_errmsg16
+/** The flags constant that can be used with [NativeSQLiteDriver.open]. */
+@IntDef(
+ flag = true,
+ value =
+ [
+ SQLITE_OPEN_READONLY,
+ SQLITE_OPEN_READWRITE,
+ SQLITE_OPEN_CREATE,
+ SQLITE_OPEN_URI,
+ SQLITE_OPEN_MEMORY,
+ SQLITE_OPEN_NOMUTEX,
+ SQLITE_OPEN_FULLMUTEX,
+ SQLITE_OPEN_NOFOLLOW
+ ],
+)
+@Retention(AnnotationRetention.SOURCE)
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+annotation class OpenFlag
+
internal fun CPointer<sqlite3>.getErrorMsg(): String? {
return sqlite3_errmsg16(this)?.reinterpret<UShortVar>()?.toKStringFromUtf16()
}
diff --git a/sqlite/sqlite-framework/src/nativeMain/kotlin/androidx/sqlite/driver/NativeSQLiteDriver.kt b/sqlite/sqlite-framework/src/nativeMain/kotlin/androidx/sqlite/driver/NativeSQLiteDriver.kt
index f482be4..c3de38c 100644
--- a/sqlite/sqlite-framework/src/nativeMain/kotlin/androidx/sqlite/driver/NativeSQLiteDriver.kt
+++ b/sqlite/sqlite-framework/src/nativeMain/kotlin/androidx/sqlite/driver/NativeSQLiteDriver.kt
@@ -16,6 +16,7 @@
package androidx.sqlite.driver
+import androidx.annotation.RestrictTo
import androidx.sqlite.SQLiteConnection
import androidx.sqlite.SQLiteDriver
import androidx.sqlite.throwSQLiteException
@@ -28,6 +29,7 @@
import sqlite3.SQLITE_OPEN_CREATE
import sqlite3.SQLITE_OPEN_READWRITE
import sqlite3.sqlite3_open_v2
+import sqlite3.sqlite3_threadsafe
/**
* A [SQLiteDriver] that uses a version of SQLite included with the host operating system.
@@ -35,18 +37,35 @@
* Usage of this driver expects that `libsqlite` can be found in the shared library path.
*/
// TODO:
-// (b/307917398) more open flags
// (b/304295573) busy handler registering
class NativeSQLiteDriver : SQLiteDriver {
- override fun open(fileName: String): SQLiteConnection = memScoped {
+
+ /**
+ * The thread safe mode SQLite was compiled with.
+ *
+ * See also [SQLite In Multi-Threaded Applications](https://www.sqlite.org/threadsafe.html)
+ */
+ @get:RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+ val threadingMode: Int
+ get() = sqlite3_threadsafe()
+
+ override fun open(fileName: String): SQLiteConnection {
+ return open(fileName, SQLITE_OPEN_READWRITE or SQLITE_OPEN_CREATE)
+ }
+
+ /**
+ * Opens a new database connection.
+ *
+ * See also [Opening A New Database Connection](https://www.sqlite.org/c3ref/open.html)
+ *
+ * @param fileName Name of the database file.
+ * @param flags Connection open flags.
+ * @return the database connection.
+ */
+ fun open(fileName: String, @OpenFlag flags: Int): SQLiteConnection = memScoped {
val dbPointer = allocPointerTo<sqlite3>()
val resultCode =
- sqlite3_open_v2(
- filename = fileName,
- ppDb = dbPointer.ptr,
- flags = SQLITE_OPEN_READWRITE or SQLITE_OPEN_CREATE,
- zVfs = null
- )
+ sqlite3_open_v2(filename = fileName, ppDb = dbPointer.ptr, flags = flags, zVfs = null)
if (resultCode != SQLITE_OK) {
throwSQLiteException(resultCode, null)
}