FMDatabaseQueue

@interface FMDatabaseQueue : NSObject

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.

Instead, use FMDatabaseQueue . Here’s how to use it:

First, make your queue.

FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:aPath];

Then use it like so:

[queue inDatabase:^(FMDatabase *db) {
    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:1]];
    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:2]];
    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:3]];

    FMResultSet *rs = [db executeQuery:@"select * from foo"];
    while ([rs next]) {
        //…
    }
}];

An easy way to wrap things up in a transaction can be done like this:

[queue inTransaction:^(FMDatabase *db, BOOL *rollback) {
    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:1]];
    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:2]];
    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:3]];

    // if (whoopsSomethingWrongHappened) {
    //     *rollback = YES;
    //     return;
    // }

    // etc…
    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:4]];
}];

FMDatabaseQueue will run the blocks on a serialized queue (hence the name of the class). So if you call FMDatabaseQueue ‘s methods from multiple threads at the same time, they will be executed in the order they are received. This way queries and updates won’t step on each other’s toes, and every one is happy.

Warning

Do not instantiate a single FMDatabase object and use it across multiple threads. Use FMDatabaseQueue instead.

Warning

The calls to FMDatabaseQueue ’s methods are blocking. So even though you are passing along blocks, they will not be run on another thread.

@sa FMDatabase

  • Path of database

    Declaration

    Objective-C

    @property (retain, nullable) NSString *path;

    Swift

    var path: String? { get set }
  • Open flags

    Declaration

    Objective-C

    @property (readonly) int openFlags;

    Swift

    var openFlags: Int32 { get }
  • Custom virtual file system name

    Declaration

    Objective-C

    @property (copy, nullable) NSString *vfsName;

    Swift

    var vfsName: String? { get set }

Initialization, opening, and closing of queue

  • Create queue using path.

    Declaration

    Objective-C

    + (nullable instancetype)databaseQueueWithPath:(NSString *_Nullable)aPath;

    Parameters

    aPath

    The file path of the database.

    Return Value

    The FMDatabaseQueue object. nil on error.

  • Create queue using file URL.

    Declaration

    Objective-C

    + (nullable instancetype)databaseQueueWithURL:(NSURL *_Nullable)url;

    Parameters

    url

    The file NSURL of the database.

    Return Value

    The FMDatabaseQueue object. nil on error.

  • Create queue using path and specified flags.

    Declaration

    Objective-C

    + (nullable instancetype)databaseQueueWithPath:(NSString *_Nullable)aPath
                                             flags:(int)openFlags;

    Parameters

    aPath

    The file path of the database.

    openFlags

    Flags passed to the openWithFlags method of the database.

    Return Value

    The FMDatabaseQueue object. nil on error.

  • Create queue using file URL and specified flags.

    Declaration

    Objective-C

    + (nullable instancetype)databaseQueueWithURL:(NSURL *_Nullable)url
                                            flags:(int)openFlags;

    Parameters

    url

    The file NSURL of the database.

    openFlags

    Flags passed to the openWithFlags method of the database.

    Return Value

    The FMDatabaseQueue object. nil on error.

  • Create queue using path.

    Declaration

    Objective-C

    - (nullable instancetype)initWithPath:(NSString *_Nullable)aPath;

    Swift

    init?(path aPath: String?)

    Parameters

    aPath

    The file path of the database.

    Return Value

    The FMDatabaseQueue object. nil on error.

  • Create queue using file URL.

    Declaration

    Objective-C

    - (nullable instancetype)initWithURL:(NSURL *_Nullable)url;

    Swift

    init?(url: URL?)

    Parameters

    url

    The file `NSURL of the database.

    Return Value

    The FMDatabaseQueue object. nil on error.

  • Create queue using path and specified flags.

    Declaration

    Objective-C

    - (nullable instancetype)initWithPath:(NSString *_Nullable)aPath
                                    flags:(int)openFlags;

    Swift

    init?(path aPath: String?, flags openFlags: Int32)

    Parameters

    aPath

    The file path of the database.

    openFlags

    Flags passed to the openWithFlags method of the database.

    Return Value

    The FMDatabaseQueue object. nil on error.

  • Create queue using file URL and specified flags.

    Declaration

    Objective-C

    - (nullable instancetype)initWithURL:(NSURL *_Nullable)url flags:(int)openFlags;

    Swift

    init?(url: URL?, flags openFlags: Int32)

    Parameters

    url

    The file path of the database.

    openFlags

    Flags passed to the openWithFlags method of the database.

    Return Value

    The FMDatabaseQueue object. nil on error.

  • Create queue using path and specified flags.

    Declaration

    Objective-C

    - (nullable instancetype)initWithPath:(NSString *_Nullable)aPath
                                    flags:(int)openFlags
                                      vfs:(NSString *_Nullable)vfsName;

    Swift

    init?(path aPath: String?, flags openFlags: Int32, vfs vfsName: String?)

    Parameters

    aPath

    The file path of the database.

    openFlags

    Flags passed to the openWithFlags method of the database

    vfsName

    The name of a custom virtual file system

    Return Value

    The FMDatabaseQueue object. nil on error.

  • Create queue using file URL and specified flags.

    Declaration

    Objective-C

    - (nullable instancetype)initWithURL:(NSURL *_Nullable)url
                                   flags:(int)openFlags
                                     vfs:(NSString *_Nullable)vfsName;

    Swift

    init?(url: URL?, flags openFlags: Int32, vfs vfsName: String?)

    Parameters

    url

    The file `NSURL of the database.

    openFlags

    Flags passed to the openWithFlags method of the database

    vfsName

    The name of a custom virtual file system

    Return Value

    The FMDatabaseQueue object. nil on error.

  • Returns the Class of ‘FMDatabase’ subclass, that will be used to instantiate database object.

    Subclasses can override this method to return specified Class of ‘FMDatabase’ subclass.

    Declaration

    Objective-C

    + (nonnull Class)databaseClass;

    Swift

    class func databaseClass() -> AnyClass

    Return Value

    The Class of ‘FMDatabase’ subclass, that will be used to instantiate database object.

  • Close database used by queue.

    Declaration

    Objective-C

    - (void)close;

    Swift

    func close()
  • Interupt pending database operation.

    Declaration

    Objective-C

    - (void)interrupt;

    Swift

    func interrupt()

Dispatching database operations to queue

  • Synchronously perform database operations on queue.

    Declaration

    Objective-C

    - (void)inDatabase:(nonnull void (^)(FMDatabase *_Nonnull))block;

    Swift

    func inDatabase(_ block: (FMDatabase) -> Void)

    Parameters

    block

    The code to be run on the queue of FMDatabaseQueue

  • Synchronously perform database operations on queue, using transactions.

    Warning

    Unlike SQLite’s BEGIN TRANSACTION, this method currently performs an exclusive transaction, not a deferred transaction. This behavior is likely to change in future versions of FMDB, whereby this method will likely eventually adopt standard SQLite behavior and perform deferred transactions. If you really need exclusive tranaction, it is recommended that you use inExclusiveTransaction, instead, not only to make your intent explicit, but also to future-proof your code.

    Declaration

    Objective-C

    - (void)inTransaction:(nonnull void (^)(FMDatabase *_Nonnull,
                                            BOOL *_Nonnull))block;

    Swift

    func inTransaction(_ block: (FMDatabase, UnsafeMutablePointer<ObjCBool>) -> Void)

    Parameters

    block

    The code to be run on the queue of FMDatabaseQueue

  • Synchronously perform database operations on queue, using deferred transactions.

    Declaration

    Objective-C

    - (void)inDeferredTransaction:(nonnull void (^)(FMDatabase *_Nonnull,
                                                    BOOL *_Nonnull))block;

    Swift

    func inDeferredTransaction(_ block: (FMDatabase, UnsafeMutablePointer<ObjCBool>) -> Void)

    Parameters

    block

    The code to be run on the queue of FMDatabaseQueue

  • Synchronously perform database operations on queue, using exclusive transactions.

    Declaration

    Objective-C

    - (void)inExclusiveTransaction:(nonnull void (^)(FMDatabase *_Nonnull,
                                                     BOOL *_Nonnull))block;

    Swift

    func inExclusiveTransaction(_ block: (FMDatabase, UnsafeMutablePointer<ObjCBool>) -> Void)

    Parameters

    block

    The code to be run on the queue of FMDatabaseQueue

  • Synchronously perform database operations on queue, using immediate transactions.

    Declaration

    Objective-C

    - (void)inImmediateTransaction:(nonnull void (^)(FMDatabase *_Nonnull,
                                                     BOOL *_Nonnull))block;

    Swift

    func inImmediateTransaction(_ block: (FMDatabase, UnsafeMutablePointer<ObjCBool>) -> Void)

    Parameters

    block

    The code to be run on the queue of FMDatabaseQueue

  • Synchronously perform database operations using save point.

    Declaration

    Objective-C

    - (NSError *_Nullable)inSavePoint:(nonnull void (^)(FMDatabase *_Nonnull,
                                                        BOOL *_Nonnull))block;

    Swift

    func inSavePoint(_ block: (FMDatabase, UnsafeMutablePointer<ObjCBool>) -> Void) -> Error?

    Parameters

    block

    The code to be run on the queue of FMDatabaseQueue

Checkpoint

  • Performs a WAL checkpoint

    Declaration

    Objective-C

    - (BOOL)checkpoint:(FMDBCheckpointMode)checkpointMode
                 error:(NSError *_Nullable *_Nullable)error;

    Swift

    func checkpoint(_ checkpointMode: FMDBCheckpointMode) throws

    Parameters

    checkpointMode

    The checkpoint mode for sqlite3_wal_checkpoint_v2

    error

    The NSError corresponding to the error, if any.

    Return Value

    YES on success, otherwise NO.

  • Performs a WAL checkpoint

    Declaration

    Objective-C

    - (BOOL)checkpoint:(FMDBCheckpointMode)checkpointMode
                  name:(NSString *_Nullable)name
                 error:(NSError *_Nullable *_Nullable)error;

    Swift

    func checkpoint(_ checkpointMode: FMDBCheckpointMode, name: String?) throws

    Parameters

    checkpointMode

    The checkpoint mode for sqlite3_wal_checkpoint_v2

    name

    The db name for sqlite3_wal_checkpoint_v2

    error

    The NSError corresponding to the error, if any.

    Return Value

    YES on success, otherwise NO.

  • Performs a WAL checkpoint

    Declaration

    Objective-C

    - (BOOL)checkpoint:(FMDBCheckpointMode)checkpointMode
                   name:(NSString *_Nullable)name
          logFrameCount:(int *_Nullable)logFrameCount
        checkpointCount:(int *_Nullable)checkpointCount
                  error:(NSError *_Nullable *_Nullable)error;

    Swift

    func checkpoint(_ checkpointMode: FMDBCheckpointMode, name: String?, logFrameCount: UnsafeMutablePointer<Int32>?, checkpointCount: UnsafeMutablePointer<Int32>?) throws

    Parameters

    checkpointMode

    The checkpoint mode for sqlite3_wal_checkpoint_v2

    name

    The db name for sqlite3_wal_checkpoint_v2

    error

    The NSError corresponding to the error, if any.

    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.

    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 Value

    YES on success, otherwise NO.