Bold
A lightweight and extensible SQLite wrapper written in Swift.
Install / Use
/learn @ChristianKienle/BoldREADME

| Branch | Status |
| ------------- |:-------------:|
| Master | |
| Develop |
|
Simple Example
The example below creates an in-memory database, opens it, creates a table, inserts a row and then queries the table. Please note that the result is closed automatically after a complete iteration by using for-in.
let db = Database(URL:":memory:")
db.open()
db.update("CREATE TABLE Person (firstName, lastName)")
let args = ["firstName" : "Christian", "lastName" : "Kienle"]
db.update("INSERT INTO Person (firstName, lastName) VALUES (:firstName, :lastName)", arguments:args)
let result = db.query(query: "SELECT firstName, lastName FROM Person")
for row in result {
let firstName = row["firstName"].string
let lastName = row["lastName"].string
println("firstName: \(firstName)")
println("lastName: \(lastName)")
}
// The result is automatically closed after a complete iteration.
Extend Bold: Custom Types
I wanted Bold to be easily extensible. There are basically two things that can be extended:
- Support for custom data types in the input arguments.
- Support for custom data types when accessing a row.
Extend Types for Input Arguments
You can support custom data types for input arguments simply by implementing Bindable. Lets assume you have a custom class called UUID which represents a UUID and you would like to pass UUIDs to Bold when inserting a new row. You could implement Bindable by doing something like this:
extension UUID : Bindable {
public func bind(to statement:Statement, atIndex index:Int32) -> Bool {
let value = stringRepresentation // assume this exists
// call the existing implementation of `bind(to:atIndex:)`
return value.bind(to: statement, atIndex:atIndex)
}
This is all you have to do. Now you could use UUID like this in combination with Bold:
let uuid = UUID()
db.update("INSERT INTO Person (id) VALUES (:id)", arguments:["id" : uuid])
Extend Types for Output Arguments
When you access the contents of a row you access the data by using methods like stringValue(columnName:), intValue(columnName:) and so on. If you would like to add support for your own data type (for example a method that uses the binary data in a column to create a UIImage) you simply extend Row. Let's see how this works with our custom UUID class from above.
extension Row {
public func UUIDValue(columnName: String) -> UUID? {
guard let stringValue = stringValue(forColumn: columnName) else {
return nil
}
return UUID(stringValue)
}
}
Now you can use UUIDValue(columnName:) when accessing the data of your rows.
Why yet another SQLite wrapper?
I wanted to dive into Swift and writing a SQLite wrapper seemed like a good thing to do. So Bold is basically a just for fun project.
Lightweight
Bold is lightweight. This means that Bold does not try to be smart. For example it does not implement SQLITE_BUSY-handling like some other SQLite wrappers do. I believe that any implementation of SQLITE_BUSY-handling hides an underlying locking problem that you might have. Other wrappers simply wait for a couple of seconds until they time out. Please note that libsqlite3 already has ways to avoid SQLITE_BUSY related errors.
Bold also exposes the raw sqlite3 database handle and the raw sqlite3_stmt handle. You should try to avoid accessing those but if you need to access them they are there.
Related Skills
feishu-drive
339.5k|
things-mac
339.5kManage Things 3 via the `things` CLI on macOS (add/update projects+todos via URL scheme; read/search/list from the local Things database)
clawhub
339.5kUse the ClawHub CLI to search, install, update, and publish agent skills from clawhub.com
yu-ai-agent
2.0k编程导航 2025 年 AI 开发实战新项目,基于 Spring Boot 3 + Java 21 + Spring AI 构建 AI 恋爱大师应用和 ReAct 模式自主规划智能体YuManus,覆盖 AI 大模型接入、Spring AI 核心特性、Prompt 工程和优化、RAG 检索增强、向量数据库、Tool Calling 工具调用、MCP 模型上下文协议、AI Agent 开发(Manas Java 实现)、Cursor AI 工具等核心知识。用一套教程将程序员必知必会的 AI 技术一网打尽,帮你成为 AI 时代企业的香饽饽,给你的简历和求职大幅增加竞争力。
