diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f57c950..a6554b2b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## 1.0.0-BETA29 (unreleased) * Fix potential race condition between jobs in `connect()` and `disconnect()`. +* [JVM Windows] Fixed PowerSync Extension temporary file deletion error on process shutdown. * [iOS] Fixed issue where automatic driver migrations would fail with the error: ``` Sqlite operation failure database is locked attempted to run migration and failed. closing connection diff --git a/core/src/jvmMain/kotlin/com/powersync/DatabaseDriverFactory.jvm.kt b/core/src/jvmMain/kotlin/com/powersync/DatabaseDriverFactory.jvm.kt index acb115d6..39864b54 100644 --- a/core/src/jvmMain/kotlin/com/powersync/DatabaseDriverFactory.jvm.kt +++ b/core/src/jvmMain/kotlin/com/powersync/DatabaseDriverFactory.jvm.kt @@ -57,6 +57,6 @@ public actual class DatabaseDriverFactory { } public companion object { - private val powersyncExtension: String = extractLib("powersync").toString() + private val powersyncExtension: String = extractLib("powersync") } } diff --git a/core/src/jvmMain/kotlin/com/powersync/ExtractLib.kt b/core/src/jvmMain/kotlin/com/powersync/ExtractLib.kt index 76f8915a..9666b5ac 100644 --- a/core/src/jvmMain/kotlin/com/powersync/ExtractLib.kt +++ b/core/src/jvmMain/kotlin/com/powersync/ExtractLib.kt @@ -1,13 +1,10 @@ package com.powersync -import java.nio.file.Path -import kotlin.io.path.createTempFile -import kotlin.io.path.deleteIfExists -import kotlin.io.path.outputStream +import java.io.File private class R -internal fun extractLib(fileName: String): Path { +internal fun extractLib(fileName: String): String { val os = System.getProperty("os.name").lowercase() val (prefix, extension) = when { @@ -26,14 +23,12 @@ internal fun extractLib(fileName: String): Path { val path = "/$prefix${fileName}_$arch.$extension" - val tmpPath = createTempFile("$prefix$fileName", ".$extension") - Runtime.getRuntime().addShutdownHook(Thread { tmpPath.deleteIfExists() }) + val resourceURI = + (R::class.java.getResource(path) ?: error("Resource $path not found")) - (R::class.java.getResourceAsStream(path) ?: error("Resource $path not found")).use { input -> - tmpPath.outputStream().use { output -> - input.copyTo(output) - } - } - - return tmpPath + // Wrapping the above in a File handle resolves the URI to a path usable by SQLite. + // This is particularly relevant on Windows. + // On Windows [resourceURI.path] starts with a `/`, e.g. `/c:/...`. SQLite does not load this path correctly. + // The wrapping here transforms the path to `c:/...` which does load correctly. + return File(resourceURI.path).path.toString() }