@@ -32,21 +32,25 @@ public struct SQLite {
32
32
self . configuration = configuration
33
33
34
34
var handle : OpaquePointer ?
35
- try Self . checkError ( " Unable to open database at \( self . location ) " ) {
35
+ try Self . checkError ( {
36
36
sqlite3_open_v2 (
37
37
location. pathString,
38
38
& handle,
39
39
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX,
40
40
nil
41
41
)
42
- }
42
+ } ,
43
+ description: " Unable to open database at \( self . location) " )
43
44
44
45
guard let db = handle else {
45
46
throw StringError ( " Unable to open database at \( self . location) " )
46
47
}
47
48
self . db = db
48
- try Self . checkError ( " Unable to configure database " ) { sqlite3_extended_result_codes ( db, 1 ) }
49
- try Self . checkError ( " Unable to configure database " ) { sqlite3_busy_timeout ( db, self . configuration. busyTimeoutMilliseconds) }
49
+ try Self . checkError ( { sqlite3_extended_result_codes ( db, 1 ) } , description: " Unable to configure database " )
50
+ try Self . checkError ( { sqlite3_busy_timeout ( db, self . configuration. busyTimeoutMilliseconds) } , description: " Unable to configure database busy timeout " )
51
+ if let maxPageCount = self . configuration. maxPageCount {
52
+ try self . exec ( query: " PRAGMA max_page_count= \( maxPageCount) ; " )
53
+ }
50
54
}
51
55
52
56
@available ( * , deprecated, message: " use init(location:configuration) instead " )
@@ -90,9 +94,14 @@ public struct SQLite {
90
94
91
95
public struct Configuration {
92
96
public var busyTimeoutMilliseconds : Int32
97
+ public var maxSizeInBytes : Int ?
98
+
99
+ // https://www.sqlite.org/pgszchng2016.html
100
+ private let defaultPageSizeInBytes = 1024
93
101
94
102
public init ( ) {
95
103
self . busyTimeoutMilliseconds = 5000
104
+ self . maxSizeInBytes = . none
96
105
}
97
106
98
107
// FIXME: deprecated 12/2020, remove once clients migrated over
@@ -113,6 +122,19 @@ public struct SQLite {
113
122
self . busyTimeoutMilliseconds = newValue * 1000
114
123
}
115
124
}
125
+
126
+ public var maxSizeInMegabytes : Int ? {
127
+ get {
128
+ self . maxSizeInBytes. map { $0 / ( 1024 * 1024 ) }
129
+ }
130
+ set {
131
+ self . maxSizeInBytes = newValue. map { $0 * 1024 * 1024 }
132
+ }
133
+ }
134
+
135
+ public var maxPageCount : Int ? {
136
+ self . maxSizeInBytes. map { $0 / self . defaultPageSizeInBytes }
137
+ }
116
138
}
117
139
118
140
public enum Location {
@@ -179,7 +201,7 @@ public struct SQLite {
179
201
180
202
public init ( db: OpaquePointer , query: String ) throws {
181
203
var stmt : OpaquePointer ?
182
- try checkError { sqlite3_prepare_v2 ( db, query, - 1 , & stmt, nil ) }
204
+ try SQLite . checkError { sqlite3_prepare_v2 ( db, query, - 1 , & stmt, nil ) }
183
205
self . stmt = stmt!
184
206
}
185
207
@@ -227,17 +249,17 @@ public struct SQLite {
227
249
228
250
/// Reset the prepared statement.
229
251
public func reset( ) throws {
230
- try checkError { sqlite3_reset ( stmt) }
252
+ try SQLite . checkError { sqlite3_reset ( stmt) }
231
253
}
232
254
233
255
/// Clear bindings from the prepared statment.
234
256
public func clearBindings( ) throws {
235
- try checkError { sqlite3_clear_bindings ( stmt) }
257
+ try SQLite . checkError { sqlite3_clear_bindings ( stmt) }
236
258
}
237
259
238
260
/// Finalize the statement and free up resources.
239
261
public func finalize( ) throws {
240
- try checkError { sqlite3_finalize ( stmt) }
262
+ try SQLite . checkError { sqlite3_finalize ( stmt) }
241
263
}
242
264
}
243
265
@@ -248,17 +270,25 @@ public struct SQLite {
248
270
}
249
271
}
250
272
251
- private static func checkError( _ errorPrefix : String ? = nil , _ fn : ( ) -> Int32 ) throws {
273
+ private static func checkError( _ fn : ( ) -> Int32 , description prefix : String ? = . none ) throws {
252
274
let result = fn ( )
253
275
if result != SQLITE_OK {
254
- var error = " "
255
- if let errorPrefix = errorPrefix {
256
- error += errorPrefix + " : "
276
+ var description = String ( cString: sqlite3_errstr ( result) )
277
+ switch description. lowercased ( ) {
278
+ case " database or disk is full " :
279
+ throw Errors . databaseFull
280
+ default :
281
+ if let prefix = prefix {
282
+ description = " \( prefix) : \( description) "
283
+ }
284
+ throw StringError ( description)
257
285
}
258
- error += String ( cString: sqlite3_errstr ( result) )
259
- throw StringError ( error)
260
286
}
261
287
}
288
+
289
+ public enum Errors : Error {
290
+ case databaseFull
291
+ }
262
292
}
263
293
264
294
private func sqlite_callback(
0 commit comments