123 lines
4.7 KiB
Swift
123 lines
4.7 KiB
Swift
import Foundation
|
||
import DataLiteCore
|
||
|
||
/// A type that defines how a database schema version is stored and retrieved.
|
||
///
|
||
/// ## Overview
|
||
///
|
||
/// This protocol separates the concept of version representation from its persistence mechanism,
|
||
/// allowing flexible implementations that store version values in different formats or locations.
|
||
///
|
||
/// The associated ``Version`` type specifies how the version is represented (for example, as an
|
||
/// integer, a semantic string, or a structured object), while the conforming type defines how that
|
||
/// version is persisted.
|
||
///
|
||
/// ## Usage
|
||
///
|
||
/// Implement this type to define a custom strategy for schema version tracking:
|
||
/// - Store an integer version in SQLite’s `user_version` field.
|
||
/// - Store a string in a dedicated metadata table.
|
||
/// - Store structured data in a JSON column.
|
||
///
|
||
/// The example below shows an implementation that stores the version string in a `schema_version`
|
||
/// table:
|
||
///
|
||
/// ```swift
|
||
/// final class StringVersionStorage: VersionStorage {
|
||
/// typealias Version = String
|
||
///
|
||
/// func prepare(_ connection: ConnectionProtocol) throws {
|
||
/// let script = """
|
||
/// CREATE TABLE IF NOT EXISTS schema_version (
|
||
/// version TEXT NOT NULL
|
||
/// );
|
||
///
|
||
/// INSERT INTO schema_version (version)
|
||
/// SELECT '0.0.0'
|
||
/// WHERE NOT EXISTS (SELECT 1 FROM schema_version);
|
||
/// """
|
||
/// try connection.execute(sql: script)
|
||
/// }
|
||
///
|
||
/// func getVersion(_ connection: ConnectionProtocol) throws -> Version {
|
||
/// let query = "SELECT version FROM schema_version LIMIT 1"
|
||
/// let stmt = try connection.prepare(sql: query)
|
||
/// guard try stmt.step(), let value: Version = stmt.columnValue(at: 0) else {
|
||
/// throw DatabaseError.message("Missing version in schema_version table.")
|
||
/// }
|
||
/// return value
|
||
/// }
|
||
///
|
||
/// func setVersion(_ connection: ConnectionProtocol, _ version: Version) throws {
|
||
/// let query = "UPDATE schema_version SET version = ?"
|
||
/// let stmt = try connection.prepare(sql: query)
|
||
/// try stmt.bind(version, at: 0)
|
||
/// try stmt.step()
|
||
/// }
|
||
/// }
|
||
/// ```
|
||
///
|
||
/// ## Topics
|
||
///
|
||
/// ### Associated Types
|
||
///
|
||
/// - ``Version``
|
||
///
|
||
/// ### Instance Methods
|
||
///
|
||
/// - ``prepare(_:)``
|
||
/// - ``getVersion(_:)``
|
||
/// - ``setVersion(_:_:)``
|
||
public protocol VersionStorage {
|
||
/// The type representing the database schema version.
|
||
associatedtype Version: VersionRepresentable
|
||
|
||
/// Creates a new instance of the version storage.
|
||
init()
|
||
|
||
/// Prepares the storage mechanism for tracking the schema version.
|
||
///
|
||
/// Called before any version operations. Use this method to create required tables or metadata
|
||
/// structures for version management.
|
||
///
|
||
/// - Important: Executed within an active migration transaction. Do not issue `BEGIN` or
|
||
/// `COMMIT` manually. If this method throws an error, the migration process will be aborted
|
||
/// and rolled back.
|
||
///
|
||
/// - Parameter connection: The database connection used for schema preparation.
|
||
/// - Throws: An error if preparation fails.
|
||
func prepare(_ connection: ConnectionProtocol) throws
|
||
|
||
/// Returns the current schema version stored in the database.
|
||
///
|
||
/// Must return a valid version previously stored by the migration system.
|
||
///
|
||
/// - Important: Executed within an active migration transaction. Do not issue `BEGIN` or
|
||
/// `COMMIT` manually. If this method throws an error, the migration process will be aborted
|
||
/// and rolled back.
|
||
///
|
||
/// - Parameter connection: The database connection used to fetch the version.
|
||
/// - Returns: The version currently stored in the database.
|
||
/// - Throws: An error if reading fails or the version is missing.
|
||
func getVersion(_ connection: ConnectionProtocol) throws -> Version
|
||
|
||
/// Stores the given version as the current schema version.
|
||
///
|
||
/// Called at the end of the migration process to persist the final schema version after all
|
||
/// migration steps complete successfully.
|
||
///
|
||
/// - Important: Executed within an active migration transaction. Do not issue `BEGIN` or
|
||
/// `COMMIT` manually. If this method throws an error, the migration process will be aborted
|
||
/// and rolled back.
|
||
///
|
||
/// - Parameters:
|
||
/// - connection: The database connection used to write the version.
|
||
/// - version: The version to store.
|
||
/// - Throws: An error if writing fails.
|
||
func setVersion(_ connection: ConnectionProtocol, _ version: Version) throws
|
||
}
|
||
|
||
public extension VersionStorage {
|
||
func prepare(_ connection: ConnectionProtocol) throws {}
|
||
}
|