Browse Source

Merge pull request #1 from robertmryan/basher/transaction-checkpoint-support

Checkpoint tweaks
Ben Asher 8 years ago
parent
commit
3475cb2c53
4 changed files with 71 additions and 11 deletions
  1. 26 1
      src/fmdb/FMDatabase.h
  2. 10 2
      src/fmdb/FMDatabase.m
  3. 21 4
      src/fmdb/FMDatabaseQueue.h
  4. 14 4
      src/fmdb/FMDatabaseQueue.m

+ 26 - 1
src/fmdb/FMDatabase.h

@@ -41,6 +41,12 @@ NS_ASSUME_NONNULL_BEGIN
 
 typedef int(^FMDBExecuteStatementsCallbackBlock)(NSDictionary *resultsDictionary);
 
+typedef NS_ENUM(int, FMDBCheckpointMode) {
+    FMDBCheckpointModePassive  = 0, // SQLITE_CHECKPOINT_PASSIVE,
+    FMDBCheckpointModeFull     = 1, // SQLITE_CHECKPOINT_FULL,
+    FMDBCheckpointModeRestart  = 2, // SQLITE_CHECKPOINT_RESTART,
+    FMDBCheckpointModeTruncate = 3  // SQLITE_CHECKPOINT_TRUNCATE
+};
 
 /** A SQLite ([http://sqlite.org/](http://sqlite.org/)) Objective-C wrapper.
  
@@ -1005,13 +1011,32 @@ typedef int(^FMDBExecuteStatementsCallbackBlock)(NSDictionary *resultsDictionary
 ///-----------------
 
 /** Performs a WAL checkpoint
+ 
+ @param checkpointMode The checkpoint mode for sqlite3_wal_checkpoint_v2
+ @param error The NSError corresponding to the error, if any.
+ @return YES on success, otherwise NO.
+ */
+- (BOOL)checkpoint:(FMDBCheckpointMode)checkpointMode error:(NSError * _Nullable *)error;
+
+/** Performs a WAL checkpoint
+ 
+ @param checkpointMode The checkpoint mode for sqlite3_wal_checkpoint_v2
+ @param name The db name for sqlite3_wal_checkpoint_v2
+ @param error The NSError corresponding to the error, if any.
+ @return YES on success, otherwise NO.
+ */
+- (BOOL)checkpoint:(FMDBCheckpointMode)checkpointMode name:(NSString * _Nullable)name error:(NSError * _Nullable *)error;
 
+/** Performs a WAL checkpoint
+ 
  @param checkpointMode The checkpoint mode for sqlite3_wal_checkpoint_v2
  @param name The db name for sqlite3_wal_checkpoint_v2
  @param error The NSError corresponding to the error, if any.
+ @param logFrameCount If not NULL, then this is set to the total number of frames in the log file or to -1 if the checkpoint could not run because of an error or because the database is not in WAL mode.
+ @param checkpointCount If not NULL, then this is set to the total number of checkpointed frames in the log file (including any that were already checkpointed before the function was called) or to -1 if the checkpoint could not run due to an error or because the database is not in WAL mode.
  @return YES on success, otherwise NO.
  */
-- (BOOL)checkpoint:(int)checkpointMode dbName:(NSString *)name error:(NSError * _Nullable *)error;
+- (BOOL)checkpoint:(FMDBCheckpointMode)checkpointMode name:(NSString * _Nullable)name logFrameCount:(int * _Nullable)logFrameCount checkpointCount:(int * _Nullable)checkpointCount error:(NSError * _Nullable *)error;
 
 ///----------------------------
 /// @name SQLite library status

+ 10 - 2
src/fmdb/FMDatabase.m

@@ -1433,11 +1433,19 @@ - (NSError*)inSavePoint:(void (^)(BOOL *rollback))block {
 #endif
 }
 
-- (BOOL)checkpoint:(int)checkpointMode dbName:(NSString *)name error:(NSError * __autoreleasing *)error
+- (BOOL)checkpoint:(FMDBCheckpointMode)checkpointMode error:(NSError * __autoreleasing *)error {
+    return [self checkpoint:checkpointMode name:nil logFrameCount:NULL checkpointCount:NULL error:error];
+}
+
+- (BOOL)checkpoint:(FMDBCheckpointMode)checkpointMode name:(NSString *)name error:(NSError * __autoreleasing *)error {
+    return [self checkpoint:checkpointMode name:name logFrameCount:NULL checkpointCount:NULL error:error];
+}
+
+- (BOOL)checkpoint:(FMDBCheckpointMode)checkpointMode name:(NSString *)name logFrameCount:(int *)logFrameCount checkpointCount:(int *)checkpointCount error:(NSError * __autoreleasing *)error
 {
     const char* dbName = [name UTF8String];
 #if SQLITE_VERSION_NUMBER >= 3007006
-    int err = sqlite3_wal_checkpoint_v2(_db, dbName, checkpointMode, NULL, NULL);
+    int err = sqlite3_wal_checkpoint_v2(_db, dbName, checkpointMode, logFrameCount, checkpointCount);
 #else
     NSLog(@"sqlite3_wal_checkpoint_v2 unavailable before sqlite 3.7.6. Ignoring checkpoint mode: %d", mode);
     int err = sqlite3_wal_checkpoint(_db, dbName);

+ 21 - 4
src/fmdb/FMDatabaseQueue.h

@@ -7,11 +7,10 @@
 //
 
 #import <Foundation/Foundation.h>
+#import "FMDatabase.h"
 
 NS_ASSUME_NONNULL_BEGIN
 
-@class FMDatabase;
-
 /** To perform queries and updates on multiple threads, you'll want to use `FMDatabaseQueue`.
 
  Using a single instance of `<FMDatabase>` from multiple threads at once is a bad idea.  It has always been OK to make a `<FMDatabase>` object *per thread*.  Just don't share a single instance across threads, and definitely not across multiple threads at the same time.
@@ -241,15 +240,33 @@ NS_ASSUME_NONNULL_BEGIN
 /// @name Checkpoint
 ///-----------------
 
-/** Synchronously performs a WAL checkpoint
+/** Performs a WAL checkpoint
+ 
+ @param checkpointMode The checkpoint mode for sqlite3_wal_checkpoint_v2
+ @param error The NSError corresponding to the error, if any.
+ @return YES on success, otherwise NO.
+ */
+- (BOOL)checkpoint:(FMDBCheckpointMode)checkpointMode error:(NSError * _Nullable *)error;
 
+/** Performs a WAL checkpoint
+ 
  @param checkpointMode The checkpoint mode for sqlite3_wal_checkpoint_v2
  @param name The db name for sqlite3_wal_checkpoint_v2
  @param error The NSError corresponding to the error, if any.
  @return YES on success, otherwise NO.
  */
+- (BOOL)checkpoint:(FMDBCheckpointMode)checkpointMode name:(NSString * _Nullable)name error:(NSError * _Nullable *)error;
 
-- (BOOL)checkpoint:(int)checkpointMode dbName:(NSString *)name error:(NSError * _Nullable *)error;
+/** Performs a WAL checkpoint
+ 
+ @param checkpointMode The checkpoint mode for sqlite3_wal_checkpoint_v2
+ @param name The db name for sqlite3_wal_checkpoint_v2
+ @param error The NSError corresponding to the error, if any.
+ @param logFrameCount If not NULL, then this is set to the total number of frames in the log file or to -1 if the checkpoint could not run because of an error or because the database is not in WAL mode.
+ @param checkpointCount If not NULL, then this is set to the total number of checkpointed frames in the log file (including any that were already checkpointed before the function was called) or to -1 if the checkpoint could not run due to an error or because the database is not in WAL mode.
+ @return YES on success, otherwise NO.
+ */
+- (BOOL)checkpoint:(FMDBCheckpointMode)checkpointMode name:(NSString * _Nullable)name logFrameCount:(int * _Nullable)logFrameCount checkpointCount:(int * _Nullable)checkpointCount error:(NSError * _Nullable *)error;
 
 @end
 

+ 14 - 4
src/fmdb/FMDatabaseQueue.m

@@ -282,17 +282,27 @@ - (NSError*)inSavePoint:(void (^)(FMDatabase *db, BOOL *rollback))block {
 #endif
 }
 
-- (BOOL)checkpoint:(int)mode dbName:(NSString *)name error:(NSError * __autoreleasing *)error
+- (BOOL)checkpoint:(FMDBCheckpointMode)mode error:(NSError * __autoreleasing *)error
+{
+    return [self checkpoint:mode name:nil logFrameCount:NULL checkpointCount:NULL error:error];
+}
+
+- (BOOL)checkpoint:(FMDBCheckpointMode)mode name:(NSString *)name error:(NSError * __autoreleasing *)error
+{
+    return [self checkpoint:mode name:name logFrameCount:NULL checkpointCount:NULL error:error];
+}
+
+- (BOOL)checkpoint:(FMDBCheckpointMode)mode name:(NSString *)name logFrameCount:(int * _Nullable)logFrameCount checkpointCount:(int * _Nullable)checkpointCount error:(NSError * __autoreleasing _Nullable * _Nullable)error
 {
     __block BOOL result;
     __block NSError *blockError;
-
+    
     FMDBRetain(self);
     dispatch_sync(_queue, ^() {
-        result = [self.database checkpoint:mode dbName:name error:&blockError];
+        result = [self.database checkpoint:mode name:name logFrameCount:NULL checkpointCount:NULL error:&blockError];
     });
     FMDBRelease(self);
-
+    
     if (error) {
         *error = blockError;
     }