SubwayTooter-Android-App/app/src/main/java/jp/juggler/subwaytooter/table/AppDatabaseHolder.kt

210 lines
9.2 KiB
Kotlin

package jp.juggler.subwaytooter.table
import android.content.Context
import android.database.sqlite.SQLiteDatabase
import android.database.sqlite.SQLiteOpenHelper
import androidx.startup.AppInitializer
import androidx.startup.Initializer
import jp.juggler.subwaytooter.pref.LazyContextInitializer
import jp.juggler.subwaytooter.pref.lazyContext
import jp.juggler.util.coroutine.EmptyScope
import jp.juggler.util.log.LogCategory
import jp.juggler.util.os.applicationContextSafe
import kotlinx.coroutines.launch
import java.util.concurrent.atomic.AtomicReference
// 2017/4/25 v10 1=>2 SavedAccount に通知設定を追加
// 2017/4/25 v10 1=>2 NotificationTracking テーブルを追加
// 2017/4/29 v20 2=>5 MediaShown,ContentWarningのインデクスが間違っていたので貼り直す
// 2017/4/29 v23 5=>6 MutedAppテーブルの追加、UserRelationテーブルの追加
// 2017/5/01 v26 6=>7 AcctSetテーブルの追加
// 2017/5/02 v32 7=>8 (この変更は取り消された)
// 2017/5/02 v32 8=>9 AcctColor テーブルの追加
// 2017/5/04 v33 9=>10 SavedAccountに項目追加
// 2017/5/08 v41 10=>11 MutedWord テーブルの追加
// 2017/5/17 v59 11=>12 PostDraft テーブルの追加
// 2017/5/23 v68 12=>13 SavedAccountに項目追加
// 2017/5/25 v69 13=>14 SavedAccountに項目追加
// 2017/5/27 v73 14=>15 TagSetテーブルの追加
// 2017/7/22 v99 15=>16 SavedAccountに項目追加
// 2017/7/22 v106 16=>17 AcctColor に項目追加
// 2017/9/23 v161 17=>18 SavedAccountに項目追加
// 2017/9/23 v161 18=>19 ClientInfoテーブルを置き換える
// 2017/12/01 v175 19=>20 UserRelation に項目追加
// 2018/1/03 v197 20=>21 HighlightWord テーブルを追加
// 2018/3/16 v226 21=>22 FavMuteテーブルを追加
// 2018/4/17 v236 22=>23 SavedAccountテーブルに項目追加
// 2018/4/20 v240 23=>24 SavedAccountテーブルに項目追加
// 2018/5/16 v252 24=>25 SubscriptionServerKey テーブルを追加
// 2018/5/16 v252 25=>26 SubscriptionServerKey テーブルを丸ごと変更
// 2018/8/5 v264 26 => 27 SavedAccountテーブルに項目追加
// 2018/8/17 v267 27 => 28 SavedAccountテーブルに項目追加
// 2018/8/19 v267 28 => 29 (失敗)ContentWarningMisskey, MediaShownMisskey テーブルを追加
// 2018/8/19 v268 29 => 30 ContentWarningMisskey, MediaShownMisskey, UserRelationMisskeyテーブルを追加
// 2018/8/19 v268 30 => 31 (29)で失敗しておかしくなったContentWarningとMediaShownを作り直す
// 2018/8/28 v279 31 => 32 UserRelation,UserRelationMisskey にendorsedを追加
// 2018/8/28 v280 32 => 33 NotificationTracking テーブルの作り直し。SavedAccountに通知二種類を追加
// 2018/10/31 v296 33 => 34 UserRelationMisskey に blocked_by を追加
// 2018/10/31 v296 34 => 35 UserRelationMisskey に requested_by を追加
// 2018/12/6 v317 35 => 36 ContentWarningテーブルの作り直し。
// 2019/6/4 v351 36 => 37 SavedAccount テーブルに項目追加。
// 2019/6/4 v351 37 => 38 SavedAccount テーブルに項目追加。
// 2019/8/12 v362 38 => 39 SavedAccount テーブルに項目追加。
// 2019/10/22 39 => 40 NotificationTracking テーブルに項目追加。
// 2019/10/22 40 => 41 NotificationCache テーブルに項目追加。
// 2019/10/23 41=> 42 SavedAccount テーブルに項目追加。
// 2019/11/15 42=> 43 HighlightWord テーブルに項目追加。
// 2019/12/17 43=> 44 SavedAccount テーブルに項目追加。
// 2019/12/18 44=> 45 SavedAccount テーブルに項目追加。
// 2019/12/18 44=> 46 SavedAccount テーブルに項目追加。
// 2020/6/8 46 => 54 別ブランチで色々してた。このブランチには影響ないが onDowngrade()を実装してないので上げてしまう
// 2020/7/19 54=>55 UserRelation テーブルに項目追加。
// 2020/9/7 55=>56 SavedAccountテーブルにCOL_DOMAINを追加。
// 2020/9/20 56=>57 SavedAccountテーブルに項目追加
// 2020/9/20 57=>58 UserRelationテーブルに項目追加
// 2021/2/10 58=>59 SavedAccountテーブルに項目追加
// 2021/5/11 59=>60 SavedAccountテーブルに項目追加
// 2021/5/23 60=>61 SavedAccountテーブルに項目追加
// 2021/11/21 61=>62 SavedAccountテーブルに項目追加
// 2022/1/5 62=>63 SavedAccountテーブルに項目追加
// 2022/3/15 63=>64 SavedAccountテーブルに項目追加
// 2023/2/2 64 => 65 PushMessage, AccountNotificationStatus,NotificationShown テーブルの追加。
// 2023/2/11 65=>66 LogDataがなければ作る
// 2023/2/26 66=>67 ImageAspect テーブルの追加
const val DB_VERSION = 67
const val DB_NAME = "app_db"
// テーブルのリスト
// kotlin は配列を Compile-time Constant で作れないのでリストを2回書かないといけない
val TABLE_LIST = arrayOf(
AcctColor.Companion,
AcctSet.Companion,
ClientInfo.Companion,
ContentWarning.Companion,
FavMute.Companion,
HighlightWord.Companion,
LogData.Companion,
MediaShown.Companion,
MutedApp.Companion,
MutedWord.Companion,
NotificationCache.Companion,
NotificationTracking.Companion,
PostDraft.Companion,
SavedAccount.Companion,
SubscriptionServerKey.Companion,
TagHistory.Companion,
UserRelation.Companion,
PushMessage.Companion, // v65
AccountNotificationStatus.Companion, // v65,
NotificationShown.Companion, // v65
ImageAspect.Companion, // v67
)
private val log = LogCategory("AppDatabaseHolder")
class AppDatabaseHolder(
val context: Context,
val dbFileName: String,
val dbSchemaVersion: Int,
) : AutoCloseable {
private inner class DBOpenHelper(context: Context) :
SQLiteOpenHelper(context, dbFileName, null, dbSchemaVersion) {
override fun onCreate(db: SQLiteDatabase) {
log.d("onCreate")
for (ti in TABLE_LIST) {
ti.onDBCreate(db)
}
}
override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
log.d("onUpgrade $oldVersion => $newVersion")
for (ti in TABLE_LIST) {
ti.onDBUpgrade(db, oldVersion, newVersion)
}
}
}
private val openHelper = DBOpenHelper(context)
val database: SQLiteDatabase
get() = openHelper.writableDatabase
override fun close() {
openHelper.close()
}
fun deleteOld() {
val db = database
log.i("deleteOld: db.version=${db.version}")
val now = System.currentTimeMillis()
AcctSet.Access(db).deleteOld(now)
UserRelation.Access(db).deleteOld(now)
ContentWarning.Access(db).deleteOld(now)
MediaShown.Access(db).deleteOld(now)
PushMessage.Access(db).deleteOld(now)
NotificationShown.Access(db).deleteOld()
LogData.Access(db).deleteOld(now)
}
}
class AppDatabaseHolderIniitalizer : Initializer<AppDatabaseHolder> {
override fun dependencies(): List<Class<out Initializer<*>>> =
listOf(LazyContextInitializer::class.java)
override fun create(context: Context): AppDatabaseHolder {
val holder = AppDatabaseHolder(
context.applicationContextSafe,
DB_NAME,
DB_VERSION,
)
EmptyScope.launch {
try {
val logAccess = LogData.Access(holder.database)
LogCategory.hook = { l,c,m -> logAccess.insert(l,c,m) }
holder.deleteOld()
} catch (ex: Throwable) {
log.e(ex, "deleteOld failed.")
}
}
return holder
}
}
var appDatabaseHolderOverride =
AtomicReference<AppDatabaseHolder>(null)
val appDatabaseHolder
get() = appDatabaseHolderOverride.get()
?: AppInitializer.getInstance(lazyContext)
.initializeComponent(AppDatabaseHolderIniitalizer::class.java)
val appDatabase
get() = appDatabaseHolder.database
val daoAccountNotificationStatus get() = AccountNotificationStatus.Access(appDatabase)
val daoAcctColor get() = AcctColor.Access(appDatabase)
val daoAcctSet get() = AcctSet.Access(appDatabase)
val daoClientInfo get() = ClientInfo.Access(appDatabase)
val daoContentWarning get() = ContentWarning.Access(appDatabase)
val daoFavMute get() = FavMute.Access(appDatabase)
val daoHighlightWord get() = HighlightWord.Access(appDatabase)
val daoMediaShown get() = MediaShown.Access(appDatabase)
val daoMutedApp get() = MutedApp.Access(appDatabase)
val daoMutedWord get() = MutedWord.Access(appDatabase)
val daoNotificationCache get() = NotificationCache.Access(appDatabase)
val daoNotificationShown get() = NotificationShown.Access(appDatabase)
val daoNotificationTracking get() = NotificationTracking.Access(appDatabase)
val daoPostDraft get() = PostDraft.Access(appDatabase)
val daoSavedAccount get() = SavedAccount.Access(appDatabase, lazyContext)
val daoSubscriptionServerKey get() = SubscriptionServerKey.Access(appDatabase)
val daoTagHistory get() = TagHistory.Access(appDatabase)
val daoUserRelation get() = UserRelation.Access(appDatabase)
val daoPushMessage get() = PushMessage.Access(appDatabase)
val daoLogData get() = LogData.Access(appDatabase)
val daoImageAspect by lazy{
ImageAspect.Access(appDatabase)
}