forked from Nozbe/WatermelonDB
/
Database.kt
104 lines (87 loc) · 3.54 KB
/
Database.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
package com.nozbe.watermelondb
import android.content.Context
import android.database.Cursor
import net.sqlcipher.database.SQLiteDatabase
import java.io.File
class Database(private val name: String, private val password: String?, private val context: Context) {
private val db: SQLiteDatabase by lazy {
SQLiteDatabase.loadLibs(context)
SQLiteDatabase.openOrCreateDatabase(
// TODO: This SUCKS. Seems like Android doesn't like sqlite `?mode=memory&cache=shared` mode. To avoid random breakages, save the file to /tmp, but this is slow.
if (name == ":memory:" || name.contains("mode=memory")) {
context.cacheDir.delete()
File(context.cacheDir, name).path
} else
// On some systems there is some kind of lock on `/databases` folder ¯\_(ツ)_/¯
context.getDatabasePath("$name.db").path.replace("/databases", ""),
password,
null)
}
var userVersion: Int
get() = db.version
set(value) {
db.version = value
}
fun executeStatements(statements: SQL) =
transaction {
statements.split(";").forEach {
if (it.isNotBlank()) execute(it)
}
}
fun execute(query: SQL, args: QueryArgs = emptyArray()) =
db.execSQL(query, args)
fun delete(query: SQL, args: QueryArgs) = db.execSQL(query, args)
fun rawQuery(query: SQL, args: RawQueryArgs = emptyArray()): Cursor = db.rawQuery(query, args)
fun count(query: SQL, args: RawQueryArgs = emptyArray()): Int =
rawQuery(query, args).use {
it.moveToFirst()
return it.getInt(it.getColumnIndex("count"))
}
fun getFromLocalStorage(key: String): String? =
rawQuery(Queries.select_local_storage, arrayOf(key)).use {
it.moveToFirst()
return if (it.count > 0) {
it.getString(0)
} else {
null
}
}
fun insertToLocalStorage(key: String, value: String) =
execute(Queries.insert_local_storage, arrayOf(key, value))
fun deleteFromLocalStorage(key: String) =
execute(Queries.delete_local_storage, arrayOf(key))
// fun unsafeResetDatabase() = context.deleteDatabase("$name.db")
fun unsafeDestroyEverything() =
transaction {
getAllTables().forEach { execute(Queries.dropTable(it)) }
execute("pragma writable_schema=1")
execute("delete from sqlite_master where type in ('table', 'index', 'trigger')")
execute("pragma user_version=0")
execute("pragma writable_schema=0")
}
private fun getAllTables(): ArrayList<String> {
val allTables: ArrayList<String> = arrayListOf()
rawQuery(Queries.select_tables).use {
if (it.count > 0) {
it.moveToFirst()
val index = it.getColumnIndex("name")
if (index > -1) {
do {
allTables.add(it.getString(index))
} while (it.moveToNext())
}
}
}
return allTables
}
fun transaction(function: () -> Unit) {
db.beginTransaction()
try {
function()
db.setTransactionSuccessful()
} finally {
db.endTransaction()
}
}
fun close() = db.close()
}