Supporting Custom Types
SQLite.swift is extensible and allows you to add support for your own custom types to be stored in the database. This is achieved by conforming your type to the Value
protocol.
The Value
Protocol
The Value
protocol defines how a custom type should be converted to and from a fundamental SQLite data type.
protocol Value {
// The fundamental Swift type (String, Int64, Double, Blob) it maps to
typealias Datatype: Binding
// The SQL type declaration (e.g., "TEXT", "INTEGER")
static var declaredDatatype: String { get }
// How to create your type from the fundamental type
static func fromDatatypeValue(datatypeValue: Datatype) -> Self
// How to convert your type to the fundamental type
var datatypeValue: Datatype { get }
}
Example: Date
Support
SQLite.swift includes Date
support out of the box by storing it as a TEXT
column in ISO 8601 format. Here is how it's implemented, serving as a clear example:
extension Date: Value {
// We will store Dates as Strings in the database
public typealias Datatype = String
public static var declaredDatatype: String {
return String.declaredDatatype // "TEXT"
}
// How to convert a String from the DB into a Date
public static func fromDatatypeValue(_ stringValue: String) -> Date {
return dateFormatter.date(from: stringValue)!
}
// How to convert a Date into a String for the DB
public var datatypeValue: String {
return dateFormatter.string(from: self)
}
}
With this conformance, you can use Date
directly in your expressions:
let published_at = Expression<Date>("published_at")
let publishedPosts = posts.filter(published_at <= Date())
// SELECT * FROM "posts" WHERE "published_at" <= '2023-10-27T10:00:00.000'
Example: Binary Data (UIImage
)
You can also bridge types that can be represented as binary data (BLOB
). For example, to store a UIImage
:
import UIKit
extension UIImage: Value {
public class var declaredDatatype: String {
return Blob.declaredDatatype // "BLOB"
}
public class func fromDatatypeValue(blobValue: Blob) -> UIImage {
return UIImage(data: Data.fromDatatypeValue(blobValue))!
}
public var datatypeValue: Blob {
return self.pngData()!.datatypeValue
}
}
Now you can define Expression<UIImage>
columns and use UIImage
objects directly in your insert and update statements.