mirror of
https://github.com/home-assistant/iOS.git
synced 2026-02-04 02:46:35 -06:00
## Summary Table migration logic for adding new columns and removing obsolete columns has been abstracted into `DatabaseTableProtocol` with a default implementation. All 13 table implementations now conform to the extended protocol and support automatic column migration. **Protocol Changes:** - Added `tableName: String` property requirement - Added `definedColumns: [String]` property requirement - Added default `migrateColumns(database:)` implementation that handles adding/removing columns **Updated Tables:** All tables now implement the protocol and support column migration: - `HAppEntityTable`, `WatchConfigTable`, `CarPlayConfigTable`, `AssistPipelinesTable` - `AppEntityRegistryListForDisplayTable`, `AppEntityRegistryTable`, `AppDeviceRegistryTable` - `AppPanelTable`, `CustomWidgetTable`, `AppAreaTable` - `HomeViewConfigurationTable`, `CameraListConfigurationTable`, `AssistConfigurationTable` **Column Enums:** All column enums in `DatabaseTables` now conform to `CaseIterable` for consistent migration support. Relies on `ALTER TABLE ... DROP COLUMN` support (SQLite 3.35+, iOS 15+). ## Screenshots N/A - Database internals only. ## Link to pull request in Documentation repository N/A - No user-facing changes. ## Any other notes The migration logic is now centralized in the protocol extension, eliminating code duplication across table implementations. Each table provides its `tableName` and `definedColumns`, and the shared `migrateColumns(database:)` method handles the actual column synchronization. <!-- START COPILOT CODING AGENT SUFFIX --> <!-- START COPILOT ORIGINAL PROMPT --> <details> <summary>Original prompt</summary> > In GRDB+Initialization.swift each tablet has a logic to create table columns that may not exist when the user updates the app, update those table creationg to also delete columns that are not defined in the create method anymore </details> <!-- START COPILOT CODING AGENT TIPS --> --- ✨ Let Copilot coding agent [set things up for you](https://github.com/home-assistant/iOS/issues/new?title=✨+Set+up+Copilot+instructions&body=Configure%20instructions%20for%20this%20repository%20as%20documented%20in%20%5BBest%20practices%20for%20Copilot%20coding%20agent%20in%20your%20repository%5D%28https://gh.io/copilot-coding-agent-tips%29%2E%0A%0A%3COnboard%20this%20repo%3E&assignees=copilot) — coding agent works faster and does higher quality work when set up for your repo. --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: bgoncal <5808343+bgoncal@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
67 lines
3.2 KiB
Swift
67 lines
3.2 KiB
Swift
import Foundation
|
|
import GRDB
|
|
|
|
final class AppDeviceRegistryTable: DatabaseTableProtocol {
|
|
var tableName: String { GRDBDatabaseTable.deviceRegistry.rawValue }
|
|
|
|
var definedColumns: [String] { DatabaseTables.DeviceRegistry.allCases.filter { $0 != .id }.map(\.rawValue) }
|
|
|
|
func createIfNeeded(database: DatabaseQueue) throws {
|
|
let shouldCreateTable = try database.read { db in
|
|
try !db.tableExists(tableName)
|
|
}
|
|
if shouldCreateTable {
|
|
try database.write { db in
|
|
try db.create(table: tableName) { t in
|
|
// Core identifiers
|
|
t.column(DatabaseTables.DeviceRegistry.serverId.rawValue, .text).notNull().indexed()
|
|
t.column(DatabaseTables.DeviceRegistry.deviceId.rawValue, .text).notNull().indexed()
|
|
|
|
// Device identification
|
|
t.column(DatabaseTables.DeviceRegistry.areaId.rawValue, .text).indexed()
|
|
t.column(DatabaseTables.DeviceRegistry.configurationURL.rawValue, .text)
|
|
t.column(DatabaseTables.DeviceRegistry.configEntries.rawValue, .jsonText)
|
|
t.column(DatabaseTables.DeviceRegistry.configEntriesSubentries.rawValue, .jsonText)
|
|
t.column(DatabaseTables.DeviceRegistry.connections.rawValue, .jsonText)
|
|
t.column(DatabaseTables.DeviceRegistry.identifiers.rawValue, .jsonText)
|
|
|
|
// Timestamps
|
|
t.column(DatabaseTables.DeviceRegistry.createdAt.rawValue, .double)
|
|
t.column(DatabaseTables.DeviceRegistry.modifiedAt.rawValue, .double)
|
|
|
|
// Status fields
|
|
t.column(DatabaseTables.DeviceRegistry.disabledBy.rawValue, .text)
|
|
t.column(DatabaseTables.DeviceRegistry.entryType.rawValue, .text)
|
|
|
|
// Hardware information
|
|
t.column(DatabaseTables.DeviceRegistry.hwVersion.rawValue, .text)
|
|
t.column(DatabaseTables.DeviceRegistry.swVersion.rawValue, .text)
|
|
t.column(DatabaseTables.DeviceRegistry.serialNumber.rawValue, .text)
|
|
|
|
// Device details
|
|
t.column(DatabaseTables.DeviceRegistry.manufacturer.rawValue, .text)
|
|
t.column(DatabaseTables.DeviceRegistry.model.rawValue, .text)
|
|
t.column(DatabaseTables.DeviceRegistry.modelID.rawValue, .text)
|
|
|
|
// Display fields
|
|
t.column(DatabaseTables.DeviceRegistry.name.rawValue, .text)
|
|
t.column(DatabaseTables.DeviceRegistry.nameByUser.rawValue, .text)
|
|
t.column(DatabaseTables.DeviceRegistry.labels.rawValue, .jsonText)
|
|
|
|
// Relationships
|
|
t.column(DatabaseTables.DeviceRegistry.primaryConfigEntry.rawValue, .text)
|
|
t.column(DatabaseTables.DeviceRegistry.viaDeviceID.rawValue, .text)
|
|
|
|
// ID
|
|
t.uniqueKey([
|
|
DatabaseTables.DeviceRegistry.serverId.rawValue,
|
|
DatabaseTables.DeviceRegistry.deviceId.rawValue,
|
|
])
|
|
}
|
|
}
|
|
} else {
|
|
try migrateColumns(database: database)
|
|
}
|
|
}
|
|
}
|