mirror of
https://github.com/signalapp/Signal-Android.git
synced 2025-12-23 12:38:33 +00:00
Merge v186 and v185 migrations.
This commit is contained in:
@@ -40,8 +40,7 @@ import org.thoughtcrime.securesms.database.helpers.migration.V181_ThreadTableFor
|
|||||||
import org.thoughtcrime.securesms.database.helpers.migration.V182_CallTableMigration
|
import org.thoughtcrime.securesms.database.helpers.migration.V182_CallTableMigration
|
||||||
import org.thoughtcrime.securesms.database.helpers.migration.V183_CallLinkTableMigration
|
import org.thoughtcrime.securesms.database.helpers.migration.V183_CallLinkTableMigration
|
||||||
import org.thoughtcrime.securesms.database.helpers.migration.V184_CallLinkReplaceIndexMigration
|
import org.thoughtcrime.securesms.database.helpers.migration.V184_CallLinkReplaceIndexMigration
|
||||||
import org.thoughtcrime.securesms.database.helpers.migration.V185_MessageRecipientsMigration
|
import org.thoughtcrime.securesms.database.helpers.migration.V185_MessageRecipientsAndEditMessageMigration
|
||||||
import org.thoughtcrime.securesms.database.helpers.migration.V186_AddEditMessageColumnsMigration
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contains all of the database migrations for [SignalDatabase]. Broken into a separate file for cleanliness.
|
* Contains all of the database migrations for [SignalDatabase]. Broken into a separate file for cleanliness.
|
||||||
@@ -50,7 +49,7 @@ object SignalDatabaseMigrations {
|
|||||||
|
|
||||||
val TAG: String = Log.tag(SignalDatabaseMigrations.javaClass)
|
val TAG: String = Log.tag(SignalDatabaseMigrations.javaClass)
|
||||||
|
|
||||||
const val DATABASE_VERSION = 186
|
const val DATABASE_VERSION = 185
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
|
fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
|
||||||
@@ -199,11 +198,7 @@ object SignalDatabaseMigrations {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (oldVersion < 185) {
|
if (oldVersion < 185) {
|
||||||
V185_MessageRecipientsMigration.migrate(context, db, oldVersion, newVersion)
|
V185_MessageRecipientsAndEditMessageMigration.migrate(context, db, oldVersion, newVersion)
|
||||||
}
|
|
||||||
|
|
||||||
if (oldVersion < 186) {
|
|
||||||
V186_AddEditMessageColumnsMigration.migrate(context, db, oldVersion, newVersion)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,12 +18,20 @@ import org.thoughtcrime.securesms.recipients.RecipientId
|
|||||||
import org.whispersystems.signalservice.api.push.ACI
|
import org.whispersystems.signalservice.api.push.ACI
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* This is a combination of the edit message and message recipient migrations (would have been V185 and v186), but as they
|
||||||
|
* both require recreating the message table, they are merged into one.
|
||||||
|
*
|
||||||
|
* Original V185:
|
||||||
* Our current column setup for knowing is the the sender/receiver of a message is both confusing and non-optimal from a performance perspective.
|
* Our current column setup for knowing is the the sender/receiver of a message is both confusing and non-optimal from a performance perspective.
|
||||||
* This moves to a world where instead of tracking a single recipient, we track two: a sender and receiver.
|
* This moves to a world where instead of tracking a single recipient, we track two: a sender and receiver.
|
||||||
|
*
|
||||||
|
* Original V186:
|
||||||
|
* Changes needed for edit message. New foreign keys require recreating the table.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
object V185_MessageRecipientsMigration : SignalDatabaseMigration {
|
object V185_MessageRecipientsAndEditMessageMigration : SignalDatabaseMigration {
|
||||||
|
|
||||||
private val TAG = Log.tag(V185_MessageRecipientsMigration::class.java)
|
private val TAG = Log.tag(V185_MessageRecipientsAndEditMessageMigration::class.java)
|
||||||
|
|
||||||
private val outgoingClause = "(" + listOf(21, 23, 22, 24, 25, 26, 2, 11)
|
private val outgoingClause = "(" + listOf(21, 23, 22, 24, 25, 26, 2, 11)
|
||||||
.map { "type & ${0x1F} = $it" }
|
.map { "type & ${0x1F} = $it" }
|
||||||
@@ -106,7 +114,10 @@ object V185_MessageRecipientsMigration : SignalDatabaseMigration {
|
|||||||
parent_story_id INTEGER DEFAULT 0,
|
parent_story_id INTEGER DEFAULT 0,
|
||||||
export_state BLOB DEFAULT NULL,
|
export_state BLOB DEFAULT NULL,
|
||||||
exported INTEGER DEFAULT 0,
|
exported INTEGER DEFAULT 0,
|
||||||
scheduled_date INTEGER DEFAULT -1
|
scheduled_date INTEGER DEFAULT -1,
|
||||||
|
latest_revision_id INTEGER DEFAULT NULL REFERENCES message (_id) ON DELETE CASCADE,
|
||||||
|
original_message_id INTEGER DEFAULT NULL REFERENCES message (_id) ON DELETE CASCADE,
|
||||||
|
revision_number INTEGER DEFAULT 0
|
||||||
)
|
)
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
@@ -164,7 +175,10 @@ object V185_MessageRecipientsMigration : SignalDatabaseMigration {
|
|||||||
parent_story_id,
|
parent_story_id,
|
||||||
export_state,
|
export_state,
|
||||||
exported,
|
exported,
|
||||||
scheduled_date
|
scheduled_date,
|
||||||
|
NULL AS latest_revision_id,
|
||||||
|
NULL AS original_message_id,
|
||||||
|
0 as revision_number
|
||||||
FROM message
|
FROM message
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
@@ -194,6 +208,8 @@ object V185_MessageRecipientsMigration : SignalDatabaseMigration {
|
|||||||
|
|
||||||
dependentItems.forEach { item ->
|
dependentItems.forEach { item ->
|
||||||
val sql = when (item.name) {
|
val sql = when (item.name) {
|
||||||
|
"mms_thread_story_parent_story_scheduled_date_index" -> "CREATE INDEX message_thread_story_parent_story_scheduled_date_latest_revision_id_index ON message (thread_id, date_received, story_type, parent_story_id, scheduled_date, latest_revision_id)"
|
||||||
|
"mms_quote_id_quote_author_scheduled_date_index" -> "CREATE INDEX message_quote_id_quote_author_scheduled_date_latest_revision_id_index ON message (quote_id, quote_author, scheduled_date, latest_revision_id)"
|
||||||
"mms_date_sent_index" -> "CREATE INDEX message_date_sent_from_to_thread_index ON message (date_sent, from_recipient_id, to_recipient_id, thread_id)"
|
"mms_date_sent_index" -> "CREATE INDEX message_date_sent_from_to_thread_index ON message (date_sent, from_recipient_id, to_recipient_id, thread_id)"
|
||||||
else -> item.createStatement.replace(Regex.fromLiteral("CREATE INDEX mms_"), "CREATE INDEX message_")
|
else -> item.createStatement.replace(Regex.fromLiteral("CREATE INDEX mms_"), "CREATE INDEX message_")
|
||||||
}
|
}
|
||||||
@@ -1,189 +0,0 @@
|
|||||||
package org.thoughtcrime.securesms.database.helpers.migration
|
|
||||||
|
|
||||||
import android.app.Application
|
|
||||||
import net.zetetic.database.sqlcipher.SQLiteDatabase
|
|
||||||
import org.signal.core.util.Stopwatch
|
|
||||||
import org.signal.core.util.logging.Log
|
|
||||||
import org.signal.core.util.readToList
|
|
||||||
import org.signal.core.util.requireNonNullString
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Changes needed for edit message. New foreign keys require recreating the table.
|
|
||||||
*/
|
|
||||||
@Suppress("ClassName")
|
|
||||||
object V186_AddEditMessageColumnsMigration : SignalDatabaseMigration {
|
|
||||||
|
|
||||||
private val TAG = Log.tag(V186_AddEditMessageColumnsMigration::class.java)
|
|
||||||
|
|
||||||
override fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
|
|
||||||
val stopwatch = Stopwatch("migration")
|
|
||||||
|
|
||||||
val dependentItems: List<SqlItem> = getAllDependentItems(db, "message")
|
|
||||||
dependentItems.forEach { item ->
|
|
||||||
val sql = "DROP ${item.type} IF EXISTS ${item.name}"
|
|
||||||
Log.d(TAG, "Executing: $sql")
|
|
||||||
db.execSQL(sql)
|
|
||||||
}
|
|
||||||
|
|
||||||
stopwatch.split("drop-dependents")
|
|
||||||
|
|
||||||
db.execSQL(
|
|
||||||
"""
|
|
||||||
CREATE TABLE message_tmp (
|
|
||||||
_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
||||||
date_sent INTEGER NOT NULL,
|
|
||||||
date_received INTEGER NOT NULL,
|
|
||||||
date_server INTEGER DEFAULT -1,
|
|
||||||
thread_id INTEGER NOT NULL REFERENCES thread (_id) ON DELETE CASCADE,
|
|
||||||
from_recipient_id INTEGER NOT NULL REFERENCES recipient (_id) ON DELETE CASCADE,
|
|
||||||
from_device_id INTEGER,
|
|
||||||
to_recipient_id INTEGER NOT NULL REFERENCES recipient (_id) ON DELETE CASCADE,
|
|
||||||
type INTEGER NOT NULL,
|
|
||||||
body TEXT,
|
|
||||||
read INTEGER DEFAULT 0,
|
|
||||||
ct_l TEXT,
|
|
||||||
exp INTEGER,
|
|
||||||
m_type INTEGER,
|
|
||||||
m_size INTEGER,
|
|
||||||
st INTEGER,
|
|
||||||
tr_id TEXT,
|
|
||||||
subscription_id INTEGER DEFAULT -1,
|
|
||||||
receipt_timestamp INTEGER DEFAULT -1,
|
|
||||||
delivery_receipt_count INTEGER DEFAULT 0,
|
|
||||||
read_receipt_count INTEGER DEFAULT 0,
|
|
||||||
viewed_receipt_count INTEGER DEFAULT 0,
|
|
||||||
mismatched_identities TEXT DEFAULT NULL,
|
|
||||||
network_failures TEXT DEFAULT NULL,
|
|
||||||
expires_in INTEGER DEFAULT 0,
|
|
||||||
expire_started INTEGER DEFAULT 0,
|
|
||||||
notified INTEGER DEFAULT 0,
|
|
||||||
quote_id INTEGER DEFAULT 0,
|
|
||||||
quote_author INTEGER DEFAULT 0,
|
|
||||||
quote_body TEXT DEFAULT NULL,
|
|
||||||
quote_missing INTEGER DEFAULT 0,
|
|
||||||
quote_mentions BLOB DEFAULT NULL,
|
|
||||||
quote_type INTEGER DEFAULT 0,
|
|
||||||
shared_contacts TEXT DEFAULT NULL,
|
|
||||||
unidentified INTEGER DEFAULT 0,
|
|
||||||
link_previews TEXT DEFAULT NULL,
|
|
||||||
view_once INTEGER DEFAULT 0,
|
|
||||||
reactions_unread INTEGER DEFAULT 0,
|
|
||||||
reactions_last_seen INTEGER DEFAULT -1,
|
|
||||||
remote_deleted INTEGER DEFAULT 0,
|
|
||||||
mentions_self INTEGER DEFAULT 0,
|
|
||||||
notified_timestamp INTEGER DEFAULT 0,
|
|
||||||
server_guid TEXT DEFAULT NULL,
|
|
||||||
message_ranges BLOB DEFAULT NULL,
|
|
||||||
story_type INTEGER DEFAULT 0,
|
|
||||||
parent_story_id INTEGER DEFAULT 0,
|
|
||||||
export_state BLOB DEFAULT NULL,
|
|
||||||
exported INTEGER DEFAULT 0,
|
|
||||||
scheduled_date INTEGER DEFAULT -1,
|
|
||||||
latest_revision_id INTEGER DEFAULT NULL REFERENCES message (_id) ON DELETE CASCADE,
|
|
||||||
original_message_id INTEGER DEFAULT NULL REFERENCES message (_id) ON DELETE CASCADE,
|
|
||||||
revision_number INTEGER DEFAULT 0
|
|
||||||
)
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
stopwatch.split("create-table")
|
|
||||||
|
|
||||||
db.execSQL(
|
|
||||||
"""
|
|
||||||
INSERT INTO message_tmp
|
|
||||||
SELECT
|
|
||||||
_id,
|
|
||||||
date_sent,
|
|
||||||
date_received,
|
|
||||||
date_server,
|
|
||||||
thread_id,
|
|
||||||
from_recipient_id,
|
|
||||||
from_device_id,
|
|
||||||
to_recipient_id,
|
|
||||||
type,
|
|
||||||
body,
|
|
||||||
read,
|
|
||||||
ct_l,
|
|
||||||
exp,
|
|
||||||
m_type,
|
|
||||||
m_size,
|
|
||||||
st,
|
|
||||||
tr_id,
|
|
||||||
subscription_id,
|
|
||||||
receipt_timestamp,
|
|
||||||
delivery_receipt_count,
|
|
||||||
read_receipt_count,
|
|
||||||
viewed_receipt_count,
|
|
||||||
mismatched_identities,
|
|
||||||
network_failures,
|
|
||||||
expires_in,
|
|
||||||
expire_started,
|
|
||||||
notified,
|
|
||||||
quote_id,
|
|
||||||
quote_author,
|
|
||||||
quote_body,
|
|
||||||
quote_missing,
|
|
||||||
quote_mentions,
|
|
||||||
quote_type,
|
|
||||||
shared_contacts,
|
|
||||||
unidentified,
|
|
||||||
link_previews,
|
|
||||||
view_once,
|
|
||||||
reactions_unread,
|
|
||||||
reactions_last_seen,
|
|
||||||
remote_deleted,
|
|
||||||
mentions_self,
|
|
||||||
notified_timestamp,
|
|
||||||
server_guid,
|
|
||||||
message_ranges,
|
|
||||||
story_type,
|
|
||||||
parent_story_id,
|
|
||||||
export_state,
|
|
||||||
exported,
|
|
||||||
scheduled_date,
|
|
||||||
NULL AS latest_revision_id,
|
|
||||||
NULL AS original_message_id,
|
|
||||||
0 as revision_number
|
|
||||||
FROM message
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
stopwatch.split("copy-data")
|
|
||||||
|
|
||||||
db.execSQL("DROP TABLE message")
|
|
||||||
stopwatch.split("drop-old")
|
|
||||||
|
|
||||||
db.execSQL("ALTER TABLE message_tmp RENAME TO message")
|
|
||||||
stopwatch.split("rename-table")
|
|
||||||
|
|
||||||
dependentItems.forEach { item ->
|
|
||||||
val sql = when (item.name) {
|
|
||||||
"message_thread_story_parent_story_scheduled_date_index" -> "CREATE INDEX message_thread_story_parent_story_scheduled_date_latest_revision_id_index ON message (thread_id, date_received, story_type, parent_story_id, scheduled_date, latest_revision_id)"
|
|
||||||
"message_quote_id_quote_author_scheduled_date_index" -> "CREATE INDEX message_quote_id_quote_author_scheduled_date_latest_revision_id_index ON message (quote_id, quote_author, scheduled_date, latest_revision_id)"
|
|
||||||
else -> item.createStatement
|
|
||||||
}
|
|
||||||
Log.d(TAG, "Executing: $sql")
|
|
||||||
db.execSQL(sql)
|
|
||||||
}
|
|
||||||
stopwatch.split("recreate-dependents")
|
|
||||||
|
|
||||||
db.execSQL("PRAGMA foreign_key_check")
|
|
||||||
stopwatch.split("fk-check")
|
|
||||||
|
|
||||||
stopwatch.stop(TAG)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getAllDependentItems(db: SQLiteDatabase, tableName: String): List<SqlItem> {
|
|
||||||
return db.rawQuery("SELECT type, name, sql FROM sqlite_schema WHERE tbl_name='$tableName' AND type != 'table'").readToList { cursor ->
|
|
||||||
SqlItem(
|
|
||||||
type = cursor.requireNonNullString("type"),
|
|
||||||
name = cursor.requireNonNullString("name"),
|
|
||||||
createStatement = cursor.requireNonNullString("sql")
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data class SqlItem(
|
|
||||||
val type: String,
|
|
||||||
val name: String,
|
|
||||||
val createStatement: String
|
|
||||||
)
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user