Skip to content
This repository was archived by the owner on Oct 24, 2025. It is now read-only.

Commit ea9049f

Browse files
committed
file rework
1 parent f015f06 commit ea9049f

File tree

12 files changed

+131
-111
lines changed

12 files changed

+131
-111
lines changed

samples/android/src/main/java/com/asyncstorage/sqlite/android/example/MainActivity.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ class MainActivity : AppCompatActivity() {
1313
override fun onCreate(savedInstanceState: Bundle?) {
1414
super.onCreate(savedInstanceState)
1515
db = SqliteStorageFactory(this).create("my_db")
16+
db.files.size()
1617
setContent {
1718
MainScreen(db)
1819
}

sqlite-storage/src/androidMain/kotlin/org/asyncstorage/sqlitestorage/AndroidDatabaseFile.kt

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,25 @@ package org.asyncstorage.sqlitestorage
22

33
import java.io.File
44

5-
internal class AndroidDatabaseFile(private val dbFile: File) : DatabaseFile {
6-
override fun path(): String = dbFile.absolutePath
5+
internal class AndroidDatabaseFile(private val dbFile: File) : DatabaseFiles {
6+
override fun path(type: DatabaseFileType): String = when (type) {
7+
DatabaseFileType.Main -> dbFile.absolutePath
8+
DatabaseFileType.Wal -> "${dbFile.absolutePath}-wal"
9+
DatabaseFileType.Index -> "${dbFile.absolutePath}-shm"
10+
}
711

812
override fun dirPath(): String = dbFile.parentFile!!.absolutePath
913

1014
override fun delete(): Boolean {
11-
val dbName = dbFile.name
1215
return try {
13-
val parent = dbFile.parentFile!!
1416
val deleted = mutableListOf<Boolean>()
1517

16-
listOf(dbName, "$dbName-wal", "$dbName-shm").forEach { dbFile ->
17-
deleted += File(parent, dbFile).delete()
18+
listOf(
19+
path(DatabaseFileType.Main),
20+
path(DatabaseFileType.Wal),
21+
path(DatabaseFileType.Index)
22+
).forEach { path ->
23+
deleted += File(path).delete()
1824
}
1925
true
2026
} catch (e: SecurityException) {
@@ -23,11 +29,12 @@ internal class AndroidDatabaseFile(private val dbFile: File) : DatabaseFile {
2329
}
2430
}
2531

26-
override fun size(): Long {
27-
var size = -1L
28-
if (dbFile.exists()) {
29-
size = (dbFile.length() / 1024L)
32+
override fun size(type: DatabaseFileType): Long? {
33+
val file = File(path(type))
34+
return if (file.exists()) {
35+
(dbFile.length() / 1024L)
36+
} else {
37+
null
3038
}
31-
return size
3239
}
3340
}

sqlite-storage/src/androidUnitTest/kotlin/org/asyncstorage/sqlitestorage/DatabaseFileTest.android.kt

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import org.asyncstorage.sqlitestorage.utils.JunitRunner
66
import org.junit.Test
77
import org.junit.runner.RunWith
88

9-
internal actual fun createDatabaseFile(name: String): DatabaseFile {
9+
internal actual fun createDatabaseFile(name: String): DatabaseFiles {
1010
val ctx: Context = ApplicationProvider.getApplicationContext()
1111
return AndroidDatabaseFile(ctx.getDatabasePath(name))
1212
}
@@ -18,9 +18,23 @@ class AndroidDatabaseFileTest {
1818
val dbName = "testing_my_db.db"
1919
val file = createDatabaseFile(dbName)
2020
val dbPath = file.path()
21-
val expected = "databases/$dbName"
22-
assert(dbPath.endsWith("databases/$dbName")) {
23-
"db path not matching, expected: $expected, received: $dbPath"
21+
22+
with(file.path()) {
23+
assert(this.endsWith(dbName)) {
24+
"db path not matching, expected: $dbName, received: $this"
25+
}
26+
}
27+
28+
with(file.path(DatabaseFileType.Index)) {
29+
assert(this.endsWith("${dbName}-shm")) {
30+
"index path not matching, expected: ${dbName}-shm, received: $this"
31+
}
32+
}
33+
34+
with(file.path(DatabaseFileType.Wal)) {
35+
assert(this.endsWith("${dbName}-wal")) {
36+
"wal path not matching, expected: ${dbName}-wal, received: $this"
37+
}
2438
}
2539
}
2640
}

sqlite-storage/src/commonMain/kotlin/org/asyncstorage/sqlitestorage/DatabaseFile.kt

Lines changed: 0 additions & 26 deletions
This file was deleted.
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package org.asyncstorage.sqlitestorage
2+
3+
4+
// todo: bring implementation to common, rather per platform
5+
// requires per platform file access
6+
interface DatabaseFiles {
7+
/**
8+
* Returns an absolute path to the selected database file
9+
*/
10+
fun path(type: DatabaseFileType = DatabaseFileType.Main): String
11+
12+
/**
13+
* An absolute path to a directory containing database files
14+
*/
15+
fun dirPath(): String
16+
17+
/**
18+
* Removes the database file and all related WAL files (-wal and -shm).
19+
*/
20+
fun delete(): Boolean
21+
22+
/**
23+
* Returns a size of a selected database file
24+
* If the file does not exists or cannot be read for some reason, returns null
25+
*/
26+
fun size(type: DatabaseFileType = DatabaseFileType.Main): Long?
27+
}
28+
29+
/**
30+
* https://www.sqlite.org/walformat.html
31+
*/
32+
enum class DatabaseFileType {
33+
Main,
34+
Wal,
35+
Index
36+
}

sqlite-storage/src/commonMain/kotlin/org/asyncstorage/sqlitestorage/DefaultSqliteStorage.kt

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,13 @@ import kotlinx.coroutines.withContext
1010
import org.asyncstorage.sqlitestorage.db.AsyncStorageDB
1111
import org.asyncstorage.sqlitestorage.dispatchers.DispatcherIO
1212
import org.asyncstorage.sqlitestorage.extensions.executePragmaOptimize
13-
import org.asyncstorage.sqlitestorage.extensions.executePragmaWalCheckpoint
1413
import org.asyncstorage.sqlitestorage.models.Entry
1514
import org.asyncstorage.sqlitestorage.models.Key
1615
import org.asyncstorage.sqlitestorage.utils.mergePossibleJsonValues
1716

1817
internal class DefaultSqliteStorage(
1918
private val driver: SqlDriver,
20-
private val dbFile: DatabaseFile,
19+
override val files: DatabaseFiles,
2120
private val dispatcher: CoroutineDispatcher = DispatcherIO,
2221
) : SqliteStorage {
2322
private val queries = AsyncStorageDB(driver).async_storage_entriesQueries
@@ -123,18 +122,4 @@ internal class DefaultSqliteStorage(
123122
driver.executePragmaOptimize()
124123
driver.close()
125124
}
126-
127-
override fun getDbPath() = dbFile.path()
128-
129-
override suspend fun getDbSize(): Long =
130-
withContext(dispatcher) {
131-
driver.executePragmaWalCheckpoint()
132-
dbFile.size()
133-
}
134-
135-
override suspend fun dropDatabase() =
136-
withContext(dispatcher) {
137-
driver.close()
138-
dbFile.delete()
139-
}
140125
}

sqlite-storage/src/commonMain/kotlin/org/asyncstorage/sqlitestorage/SqliteStorage.kt

Lines changed: 8 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@ import org.asyncstorage.sqlitestorage.models.Key
1010
* The connection is required for any database access action, otherwise an exception is thrown.
1111
*/
1212
interface SqliteStorage {
13+
/**
14+
* Access database files related to instance of this SqliteStorage directly
15+
* See [DatabaseFiles]
16+
*/
17+
val files: DatabaseFiles
18+
1319
/**
1420
* Reads a single entry, matching provided key.
1521
* If entry does not exist in database, Entry will contain `null` value.
@@ -110,38 +116,14 @@ interface SqliteStorage {
110116
*/
111117
@Throws(Throwable::class)
112118
suspend fun closeConnection()
113-
114-
/**
115-
* Returns an absolute path to database file on the device.
116-
*/
117-
fun getDbPath(): String
118-
119-
/**
120-
* Returns a size of database file on filesystem, in KB.
121-
* If file does not exist, or there's an exception while accessing it, returns -1.
122-
* Throws if DB connection is closed.
123-
*/
124-
@Throws(Throwable::class)
125-
suspend fun getDbSize(): Long
126-
127-
/**
128-
* Closes current connection to database and removes its file from filesystem.
129-
* After this action, this StorageAccess instance should no longer be used.
130-
* Returns boolean if file deletion was successful or not.
131-
* Throws if DB connection is closed.
132-
*
133-
* This action is not recoverable.
134-
*/
135-
@Throws(Throwable::class)
136-
suspend fun dropDatabase(): Boolean
137119
}
138120

139121
fun SqliteStorage(
140122
driver: SqlDriver,
141-
dbFile: DatabaseFile,
123+
dbFile: DatabaseFiles,
142124
): SqliteStorage {
143125
return DefaultSqliteStorage(
144126
driver = driver,
145-
dbFile = dbFile,
127+
files = dbFile,
146128
)
147129
}

sqlite-storage/src/commonTest/kotlin/org/asyncstorage/sqlitestorage/DatabaseFileTest.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import kotlin.test.Test
77
import kotlin.test.assertEquals
88
import kotlin.test.assertTrue
99

10-
internal expect fun createDatabaseFile(name: String = "Test"): DatabaseFile
10+
internal expect fun createDatabaseFile(name: String = "Test"): DatabaseFiles
1111

1212
@RunWith(JunitRunner::class)
1313
class DatabaseFileTest {
@@ -16,7 +16,7 @@ class DatabaseFileTest {
1616
val dbName = "testing_my_db.db"
1717
val file = createDatabaseFile(dbName)
1818
val dbPath = file.dirPath()
19-
assertTrue(file.dirPath().endsWith("databases/$dbName"), "db path not matching $dbPath")
19+
assertTrue(file.dirPath().endsWith("/databases"), "db path not matching $dbPath")
2020
}
2121

2222
@Test
@@ -38,6 +38,6 @@ class DatabaseFileTest {
3838
file.delete()
3939
assertTrue(!helper.exists(), "db file still exists")
4040
val size = file.size()
41-
assertEquals(-1L, size, "size should be -1, instead: $size")
41+
assertEquals(null, size, "size should be null, instead: $size")
4242
}
4343
}

sqlite-storage/src/commonTest/kotlin/org/asyncstorage/sqlitestorage/SqliteStorageTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class SqliteStorageTest {
2828
return realRunTest(context = testDispatcher, testBody = {
2929
val db = createDb()
3030
testBody(db)
31-
db.dropDatabase()
31+
db.clear()
3232
})
3333
}
3434

sqlite-storage/src/iosMain/kotlin/org/asyncstorage/sqlitestorage/IosDatabaseFile.kt

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import platform.Foundation.NSSearchPathForDirectoriesInDomains
1111
import platform.Foundation.NSUserDomainMask
1212
import platform.posix.remove
1313

14-
internal class IosDatabaseFile(private val dbName: String) : DatabaseFile {
14+
internal class IosDatabaseFile(private val dbName: String) : DatabaseFiles {
1515
/**
1616
* Main location to store database file is at
1717
* Application Support/App_Bundle_Id/${MainBundleName or SqliteStorage}/databases
@@ -29,32 +29,38 @@ internal class IosDatabaseFile(private val dbName: String) : DatabaseFile {
2929
"$docDirectory/$bundleId/databases"
3030
}
3131

32-
override fun path(): String = "$dbDir/$dbName"
32+
override fun path(type: DatabaseFileType): String =
33+
when (type) {
34+
DatabaseFileType.Main -> "$dbDir/$dbName"
35+
DatabaseFileType.Wal -> "$dbDir/$dbName-wal"
36+
DatabaseFileType.Index -> "$dbDir/$dbName-shm"
37+
}
3338

3439
override fun dirPath() = dbDir
3540

3641
override fun delete(): Boolean {
3742
val deleted = mutableListOf<Boolean>()
38-
val dbFile = path()
39-
listOf(dbFile, "$dbFile-wal", "$dbFile-shm").forEach { file ->
43+
listOf(
44+
path(DatabaseFileType.Main),
45+
path(DatabaseFileType.Wal),
46+
path(DatabaseFileType.Index)
47+
).forEach { file ->
4048
deleted += remove(file) == 0
4149
}
4250
return deleted.all { it }
4351
}
4452

45-
override fun size(): Long {
46-
val file = path()
47-
var size = -1L
48-
try {
53+
override fun size(type: DatabaseFileType): Long? {
54+
val file = path(type)
55+
return try {
4956
val attrs = NSFileManager.defaultManager.attributesOfItemAtPath(file, null)
5057
val fileSize = attrs?.get(NSFileSize) as Long?
51-
if (fileSize != null) {
52-
size = fileSize / 1024L
58+
fileSize?.let {
59+
it / 1024L
5360
}
5461
} catch (e: Exception) {
55-
// potentially means trying to get attributes file that does not exist
62+
return null
5663
}
57-
return size
5864
}
5965

6066
/**

0 commit comments

Comments
 (0)