SQLite.swift: A Type-Safe Swift Language Layer Over SQLite3
Welcome to the documentation for SQLite.swift, a library that provides a pure-Swift, type-safe, and developer-friendly interface to the powerful SQLite3 database engine. This project is designed to give you compile-time confidence in your SQL statements, eliminating common runtime errors and making database interactions in your Swift applications safer and more intuitive.
The Problem SQLite.swift Solves
Working directly with database APIs, especially C-based ones like SQLite's, can be cumbersome and error-prone in Swift. You often deal with raw strings for SQL queries, manual data type conversions, and optional values that can lead to unexpected crashes.
SQLite.swift elegantly solves this by creating a Swift-friendly abstraction layer that leverages the Swift type system. It allows you to build complex SQL queries using a chainable and expressive syntax, all while ensuring that your table names, column names, and data types are checked at compile time.
Key Features
- Type-Safe, Optional-Aware SQL Expression Builder: Write queries that are checked by the Swift compiler. Say goodbye to typos in column names causing runtime failures.
- Pure Swift Interface: A clean, modern API that feels right at home in any Swift project.
- Flexible & Chainable Query Layer: Construct queries piece by piece with a lazy-executing system that is both powerful and easy to read.
- Automatic Type Handling: Data is automatically converted between Swift types (
Int
,String
,Date
,Data
, etc.) and their corresponding SQLite counterparts. - Developer-Friendly Error Handling: Clear, descriptive errors help you debug issues quickly.
- Advanced Feature Support: Full-text search (FTS5), schema migrations, transactions, custom functions, and more are supported out of the box.
- SQLCipher Integration: Easily add database encryption to your projects via a simple CocoaPods subspec.
- Cross-Platform: Works on all Apple platforms (iOS, macOS, watchOS, tvOS, visionOS) and has support for Linux.
A Quick Look at the Syntax
Here’s a small taste of how SQLite.swift transforms database operations into clean, readable Swift code.
The Expression Builder Approach
import SQLite
do {
let db = try Connection("path/to/db.sqlite3")
let users = Table("users")
let id = Expression<Int64>("id")
let name = Expression<String?>("name")
let email = Expression<String>("email")
try db.run(users.create { t in
t.column(id, primaryKey: true)
t.column(name)
t.column(email, unique: true)
})
// CREATE TABLE "users" (
// "id" INTEGER PRIMARY KEY NOT NULL,
// "name" TEXT,
// "email" TEXT NOT NULL UNIQUE
// )
let insert = users.insert(name <- "Alice", email <- "alice@mac.com")
let rowid = try db.run(insert)
// INSERT INTO "users" ("name", "email") VALUES ('Alice', 'alice@mac.com')
for user in try db.prepare(users) {
print("id: \(user[id]), name: \(user[name]), email: \(user[email])")
// id: 1, name: Optional("Alice"), email: alice@mac.com
}
// SELECT * FROM "users"
} catch {
print (error)
}
Lightweight C API Wrapper
For those who prefer writing raw SQL, SQLite.swift also serves as a lightweight, Swift-friendly wrapper over the C API.
do {
let db = try Connection("path/to/db.sqlite3")
let stmt = try db.prepare("INSERT INTO users (email) VALUES (?)")
for email in ["betty@icloud.com", "cathy@icloud.com"] {
try stmt.run(email)
}
for row in try db.prepare("SELECT id, email FROM users") {
print("id: \(row[0]), email: \(row[1])")
// id: Optional(2), email: Optional("betty@icloud.com")
// id: Optional(3), email: Optional("cathy@icloud.com")
}
} catch {
print (error)
}
Ready to get started? Head over to the Installation guide.