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 { override fun dependencies(): List>> = 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(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) }