Using SQLite3 in Swift directly
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
class SQLite { | |
enum SQLError: Error { | |
case connectionError | |
case queryError | |
case otherError | |
} | |
enum ColumnType { | |
case int | |
case double | |
case text | |
} | |
var db: OpaquePointer? | |
var stmt: OpaquePointer? | |
let path: String = { | |
let fm = FileManager.default | |
return fm.urls(for:.libraryDirectory, in:.userDomainMask).last! | |
.appendingPathComponent("data.db").path | |
}() | |
init() throws { | |
guard sqlite3_open(path, &db) == SQLITE_OK | |
else { | |
throw SQLError.connectionError | |
} | |
} | |
func install(query: String) throws { | |
sqlite3_finalize(stmt) | |
stmt = nil | |
if sqlite3_prepare_v2(db, query, -1, &stmt, nil) == SQLITE_OK { | |
return | |
} | |
throw SQLError.queryError | |
} | |
func bind(data:Any, withType type: ColumnType, at col: Int32 = 1) { | |
switch type { | |
case .int: | |
if let value = data as? Int { | |
sqlite3_bind_int(stmt, col, Int32(value)) | |
} | |
case .double: | |
if let value = data as? Double { | |
sqlite3_bind_double(stmt, col, value) | |
} | |
case .text: | |
if let value = data as? String { | |
sqlite3_bind_text(stmt, col, value, -1, nil) | |
} | |
} | |
} | |
func execute(rowHandler:((OpaquePointer) -> Void)? = nil) throws { | |
while true { | |
switch sqlite3_step(stmt) { | |
case SQLITE_DONE: | |
return | |
case SQLITE_ROW: | |
rowHandler?(stmt!) | |
default: | |
throw SQLError.otherError | |
} | |
} | |
} | |
deinit { | |
sqlite3_finalize(stmt) | |
sqlite3_close(db) | |
} | |
} | |
do { | |
let db = try SQLite() | |
// 테이블 생성 | |
try db.install(query:"CREATE TABLE IF NOT EXISTS test (num INTEGER)") | |
try db.execute() | |
for i in 10..<20 { | |
try db.install(query:"INSERT INTO test VALUES (?)") | |
db.bind(data: i, withType: .int) | |
try db.execute() | |
} | |
/// 조회 | |
try db.install(query:"select * from test") | |
try db.execute(){ stmt in | |
let n = sqlite3_column_int(stmt, 0) | |
print(n) | |
} | |
} catch { | |
print(error) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment