Contents

william-weng/wwsqlite3manager

English | 繁體中文

🎉 相關說明

一套輕量級的 Swift SQLite3 工具,讓資料表定義、CRUD、條件查詢,以及聚合查詢都更直覺、更容易維護。


✨ 功能特色

  • 透過 SchemeDelegate 定義資料表結構,讓欄位與型別管理更明確。
  • 提供 createdropinsertupdatedeleteselect 等常用操作 API。
  • 支援可鏈式組合的 WhereGroupByHavingOrderByLimit,讓 SQL 更容易閱讀。
  • 同時支援以 schema 為基礎的全欄位查詢,以及使用 SelectMethod 的自訂欄位查詢。
  • 需要較底層控制時,也可以直接執行原生 SQL。

🧠 設計說明

這個套件的設計重點之一,是把資料表 schema 與查詢欄位投影分開。

  • SchemeDelegate.structure() 用在建表與全欄位查詢。
  • SelectMethod 用在查詢階段的欄位投影,例如聚合函數與別名。
  • 比起直接依賴 SELECT *,明確列出欄位通常更容易控管,也更適合長期維護。

📦 安裝方式

Swift Package Manager

dependencies: [
    .package(url: "https://github.com/William-Weng/WWSQLite3Manager.git", .upToNextMajor(from: "2.3.1"))
]
https://github.com/William-Weng/WWSQLite3Manager.git

🛠️ 公開 API

| API (WWSQLite3Manager) | 說明 | |---|---| | connect(fileURL:) | 建立 SQLite 連線。 | | connect(for:filename:) | 使用指定位置與檔名建立 SQLite 連線。 |

| API (Database) | 說明 | |---|---| | execute(sql:) | 直接執行原生 SQL。 | | prepare(sql:) | 預備並執行 SQL 語句。 | | query(sql:result:completion:) | 執行原生 SELECT 查詢。 | | close() | 關閉目前的 SQLite 連線。 | | scheme(tableName:) | 讀取指定資料表的結構資訊。 | | create(tableName:type:primaryKeys:ifNotExists:) | 依 schema 定義建立資料表。 | | drop(tableName:ifExists:) | 刪除資料表。 | | transaction(type:) | 在 transaction 範圍內執行 SQL。 | | insert(tableName:itemsArray:) | 執行 INSERT 查詢。 | | update(tableName:items:where:) | 執行 UPDATE 查詢。 | | delete(tableName:where:) | 執行 DELETE 查詢。 | | select(tableName:type:where:groupBy:having:orderBy:limit:) | 執行以 schema 為基礎的 SELECT 查詢。 | | select(tableName:methods:where:groupBy:having:orderBy:limit:) | 執行自訂欄位投影的 SELECT 查詢。 | | begin(type:) | 依指定模式開始 transaction。 | | commit() | 提交目前 transaction 的所有變更。 | | rollback() | 回滾目前 transaction 中尚未提交的變更。 | | transaction(type:_:) | 在 block 內執行 transaction,成功時自動提交,失敗時自動回滾。 |


🚀 基本範例

1. 定義資料模型與資料表結構

import Foundation
import WWSQLite3Manager

final class Student: Codable {
    
    let id: Int
    let name: String
    let height: Double
    let image: Data?
    let time: Date?
}

extension Student: WWSQLite3Manager.SchemeDelegate {
    
    static func structure() -> [WWSQLite3Manager.SchemeColumn] {
        [
            (key: "id", type: .INTEGER()),
            (key: "name", type: .TEXT(attribute: (isNotNull: true, isNoCase: true, isUnique: true), defaultValue: nil)),
            (key: "height", type: .REAL()),
            (key: "image", type: .BLOB()),
            (key: "time", type: .TIMESTAMP()),
        ]
    }
}

2. 連線、建表、寫入與查詢

final class ViewController: UIViewController {
    
    @IBOutlet weak var sqlLabel: UILabel!
    @IBOutlet weak var resultLabel: UILabel!
    
    private let filename = "sqlite3.db"
    private let tableName = "students"
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        do {
            let database = try WWSQLite3Manager.shared.connect(filename: filename)
            
            try database.drop(tableName: tableName, ifExists: true)
            try database.create(tableName: tableName, type: Student.self, ifNotExists: true)
            
            let items: [WWSQLite3Manager.InsertItem] = [
                (key: "name", value: .string("William.Weng")),
                (key: "height", value: .double(180.87)),
            ]
            
            let `where`: WWSQLite3Manager.Where = .init()
                .compare("height", .greaterThanOrEqual, .int(180))
                .and("name", .like, .text("%William%"))
            
            try database.insert(tableName: tableName, itemsArray: [items])
            let result = database.select(tableName: tableName, type: Student.self, where: `where`)
            
            sqlLabel.text = result.sql
            resultLabel.text = String(describing: result.array)
            
        } catch {
            print(error)
        }
    }
}

3. FTS5查詢功能

import UIKit
import WWSQLite3Manager

final class FTS5ViewController: UIViewController {
    
    @IBOutlet weak var resultLabel: UILabel!
    
    private let filename = "fts5.db"
    
    override func viewDidLoad() {
        
        super.viewDidLoad()
        
        do {
            let fileURL = URL.documentsDirectory.appendingPathComponent(filename)
                        
            if FileManager.default.fileExists(atPath: fileURL.path()) {
                try FileManager.default.removeItem(at: fileURL)
            }
            
            let database = try WWSQLite3Manager.shared.connect(fileURL: fileURL)
            
            let demo = FTS5Demo(database: database)
            let text1 = try demo.run()
            let text2 = try demo.testUpdateAndDelete()
            
            resultLabel.text = "\([text1, text2].flatMap { $0 }))"
            
            try database.close()
            
        } catch {
            print(error)
        }
    }
}

🧠 查詢條件建構器

這個套件提供多種 builder,讓 Swift 端組 SQL 時更好閱讀。

Where

let `where`: WWSQLite3Manager.Where = .init()
    .compare("height", .greaterThanOrEqual, .int(180))
    .and("name", .like, .text("%William%"))

GroupBy

let groupBy = WWSQLite3Manager.GroupBy().build(keys: ["department"])

Having

let having = WWSQLite3Manager.Having()
    .compare("COUNT(*)", .greaterThan, .int(3))

OrderBy

let orderBy = WWSQLite3Manager.OrderBy().build(orderTypes: [
    (key: "height", direction: .desc),
    (key: "name", direction: .asc)
])

Limit

let limit = WWSQLite3Manager.Limit().build(count: 20, offset: 0)

🍤 SelectMethod 自訂查詢欄位範例

當查詢結果不是整張表的原始欄位,而是聚合函數、別名或自訂欄位投影時,建議使用 select(tableName:methods:...)

let methods: [WWSQLite3Manager.SelectMethod] = [
    .column("name", .text),
    .count(nil, .int, aliasName: "totalCount"),
    .avg("height", .double, aliasName: "averageHeight")
]

let groupBy = WWSQLite3Manager.GroupBy().build(key: "name")
let having = WWSQLite3Manager.Having().compare("COUNT(*)", .greaterThan, .int(0))

let result = database.select(
    tableName: tableName,
    methods: methods,
    groupBy: groupBy,
    having: having
)

print(result.sql)
print(result.array)

建議使用方式:

  • select(tableName:type:...):適合依照 schema 查詢完整欄位。
  • select(tableName:methods:...):適合聚合查詢、別名欄位與自訂查詢結果。

Package Metadata

Repository: william-weng/wwsqlite3manager

Default branch: main

README: README.md