FMDatabaseQueue.h 7.56 KB
Newer Older
曹云霄's avatar
曹云霄 committed
1 2 3 4 5 6 7 8 9 10
//
//  FMDatabaseQueue.h
//  fmdb
//
//  Created by August Mueller on 6/22/11.
//  Copyright 2011 Flying Meat Inc. All rights reserved.
//

#import <Foundation/Foundation.h>

11 12
NS_ASSUME_NONNULL_BEGIN

曹云霄's avatar
曹云霄 committed
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
@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.

 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.

 ### See also

 - `<FMDatabase>`

 @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.

 */

65
@interface FMDatabaseQueue : NSObject
曹云霄's avatar
曹云霄 committed
66 67
/** Path of database */

68
@property (atomic, retain, nullable) NSString *path;
曹云霄's avatar
曹云霄 committed
69 70 71 72 73

/** Open flags */

@property (atomic, readonly) int openFlags;

74 75 76 77
/**  Custom virtual file system name */

@property (atomic, copy, nullable) NSString *vfsName;

曹云霄's avatar
曹云霄 committed
78 79 80 81 82 83 84 85 86 87 88
///----------------------------------------------------
/// @name Initialization, opening, and closing of queue
///----------------------------------------------------

/** Create queue using path.
 
 @param aPath The file path of the database.
 
 @return The `FMDatabaseQueue` object. `nil` on error.
 */

89 90 91 92 93 94 95 96 97 98
+ (instancetype)databaseQueueWithPath:(NSString * _Nullable)aPath;

/** Create queue using file URL.
 
 @param url The file `NSURL` of the database.
 
 @return The `FMDatabaseQueue` object. `nil` on error.
 */

+ (instancetype)databaseQueueWithURL:(NSURL * _Nullable)url;
曹云霄's avatar
曹云霄 committed
99 100 101 102

/** Create queue using path and specified flags.
 
 @param aPath The file path of the database.
103
 @param openFlags Flags passed to the openWithFlags method of the database.
曹云霄's avatar
曹云霄 committed
104 105 106
 
 @return The `FMDatabaseQueue` object. `nil` on error.
 */
107
+ (instancetype)databaseQueueWithPath:(NSString * _Nullable)aPath flags:(int)openFlags;
曹云霄's avatar
曹云霄 committed
108

109 110 111 112 113 114 115 116
/** Create queue using file URL and specified flags.
 
 @param url The file `NSURL` of the database.
 @param openFlags Flags passed to the openWithFlags method of the database.
 
 @return The `FMDatabaseQueue` object. `nil` on error.
 */
+ (instancetype)databaseQueueWithURL:(NSURL * _Nullable)url flags:(int)openFlags;
曹云霄's avatar
曹云霄 committed
117

118 119
/** Create queue using path.
 
曹云霄's avatar
曹云霄 committed
120
 @param aPath The file path of the database.
121 122 123
 
 @return The `FMDatabaseQueue` object. `nil` on error.
 */
曹云霄's avatar
曹云霄 committed
124

125 126 127 128 129 130
- (instancetype)initWithPath:(NSString * _Nullable)aPath;

/** Create queue using file URL.
 
 @param url The file `NSURL of the database.
 
曹云霄's avatar
曹云霄 committed
131 132 133
 @return The `FMDatabaseQueue` object. `nil` on error.
 */

134
- (instancetype)initWithURL:(NSURL * _Nullable)url;
曹云霄's avatar
曹云霄 committed
135 136 137 138

/** Create queue using path and specified flags.
 
 @param aPath The file path of the database.
139 140 141 142 143 144 145 146 147 148 149
 @param openFlags Flags passed to the openWithFlags method of the database.
 
 @return The `FMDatabaseQueue` object. `nil` on error.
 */

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

/** Create queue using file URL and specified flags.
 
 @param url The file path of the database.
 @param openFlags Flags passed to the openWithFlags method of the database.
曹云霄's avatar
曹云霄 committed
150 151 152 153
 
 @return The `FMDatabaseQueue` object. `nil` on error.
 */

154
- (instancetype)initWithURL:(NSURL * _Nullable)url flags:(int)openFlags;
曹云霄's avatar
曹云霄 committed
155 156 157 158 159 160 161 162 163 164

/** Create queue using path and specified flags.
 
 @param aPath The file path of the database.
 @param openFlags Flags passed to the openWithFlags method of the database
 @param vfsName The name of a custom virtual file system
 
 @return The `FMDatabaseQueue` object. `nil` on error.
 */

165 166 167 168 169 170 171 172 173 174 175 176
- (instancetype)initWithPath:(NSString * _Nullable)aPath flags:(int)openFlags vfs:(NSString * _Nullable)vfsName;

/** Create queue using file URL and specified flags.
 
 @param url The file `NSURL of the database.
 @param openFlags Flags passed to the openWithFlags method of the database
 @param vfsName The name of a custom virtual file system
 
 @return The `FMDatabaseQueue` object. `nil` on error.
 */

- (instancetype)initWithURL:(NSURL * _Nullable)url flags:(int)openFlags vfs:(NSString * _Nullable)vfsName;
曹云霄's avatar
曹云霄 committed
177 178 179 180 181 182 183 184 185 186 187 188 189 190

/** 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.
 
 @return The Class of 'FMDatabase' subclass, that will be used to instantiate database object.
 */

+ (Class)databaseClass;

/** Close database used by queue. */

- (void)close;

191 192 193 194
/** Interupt pending database operation. */

- (void)interrupt;

曹云霄's avatar
曹云霄 committed
195 196 197 198 199 200 201 202 203
///-----------------------------------------------
/// @name Dispatching database operations to queue
///-----------------------------------------------

/** Synchronously perform database operations on queue.
 
 @param block The code to be run on the queue of `FMDatabaseQueue`
 */

204
- (void)inDatabase:(__attribute__((noescape)) void (^)(FMDatabase *db))block;
曹云霄's avatar
曹云霄 committed
205 206 207 208 209 210

/** Synchronously perform database operations on queue, using transactions.

 @param block The code to be run on the queue of `FMDatabaseQueue`
 */

211
- (void)inTransaction:(__attribute__((noescape)) void (^)(FMDatabase *db, BOOL *rollback))block;
曹云霄's avatar
曹云霄 committed
212 213 214 215 216 217

/** Synchronously perform database operations on queue, using deferred transactions.

 @param block The code to be run on the queue of `FMDatabaseQueue`
 */

218
- (void)inDeferredTransaction:(__attribute__((noescape)) void (^)(FMDatabase *db, BOOL *rollback))block;
曹云霄's avatar
曹云霄 committed
219 220 221 222 223 224 225 226 227 228 229 230

///-----------------------------------------------
/// @name Dispatching database operations to queue
///-----------------------------------------------

/** Synchronously perform database operations using save point.

 @param block The code to be run on the queue of `FMDatabaseQueue`
 */

// NOTE: you can not nest these, since calling it will pull another database out of the pool and you'll get a deadlock.
// If you need to nest, use FMDatabase's startSavePointWithName:error: instead.
231
- (NSError * _Nullable)inSavePoint:(__attribute__((noescape)) void (^)(FMDatabase *db, BOOL *rollback))block;
曹云霄's avatar
曹云霄 committed
232 233 234

@end

235
NS_ASSUME_NONNULL_END