@@ -58,20 +58,20 @@ public protocol SQLiteType {
5858 func dropIndex( in table: SQLTable , forColumn columnName: String ) throws
5959 func beginTransaction( ) throws
6060 func endTransaction( ) throws
61- func insertRow( sql: String , params: [ Any ] ? ) throws -> Int
62- func updateRow( sql: String , params: [ Any ] ? ) throws
63- func deleteRow( sql: String , params: [ Any ] ? ) throws
64- func deleteByID( in table: SQLTable , id: Int ) throws
65- func deleteAllRows( in table: SQLTable , vacuum: Bool , resetAutoincrement: Bool ) throws
61+ func insertRow( sql: String , params: [ Any ] ? ) throws -> ( Int , Int )
62+ func updateRow( sql: String , params: [ Any ] ? ) throws -> Int
63+ func deleteRow( sql: String , params: [ Any ] ? ) throws -> Int
64+ func deleteByID( in table: SQLTable , id: Int ) throws -> Int
65+ func deleteAllRows( in table: SQLTable , vacuum: Bool , resetAutoincrement: Bool ) throws -> Int
6666 func getRowCount( in table: SQLTable ) throws -> Int
6767 func getRowCountWithCondition( sql: String , params: [ Any ] ? ) throws -> Int
68- func getRow( from table: SQLTable , sql: String , params: [ Any ] ? ) throws -> [ SQLValues ]
69- func getAllRows( from table: SQLTable ) throws -> [ SQLValues ]
70- func getByID( from table: SQLTable , id: Int ) throws -> SQLValues
71- func getFirstRow( from table: SQLTable ) throws -> SQLValues
72- func getLastRow( from table: SQLTable ) throws -> SQLValues
68+ func getRow( from table: SQLTable , sql: String , params: [ Any ] ? ) throws -> [ SQLValues ] ?
69+ func getAllRows( from table: SQLTable ) throws -> [ SQLValues ] ?
70+ func getByID( from table: SQLTable , id: Int ) throws -> SQLValues ?
71+ func getFirstRow( from table: SQLTable ) throws -> SQLValues ?
72+ func getLastRow( from table: SQLTable ) throws -> SQLValues ?
7373 func vacuum( ) throws
74- func query( sql: String , params: [ Any ] ? ) throws
74+ func query( sql: String , params: [ Any ] ? ) throws -> Int
7575}
7676
7777open class SQLite : SQLiteType {
@@ -95,23 +95,23 @@ open class SQLite: SQLiteType {
9595 return id
9696 }
9797
98- /// Returns number of rows changed by last INSERT, UPDATE or DELETE statement
98+ /// - Returns: the number of rows changed by the most recently completed INSERT, DELETE or UPDATE statement
9999 public var changes : Int {
100100 var changes = 0
101101 queue. sync {
102102 changes = Int ( sqlite3_changes ( dbPointer) )
103103 }
104- log ( " number of changes: \( changes) " )
104+ log ( " changes: \( changes) " )
105105 return changes
106106 }
107107
108- /// Returns number of rows changed by INSERT, UPDATE or DELETE statements since the DB was opened
108+ /// - Returns: the number of rows changed by INSERT, DELETE or UPDATE statements since the current DB was opened
109109 public var totalChanges : Int {
110110 var totalChanges = 0
111111 queue. sync {
112112 totalChanges = Int ( sqlite3_total_changes ( dbPointer) )
113113 }
114- log ( " number of total changes: \( totalChanges) " )
114+ log ( " total changes: \( totalChanges) " )
115115 return totalChanges
116116 }
117117
@@ -156,7 +156,7 @@ open class SQLite: SQLiteType {
156156 do {
157157 try fileManager. removeItem ( atPath: path)
158158 } catch {
159- throw SQLiteError . Other ( " SQLite file has not been deleted " )
159+ throw SQLiteError . OpenDB ( " SQLite file has not been deleted " )
160160 }
161161 }
162162
@@ -223,7 +223,8 @@ open class SQLite: SQLiteType {
223223 }
224224 }
225225
226- private func operation( sql: String , params: [ Any ] ? = nil ) throws {
226+ @discardableResult
227+ private func operation( sql: String , params: [ Any ] ? = nil ) throws -> Int {
227228 try queue. sync {
228229 let sqlStatement = try prepareStatement ( sql: sql)
229230
@@ -236,6 +237,8 @@ open class SQLite: SQLiteType {
236237 guard sqlite3_step ( sqlStatement) == SQLITE_DONE else {
237238 throw SQLiteError . Step ( getErrorMessage ( dbPointer: dbPointer) )
238239 }
240+
241+ return Int ( sqlite3_changes ( dbPointer) )
239242 }
240243 }
241244
@@ -253,12 +256,10 @@ open class SQLite: SQLiteType {
253256 }
254257
255258 public func checkIfTableExists( _ table: SQLTable ) throws -> Bool {
256- if let count = try ? getRowCountWithCondition ( sql: " SELECT count(*) FROM sqlite_master WHERE type='table' AND name=' \( table. name) '; " ) {
257- let result = count == 1 ? true : false
258- log ( " successfully checked if table \( table. name) exists: \( result) " )
259- return result
260- }
261- throw SQLiteError . Other ( getErrorMessage ( dbPointer: dbPointer) )
259+ let count = try getRowCountWithCondition ( sql: " SELECT count(*) FROM sqlite_master WHERE type='table' AND name=' \( table. name) '; " )
260+ let result = count == 1 ? true : false
261+ log ( " successfully checked if table \( table. name) exists: \( result) " )
262+ return result
262263 }
263264
264265 public func dropTable( _ table: SQLTable , vacuum: Bool = true ) throws {
@@ -276,9 +277,9 @@ open class SQLite: SQLiteType {
276277
277278 var sql = " "
278279 if !unique {
279- sql = " CREATE INDEX \" \( indexName) \" ON \" \( table. name) \" ( \" \( columnName) \" "
280+ sql = " CREATE INDEX IF NOT EXISTS \" \( indexName) \" ON \" \( table. name) \" ( \" \( columnName) \" "
280281 } else {
281- sql = " CREATE UNIQUE INDEX \" \( indexName) ) \" ON \" \( table. name) \" ( \" \( columnName) \" "
282+ sql = " CREATE UNIQUE INDEX IF NOT EXISTS \" \( indexName) ) \" ON \" \( table. name) \" ( \" \( columnName) \" "
282283 }
283284
284285 switch order {
@@ -295,12 +296,10 @@ open class SQLite: SQLiteType {
295296 }
296297
297298 public func checkIfIndexExists( in table: SQLTable , indexName: String ) throws -> Bool {
298- if let count = try ? getRowCountWithCondition ( sql: " SELECT count(*) FROM sqlite_master WHERE type='index' AND tbl_name=' \( table. name) ' AND name=' \( indexName) '; " ) {
299- let result = count == 1 ? true : false
300- log ( " successfully checked if index \( indexName) exists: \( result) " )
301- return result
302- }
303- throw SQLiteError . Other ( getErrorMessage ( dbPointer: dbPointer) )
299+ let count = try getRowCountWithCondition ( sql: " SELECT count(*) FROM sqlite_master WHERE type='index' AND tbl_name=' \( table. name) ' AND name=' \( indexName) '; " )
300+ let result = count == 1 ? true : false
301+ log ( " successfully checked if index \( indexName) exists: \( result) " )
302+ return result
304303 }
305304
306305 public func dropIndex( in table: SQLTable , forColumn columnName: String ) throws {
@@ -323,50 +322,83 @@ open class SQLite: SQLiteType {
323322 }
324323
325324 /// Can be used to insert one or several rows depending on the SQL statement
326- /// - Returns: The id for the last inserted row
327- public func insertRow( sql: String , params: [ Any ] ? = nil ) throws -> Int {
325+ /// - Returns: (the number of inserted rows, id for the last inserted row)
326+ @discardableResult
327+ public func insertRow( sql: String , params: [ Any ] ? = nil ) throws -> ( Int , Int ) {
328328 guard sql. uppercased ( ) . trimmingCharacters ( in: . whitespaces) . hasPrefix ( " INSERT " ) else {
329329 throw SQLiteError . Statement ( " Invalid SQL statement " )
330330 }
331- try operation ( sql: sql, params: params)
332- log ( " successfully inserted row(s), sql: \( sql) " )
333- return self . lastInsertID
331+ let changes = try operation ( sql: sql, params: params)
332+ if changes > 0 {
333+ log ( " successfully inserted row(s), sql: \( sql) " )
334+ } else {
335+ log ( " no rows were inserted, sql: \( sql) " )
336+ }
337+ return ( changes, lastInsertID)
334338 }
335339
336340 /// Can be used to update one or several rows depending on the SQL statement
337- public func updateRow( sql: String , params: [ Any ] ? = nil ) throws {
341+ /// - Returns: the number of updated rows
342+ @discardableResult
343+ public func updateRow( sql: String , params: [ Any ] ? = nil ) throws -> Int {
338344 guard sql. uppercased ( ) . trimmingCharacters ( in: . whitespaces) . hasPrefix ( " UPDATE " ) else {
339345 throw SQLiteError . Statement ( " Invalid SQL statement " )
340346 }
341- try operation ( sql: sql, params: params)
342- log ( " successfully updated row(s), sql: \( sql) " )
347+ let changes = try operation ( sql: sql, params: params)
348+ if changes > 0 {
349+ log ( " successfully updated row(s), sql: \( sql) " )
350+ } else {
351+ log ( " no rows were updated, sql: \( sql) " )
352+ }
353+ return changes
343354 }
344355
345356 /// Can be used to delete one or several rows depending on the SQL statement
346- public func deleteRow( sql: String , params: [ Any ] ? = nil ) throws {
357+ /// - Returns: the number of deleted rows
358+ @discardableResult
359+ public func deleteRow( sql: String , params: [ Any ] ? = nil ) throws -> Int {
347360 guard sql. uppercased ( ) . trimmingCharacters ( in: . whitespaces) . hasPrefix ( " DELETE " ) else {
348361 throw SQLiteError . Statement ( " Invalid SQL statement " )
349362 }
350- try operation ( sql: sql, params: params)
351- log ( " successfully deleted row(s), sql: \( sql) " )
363+ let changes = try operation ( sql: sql, params: params)
364+ if changes > 0 {
365+ log ( " successfully deleted row(s), sql: \( sql) " )
366+ } else {
367+ log ( " no rows were deleted, sql: \( sql) " )
368+ }
369+ return changes
352370 }
353371
354- public func deleteByID( in table: SQLTable , id: Int ) throws {
372+ /// - Returns: 1 if the row with the specified id was deleted, otherwise returns 0
373+ @discardableResult
374+ public func deleteByID( in table: SQLTable , id: Int ) throws -> Int {
355375 let sql = " DELETE FROM \( table. name) WHERE \( table. primaryKey) = ?; "
356- try operation ( sql: sql, params: [ id] )
357- log ( " successfully deleted a row by id \( id) in \( table. name) " )
376+ let changes = try operation ( sql: sql, params: [ id] )
377+ if changes == 1 {
378+ log ( " successfully deleted the row with id \( id) in \( table. name) " )
379+ } else {
380+ log ( " row with id \( id) was not deleted in \( table. name) " )
381+ }
382+ return changes
358383 }
359384
360- public func deleteAllRows( in table: SQLTable , vacuum: Bool = true , resetAutoincrement: Bool = true ) throws {
385+ /// - Returns: the number of deleted rows
386+ @discardableResult
387+ public func deleteAllRows( in table: SQLTable , vacuum: Bool = true , resetAutoincrement: Bool = true ) throws -> Int {
361388 let sql = " DELETE FROM \( table. name) ; "
362- try operation ( sql: sql)
363- log ( " successfully deleted all rows in \( table. name) " )
389+ let changes = try operation ( sql: sql)
390+ if changes > 0 {
391+ log ( " successfully deleted all rows in \( table. name) " )
392+ } else {
393+ log ( " no rows were deleted in \( table. name) " )
394+ }
364395 if vacuum {
365396 try self . vacuum ( )
366397 }
367398 if resetAutoincrement {
368399 try self . resetAutoincrement ( in: table)
369400 }
401+ return changes
370402 }
371403
372404 public func getRowCount( in table: SQLTable ) throws -> Int {
@@ -409,7 +441,8 @@ open class SQLite: SQLiteType {
409441 }
410442
411443 /// Can be used to read one or several rows depending on the SQL statement
412- public func getRow( from table: SQLTable , sql: String , params: [ Any ] ? = nil ) throws -> [ SQLValues ] {
444+ /// - Returns: [SQLValues] if one or more rows were selected, otherwise returns nil
445+ public func getRow( from table: SQLTable , sql: String , params: [ Any ] ? = nil ) throws -> [ SQLValues ] ? {
413446 guard sql. uppercased ( ) . trimmingCharacters ( in: . whitespaces) . hasPrefix ( " SELECT " ) else {
414447 throw SQLiteError . Statement ( " Invalid SQL statement " )
415448 }
@@ -488,8 +521,13 @@ open class SQLite: SQLiteType {
488521 }
489522 }
490523
491- log ( " successfully read row(s), count: \( allRows. count) , sql: \( sql) " )
492- return allRows
524+ if allRows. count > 0 {
525+ log ( " successfully read row(s), count: \( allRows. count) , sql: \( sql) " )
526+ return allRows
527+ } else {
528+ log ( " no rows selected, sql: \( sql) " )
529+ return nil
530+ }
493531 }
494532
495533 /// Checks the structure of the result table and synchronizes it in SQLTableColums
@@ -516,44 +554,44 @@ open class SQLite: SQLiteType {
516554 return resultColumns
517555 }
518556
519- public func getAllRows( from table: SQLTable ) throws -> [ SQLValues ] {
557+ /// - Returns: [SQLValues] if one or more rows were selected, otherwise returns nil
558+ public func getAllRows( from table: SQLTable ) throws -> [ SQLValues ] ? {
520559 let sql = " SELECT * FROM \( table. name) ; "
521- let result = try getRow ( from: table, sql: sql)
522- log ( " successfully read all rows in \( table. name) , count: \( result. count) " )
523- return result
560+ if let result = try getRow ( from: table, sql: sql) {
561+ log ( " successfully read all rows in \( table. name) , count: \( result. count) " )
562+ return result
563+ }
564+ return nil
524565 }
525566
526- public func getByID( from table: SQLTable , id: Int ) throws -> SQLValues {
567+ /// - Returns: SQLValues if a row was selected, otherwise returns nil
568+ public func getByID( from table: SQLTable , id: Int ) throws -> SQLValues ? {
527569 let sql = " SELECT * FROM \( table. name) WHERE \( table. primaryKey) = ? LIMIT 1; "
528- let result = try getRow ( from: table, sql: sql, params: [ id] )
529- if result. count == 1 {
570+ if let result = try getRow ( from: table, sql: sql, params: [ id] ) {
530571 log ( " successfully read a row by id \( id) in \( table. name) " )
531572 return result [ 0 ]
532- } else {
533- throw SQLiteError . Other ( getErrorMessage ( dbPointer: dbPointer) )
534573 }
574+ return nil
535575 }
536576
537- public func getFirstRow( from table: SQLTable ) throws -> SQLValues {
577+ /// - Returns: SQLValues if a row was selected, otherwise returns nil
578+ public func getFirstRow( from table: SQLTable ) throws -> SQLValues ? {
538579 let sql = " SELECT * FROM \( table. name) WHERE \( table. primaryKey) = (SELECT MIN( \( table. primaryKey) ) FROM \( table. name) ); "
539- let result = try getRow ( from: table, sql: sql)
540- if result. count == 1 {
580+ if let result = try getRow ( from: table, sql: sql) {
541581 log ( " successfully read the first row in \( table. name) " )
542582 return result [ 0 ]
543- } else {
544- throw SQLiteError . Other ( getErrorMessage ( dbPointer: dbPointer) )
545583 }
584+ return nil
546585 }
547586
548- public func getLastRow( from table: SQLTable ) throws -> SQLValues {
587+ /// - Returns: SQLValues if a row was selected, otherwise returns nil
588+ public func getLastRow( from table: SQLTable ) throws -> SQLValues ? {
549589 let sql = " SELECT * FROM \( table. name) WHERE \( table. primaryKey) = (SELECT MAX( \( table. primaryKey) ) FROM \( table. name) ); "
550- let result = try getRow ( from: table, sql: sql)
551- if result. count == 1 {
590+ if let result = try getRow ( from: table, sql: sql) {
552591 log ( " successfully read the last row in \( table. name) " )
553592 return result [ 0 ]
554- } else {
555- throw SQLiteError . Other ( getErrorMessage ( dbPointer: dbPointer) )
556593 }
594+ return nil
557595 }
558596
559597 /// Repacks the DB to take advantage of deleted data
@@ -564,8 +602,11 @@ open class SQLite: SQLiteType {
564602 }
565603
566604 /// Any other query except reading
567- public func query( sql: String , params: [ Any ] ? = nil ) throws {
568- try operation ( sql: sql, params: params)
605+ /// - Returns: the number of rows changed
606+ @discardableResult
607+ public func query( sql: String , params: [ Any ] ? = nil ) throws -> Int {
608+ let changes = try operation ( sql: sql, params: params)
569609 log ( " successful query, sql: \( sql) " )
610+ return changes
570611 }
571612}
0 commit comments