2022-02-14 19:18:03 +00:00
|
|
|
package org.signal.spinner
|
|
|
|
|
2022-02-23 23:22:58 +00:00
|
|
|
import android.app.Application
|
2022-02-21 17:39:07 +00:00
|
|
|
import android.content.ContentValues
|
|
|
|
import android.database.sqlite.SQLiteQueryBuilder
|
2022-02-14 19:18:03 +00:00
|
|
|
import androidx.sqlite.db.SupportSQLiteDatabase
|
|
|
|
import org.signal.core.util.logging.Log
|
|
|
|
import java.io.IOException
|
|
|
|
|
|
|
|
/**
|
|
|
|
* A class to help initialize Spinner, our database debugging interface.
|
|
|
|
*/
|
|
|
|
object Spinner {
|
|
|
|
val TAG: String = Log.tag(Spinner::class.java)
|
|
|
|
|
2022-02-21 17:39:07 +00:00
|
|
|
private lateinit var server: SpinnerServer
|
|
|
|
|
2022-02-23 23:22:58 +00:00
|
|
|
fun init(application: Application, deviceInfo: DeviceInfo, databases: Map<String, DatabaseConfig>) {
|
2022-02-14 19:18:03 +00:00
|
|
|
try {
|
2022-02-23 23:22:58 +00:00
|
|
|
server = SpinnerServer(application, deviceInfo, databases)
|
2022-02-21 17:39:07 +00:00
|
|
|
server.start()
|
2022-02-14 19:18:03 +00:00
|
|
|
} catch (e: IOException) {
|
2022-02-21 17:39:07 +00:00
|
|
|
Log.w(TAG, "Spinner server hit IO exception!", e)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fun onSql(dbName: String, sql: String, args: Array<Any>?) {
|
|
|
|
server.onSql(dbName, replaceQueryArgs(sql, args))
|
|
|
|
}
|
|
|
|
|
|
|
|
fun onQuery(dbName: String, distinct: Boolean, table: String, projection: Array<String>?, selection: String?, args: Array<Any>?, groupBy: String?, having: String?, orderBy: String?, limit: String?) {
|
|
|
|
val queryString = SQLiteQueryBuilder.buildQueryString(distinct, table, projection, selection, groupBy, having, orderBy, limit)
|
|
|
|
server.onSql(dbName, replaceQueryArgs(queryString, args))
|
|
|
|
}
|
|
|
|
|
|
|
|
fun onDelete(dbName: String, table: String, selection: String?, args: Array<Any>?) {
|
|
|
|
var query = "DELETE FROM $table"
|
|
|
|
if (selection != null) {
|
|
|
|
query += " WHERE $selection"
|
|
|
|
query = replaceQueryArgs(query, args)
|
2022-02-14 19:18:03 +00:00
|
|
|
}
|
2022-02-21 17:39:07 +00:00
|
|
|
|
|
|
|
server.onSql(dbName, query)
|
|
|
|
}
|
|
|
|
|
|
|
|
fun onUpdate(dbName: String, table: String, values: ContentValues, selection: String?, args: Array<Any>?) {
|
|
|
|
val query = StringBuilder("UPDATE $table SET ")
|
|
|
|
|
|
|
|
for (key in values.keySet()) {
|
|
|
|
query.append("$key = ${values.get(key)}, ")
|
|
|
|
}
|
|
|
|
|
|
|
|
query.delete(query.length - 2, query.length)
|
|
|
|
|
|
|
|
if (selection != null) {
|
|
|
|
query.append(" WHERE ").append(selection)
|
|
|
|
}
|
|
|
|
|
|
|
|
var queryString = query.toString()
|
|
|
|
|
|
|
|
if (args != null) {
|
|
|
|
queryString = replaceQueryArgs(queryString, args)
|
|
|
|
}
|
|
|
|
|
|
|
|
server.onSql(dbName, queryString)
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun replaceQueryArgs(query: String, args: Array<Any>?): String {
|
|
|
|
if (args == null) {
|
|
|
|
return query
|
|
|
|
}
|
|
|
|
|
|
|
|
val builder = StringBuilder()
|
|
|
|
|
|
|
|
var i = 0
|
|
|
|
var argIndex = 0
|
|
|
|
while (i < query.length) {
|
|
|
|
if (query[i] == '?' && argIndex < args.size) {
|
|
|
|
builder.append("'").append(args[argIndex]).append("'")
|
|
|
|
argIndex++
|
|
|
|
} else {
|
|
|
|
builder.append(query[i])
|
|
|
|
}
|
|
|
|
i++
|
|
|
|
}
|
|
|
|
|
|
|
|
return builder.toString()
|
2022-02-14 19:18:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
data class DeviceInfo(
|
|
|
|
val name: String,
|
|
|
|
val packageName: String,
|
|
|
|
val appVersion: String
|
|
|
|
)
|
2022-02-23 23:22:58 +00:00
|
|
|
|
|
|
|
data class DatabaseConfig(
|
|
|
|
val db: SupportSQLiteDatabase,
|
|
|
|
val columnTransformers: List<ColumnTransformer> = emptyList()
|
|
|
|
)
|
2022-02-14 19:18:03 +00:00
|
|
|
}
|