SqlitePreparedStatement
struct
SqlitePreparedStatement
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
let statement: OpaquePointer?
// bind blob
func bind(_ index: Int, data: UnsafeRawPointer, length: Int) {
sqlite3_bind_blob(statement, Int32(index), data, Int32(length), SQLITE_TRANSIENT)
}
// bind text
func bindText(_ index: Int, data: UnsafeRawPointer, length: Int) {
sqlite3_bind_text(statement, Int32(index), data.assumingMemoryBound(to: Int8.self), Int32(length), SQLITE_TRANSIENT)
}
// bind int64
func bind(_ index: Int, number: Int64) {
sqlite3_bind_int64(statement, Int32(index), number)
}
// bind null
func bindNull(_ index: Int) {
sqlite3_bind_null(statement, Int32(index))
}
// bind int32
func bind(_ index: Int, number: Int32) {
sqlite3_bind_int(statement, Int32(index), number)
}
// reset and clear bindings
func reset() {
sqlite3_reset(statement)
sqlite3_clear_bindings(statement)
}
// step
func step(handle: OpaquePointer?, _ initial: Bool = false, pathToRemoveOnError: String?) -> Bool {
let res = sqlite3_step(statement)
if res != SQLITE_ROW && res != SQLITE_DONE {
// -[NSString initWithUtf8String:]
if let error = sqlite3_errmsg(handle), let str = NSString(utf8String: error) {
postboxLog("SQL error \(res): \(str) on step")
} else {
postboxLog("SQL error \(res) on step")
}
if res == SQLITE_CORRUPT {
if let path = pathToRemoveOnError {
postboxLog("Corrupted DB at step, dropping")
try? FileManager.default.removeItem(atPath: path)
preconditionFailure()
}
}
}
return res == SQLITE_ROW
}
// try step -> Result<Void, SqlError>
func tryStep(handle: OpaquePointer?, _ initial: Bool = false, pathToRemoveOnError: String?) -> Result<Void, SqlError> {
let res = sqlite3_step(statement)
if res != SQLITE_ROW && res != SQLITE_DONE {
if let error = sqlite3_errmsg(handle), let str = NSString(utf8String: error) {
postboxLog("SQL error \(res): \(str) on step")
} else {
postboxLog("SQL error \(res) on step")
}
if res == SQLITE_CORRUPT {
if let path = pathToRemoveOnError {
postboxLog("Corrupted DB at step, dropping")
try? FileManager.default.removeItem(atPath: path)
preconditionFailure()
}
}
}
if res == SQLITE_ROW || res == SQLITE_DONE {
return .success(Void())
} else {
return .failure(SqlError(code: res))
}
}
// read value of column at index as int32
func int32At(_ index: Int) -> Int32 {
return sqlite3_column_int(statement, Int32(index))
}
// read value of column at index as int64
func int64At(_ index: Int) -> Int64 {
return sqlite3_column_int64(statement, Int32(index))
}
// read value of column at index as blob that represented internally as ReadBuffer
func valueAt(_ index: Int) -> ReadBuffer {
let valueLength = sqlite3_column_bytes(statement, Int32(index))
let valueData = sqlite3_column_blob(statement, Int32(index))
let valueMemory = malloc(Int(valueLength))!
memcpy(valueMemory, valueData, Int(valueLength))
return ReadBuffer(memory: valueMemory, length: Int(valueLength), freeWhenDone: true)
}
// read value of column at index as blob that represented internally as an utf8 encoded String
func stringAt(_ index: Int) -> String? {
let valueLength = sqlite3_column_bytes(statement, Int32(index))
if let valueData = sqlite3_column_blob(statement, Int32(index)) {
return String(data: Data(bytes: valueData, count: Int(valueLength)), encoding: .utf8)
} else {
return nil
}
}
// read value at column index as blob that represented internally as a `ValueBoxKey`
func keyAt(_ index: Int) -> ValueBoxKey {
let valueLength = sqlite3_column_bytes(statement, Int32(index))
let valueData = sqlite3_column_blob(statement, Int32(index))
let key = ValueBoxKey(length: Int(valueLength))
memcpy(key.memory, valueData, Int(valueLength))
return key
}
// read value at column index as `int64` that represented internally as a `ValueBoxKey`
func int64KeyAt(_ index: Int) -> ValueBoxKey {
let value = sqlite3_column_int64(statement, Int32(index))
let key = ValueBoxKey(length: 8)
key.setInt64(0, value: value)
return key
}
// read value at column index as `int64`
func int64KeyValueAt(_ index: Int) -> Int64 {
return sqlite3_column_int64(statement, Int32(index))
}
// destory & finalize the memory
func destroy() {
sqlite3_finalize(statement)
}