@@ -32,21 +32,25 @@ public struct SQLite {
3232 self . configuration = configuration
3333
3434 var handle : OpaquePointer ?
35- try Self . checkError ( " Unable to open database at \( self . location ) " ) {
35+ try Self . checkError ( {
3636 sqlite3_open_v2 (
3737 location. pathString,
3838 & handle,
3939 SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX,
4040 nil
4141 )
42- }
42+ } ,
43+ description: " Unable to open database at \( self . location) " )
4344
4445 guard let db = handle else {
4546 throw StringError ( " Unable to open database at \( self . location) " )
4647 }
4748 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+ }
5054 }
5155
5256 @available ( * , deprecated, message: " use init(location:configuration) instead " )
@@ -90,9 +94,14 @@ public struct SQLite {
9094
9195 public struct Configuration {
9296 public var busyTimeoutMilliseconds : Int32
97+ public var maxSizeInBytes : Int ?
98+
99+ // https://www.sqlite.org/pgszchng2016.html
100+ private let defaultPageSizeInBytes = 1024
93101
94102 public init ( ) {
95103 self . busyTimeoutMilliseconds = 5000
104+ self . maxSizeInBytes = . none
96105 }
97106
98107 // FIXME: deprecated 12/2020, remove once clients migrated over
@@ -113,6 +122,19 @@ public struct SQLite {
113122 self . busyTimeoutMilliseconds = newValue * 1000
114123 }
115124 }
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+ }
116138 }
117139
118140 public enum Location {
@@ -179,7 +201,7 @@ public struct SQLite {
179201
180202 public init ( db: OpaquePointer , query: String ) throws {
181203 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 ) }
183205 self . stmt = stmt!
184206 }
185207
@@ -227,17 +249,17 @@ public struct SQLite {
227249
228250 /// Reset the prepared statement.
229251 public func reset( ) throws {
230- try checkError { sqlite3_reset ( stmt) }
252+ try SQLite . checkError { sqlite3_reset ( stmt) }
231253 }
232254
233255 /// Clear bindings from the prepared statment.
234256 public func clearBindings( ) throws {
235- try checkError { sqlite3_clear_bindings ( stmt) }
257+ try SQLite . checkError { sqlite3_clear_bindings ( stmt) }
236258 }
237259
238260 /// Finalize the statement and free up resources.
239261 public func finalize( ) throws {
240- try checkError { sqlite3_finalize ( stmt) }
262+ try SQLite . checkError { sqlite3_finalize ( stmt) }
241263 }
242264 }
243265
@@ -248,17 +270,25 @@ public struct SQLite {
248270 }
249271 }
250272
251- private static func checkError( _ errorPrefix : String ? = nil , _ fn : ( ) -> Int32 ) throws {
273+ private static func checkError( _ fn : ( ) -> Int32 , description prefix : String ? = . none ) throws {
252274 let result = fn ( )
253275 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)
257285 }
258- error += String ( cString: sqlite3_errstr ( result) )
259- throw StringError ( error)
260286 }
261287 }
288+
289+ public enum Errors : Error {
290+ case databaseFull
291+ }
262292}
263293
264294private func sqlite_callback(
0 commit comments