Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Got rid of the pop and pull from the database pool- too dangerous! Up…

…dated readme and tests.
commit ab3b78cf02fea1092128d51e0607cf51075be1fa 1 parent 58c3e70
@ccgus authored
View
6 CHANGES_AND_TODO_LIST.txt
@@ -3,6 +3,12 @@ Zip, nada, zilch. Got any ideas?
If you would like to contribute some code- awesome! I just ask that you make it conform to the coding conventions already set in here, and to add a couple of tests for your new code to fmdb.m. And of course, the code should be of general use to more than just a couple of folks. Send your patches to gus@flyingmeat.com.
+2012.02.10:
+ Changed up FMDatabasePool so that you can't "pop" it from a pool anymore. I just consider this too risky- use the block based functions instead.
+ Also provided a good reason in main.m for why you should use FMDatabaseQueue instead. Search for "ONLY_USE_THE_POOL_IF_YOU_ARE_DOING_READS".
+ I consider this branch 2.0 at this point- I'll let it bake for a couple of days, then push it to the main repo.
+
+
2012.01.06:
Added a new method to FMDatabase to make custom functions out of a block:
- (void)makeFunctionNamed:(NSString*)name maximumArguments:(int)count withBlock:(void (^)(sqlite3_context *context, int argc, sqlite3_value **argv))block
View
4 README.markdown
@@ -174,6 +174,10 @@ An easy way to wrap things up in a transaction can be done like this:
FMDatabaseQueue will make a serialized GCD queue in the background and execute the blocks you pass to the GCD queue. This means if you call your FMDatabaseQueue's methods from multiple threads at the same time GDC will execute them in the order they are received. This means queries and updates won't step on each other's toes, and every one is happy.
+## Making custom sqlite functions, based on blocks.
+
+You can do this! For an example, look for "makeFunctionNamed:" in main.m
+
## History
The history and changes are availbe on its [GitHub page](https://github.com/ccgus/fmdb) and are summarized in the "CHANGES_AND_TODO_LIST.txt" file.
View
2  fmdb.xcodeproj/project.pbxproj
@@ -273,6 +273,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
+ CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_OBJCPP_ARC_ABI = YES;
COPY_PHASE_STRIP = NO;
GCC_DYNAMIC_NO_PIC = NO;
@@ -289,6 +290,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+ CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_OBJCPP_ARC_ABI = YES;
GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
GCC_MODEL_TUNING = G5;
View
13 src/FMDatabase.h
@@ -2,7 +2,7 @@
#import "sqlite3.h"
#import "FMResultSet.h"
#import "FMDatabasePool.h"
-
+/*
#ifndef MAC_OS_X_VERSION_10_7
#define MAC_OS_X_VERSION_10_7 1070
#endif
@@ -10,7 +10,7 @@
#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_7
#define FMDB_USE_WEAK_POOL 1
#endif
-
+*/
#if ! __has_feature(objc_arc)
#define FMDBAutorelease(__v) ([__v autorelease]);
#define FMDBReturnAutoreleased FMDBAutorelease
@@ -47,7 +47,7 @@
NSMutableDictionary *_cachedStatements;
NSMutableSet *_openResultSets;
NSMutableSet *_openFunctions;
-
+ /*
#ifdef FMDB_USE_WEAK_POOL
__weak FMDatabasePool *_poolAccessViaMethodOnly;
#else
@@ -57,6 +57,7 @@
NSInteger _poolPopCount;
FMDatabasePool *pool;
+ */
}
@@ -128,12 +129,6 @@
- (int)changes;
-- (FMDatabase*)popFromPool;
-- (void)pushToPool;
-
-- (FMDatabasePool *)pool;
-- (void)setPool:(FMDatabasePool *)value;
-
- (void)makeFunctionNamed:(NSString*)name maximumArguments:(int)count withBlock:(void (^)(sqlite3_context *context, int argc, sqlite3_value **argv))block;
@end
View
89 src/FMDatabase.m
@@ -4,7 +4,6 @@
@interface FMDatabase ()
-- (void)checkPoolPushBack;
- (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray*)arrayArgs orDictionary:(NSDictionary *)dictionaryArgs orVAList:(va_list)args;
- (BOOL)executeUpdate:(NSString*)sql error:(NSError**)outErr withArgumentsInArray:(NSArray*)arrayArgs orDictionary:(NSDictionary *)dictionaryArgs orVAList:(va_list)args;
@end
@@ -60,8 +59,6 @@ - (void)dealloc {
FMDBRelease(_databasePath);
FMDBRelease(_openFunctions);
- [self setPool:0x00];
-
#if ! __has_feature(objc_arc)
[super dealloc];
#endif
@@ -181,8 +178,6 @@ - (void)resultSetDidClose:(FMResultSet *)resultSet {
NSValue *setValue = [NSValue valueWithNonretainedObject:resultSet];
[_openResultSets removeObject:setValue];
-
- [self checkPoolPushBack];
}
- (FMStatement*)cachedStatementForQuery:(NSString*)query {
@@ -489,14 +484,11 @@ - (FMResultSet *)executeQuery:(NSString *)sql withParameterDictionary:(NSDiction
- (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray*)arrayArgs orDictionary:(NSDictionary *)dictionaryArgs orVAList:(va_list)args {
if (![self databaseExists]) {
- //Pushing the FMDatabase instance back to the pool if error occurs
- [self checkPoolPushBack];
return 0x00;
}
if (_isExecutingStatement) {
[self warnInUse];
- [self checkPoolPushBack];
return 0x00;
}
@@ -533,7 +525,6 @@ - (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray*)arr
NSLog(@"Database busy");
sqlite3_finalize(pStmt);
_isExecutingStatement = NO;
- [self checkPoolPushBack];
return nil;
}
}
@@ -553,7 +544,6 @@ - (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray*)arr
sqlite3_finalize(pStmt);
_isExecutingStatement = NO;
- [self checkPoolPushBack];
return nil;
}
}
@@ -614,7 +604,6 @@ - (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray*)arr
NSLog(@"Error: the bind count is not correct for the # of variables (executeQuery)");
sqlite3_finalize(pStmt);
_isExecutingStatement = NO;
- [self checkPoolPushBack];
return nil;
}
@@ -675,12 +664,10 @@ - (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray *)ar
- (BOOL)executeUpdate:(NSString*)sql error:(NSError**)outErr withArgumentsInArray:(NSArray*)arrayArgs orDictionary:(NSDictionary *)dictionaryArgs orVAList:(va_list)args {
if (![self databaseExists]) {
- [self checkPoolPushBack];
return NO;
}
if (_isExecutingStatement) {
- [self checkPoolPushBack];
[self warnInUse];
return NO;
}
@@ -717,7 +704,6 @@ - (BOOL)executeUpdate:(NSString*)sql error:(NSError**)outErr withArgumentsInArra
NSLog(@"Database busy");
sqlite3_finalize(pStmt);
_isExecutingStatement = NO;
- [self checkPoolPushBack];
return NO;
}
}
@@ -742,7 +728,6 @@ - (BOOL)executeUpdate:(NSString*)sql error:(NSError**)outErr withArgumentsInArra
}
_isExecutingStatement = NO;
- [self checkPoolPushBack];
return NO;
}
}
@@ -804,7 +789,6 @@ - (BOOL)executeUpdate:(NSString*)sql error:(NSError**)outErr withArgumentsInArra
NSLog(@"Error: the bind count is not correct for the # of variables (%@) (executeUpdate)", sql);
sqlite3_finalize(pStmt);
_isExecutingStatement = NO;
- [self checkPoolPushBack];
return NO;
}
@@ -888,7 +872,6 @@ - (BOOL)executeUpdate:(NSString*)sql error:(NSError**)outErr withArgumentsInArra
}
_isExecutingStatement = NO;
- [self checkPoolPushBack];
return (rc == SQLITE_DONE || rc == SQLITE_OK);
}
@@ -938,8 +921,6 @@ - (BOOL)update:(NSString*)sql withErrorAndBindings:(NSError**)outErr, ... {
- (BOOL)rollback {
BOOL b = [self executeUpdate:@"rollback transaction"];
- [self pushToPool];
-
if (b) {
_inTransaction = NO;
}
@@ -950,8 +931,6 @@ - (BOOL)rollback {
- (BOOL)commit {
BOOL b = [self executeUpdate:@"commit transaction"];
- [self pushToPool];
-
if (b) {
_inTransaction = NO;
}
@@ -961,10 +940,6 @@ - (BOOL)commit {
- (BOOL)beginDeferredTransaction {
- if ([self pool]) {
- [self popFromPool];
- }
-
BOOL b = [self executeUpdate:@"begin deferred transaction"];
if (b) {
_inTransaction = YES;
@@ -975,10 +950,6 @@ - (BOOL)beginDeferredTransaction {
- (BOOL)beginTransaction {
- if ([self pool]) {
- [self popFromPool];
- }
-
BOOL b = [self executeUpdate:@"begin exclusive transaction"];
if (b) {
_inTransaction = YES;
@@ -999,10 +970,6 @@ - (BOOL)startSavePointWithName:(NSString*)name error:(NSError**)outErr {
NSParameterAssert(name);
- if ([self pool]) {
- [self popFromPool];
- }
-
if (![self executeUpdate:[NSString stringWithFormat:@"savepoint '%@';", name]]) {
if (*outErr) {
@@ -1025,10 +992,6 @@ - (BOOL)releaseSavePointWithName:(NSString*)name error:(NSError**)outErr {
*outErr = [self lastError];
}
- if ([self pool]) {
- [self pushToPool];
- }
-
return worked;
}
@@ -1042,10 +1005,6 @@ - (BOOL)rollbackToSavePointWithName:(NSString*)name error:(NSError**)outErr {
*outErr = [self lastError];
}
- if ([self pool]) {
- [self pushToPool];
- }
-
return worked;
}
@@ -1094,54 +1053,6 @@ - (void)setShouldCacheStatements:(BOOL)value {
}
}
-
-- (FMDatabase*)popFromPool {
-
- if (![self pool]) {
- NSLog(@"No FMDatabasePool in place for %@", self);
- return 0x00;
- }
-
- _poolPopCount++;
-
- return self;
-}
-
-- (void)pushToPool {
- _poolPopCount--;
-
- [self checkPoolPushBack];
-}
-
-- (void)checkPoolPushBack {
-
- if (_poolPopCount <= 0) {
- [[self pool] pushDatabaseBackInPool:self];
-
- if (_poolPopCount < 0) {
- _poolPopCount = 0;
- }
- }
-}
-
-// #if __has_feature(objc_arc_weak)
-
-- (FMDatabasePool *)pool {
-#if FMDB_USE_WEAK_POOL && (!__has_feature(objc_arc_weak))
- return objc_loadWeak(&_poolAccessViaMethodOnly);
-#else
- return _poolAccessViaMethodOnly;
-#endif
-}
-
-- (void)setPool:(FMDatabasePool *)value {
-#if FMDB_USE_WEAK_POOL && (!__has_feature(objc_arc_weak))
- objc_storeWeak(&_poolAccessViaMethodOnly, value);
-#else
- _poolAccessViaMethodOnly = value;
-#endif
-}
-
void FMDBBlockSQLiteCallBackFunction(sqlite3_context *context, int argc, sqlite3_value **argv);
void FMDBBlockSQLiteCallBackFunction(sqlite3_context *context, int argc, sqlite3_value **argv) {
#if ! __has_feature(objc_arc)
View
5 src/FMDatabasePool.h
@@ -15,7 +15,7 @@
Before using FMDatabasePool, please consider using FMDatabaseQueue instead.
I'm also not 100% sold on this interface. So if you use FMDatabasePool, things like
-[[pool db] popFromPool] might go away.
+[[pool db] popFromPool] might go away. In fact, I'm pretty darn sure they will.
If you really really really know what you're doing and FMDatabasePool is what
you really really need, OK you can use it. But just be careful not to deadlock!
@@ -122,9 +122,6 @@ If you check out a database, but never execute a statement or query, **you need
+ (id)databasePoolWithPath:(NSString*)aPath;
- (id)initWithPath:(NSString*)aPath;
-- (void)pushDatabaseBackInPool:(FMDatabase*)db;
-- (FMDatabase*)db;
-
- (NSUInteger)countOfCheckedInDatabases;
- (NSUInteger)countOfCheckedOutDatabases;
- (NSUInteger)countOfOpenDatabases;
View
25 src/FMDatabasePool.m
@@ -9,6 +9,14 @@
#import "FMDatabasePool.h"
#import "FMDatabase.h"
+@interface FMDatabasePool()
+
+- (void)pushDatabaseBackInPool:(FMDatabase*)db;
+- (FMDatabase*)db;
+
+@end
+
+
@implementation FMDatabasePool
@synthesize path=_path;
@synthesize delegate=_delegate;
@@ -56,6 +64,10 @@ - (void)executeLocked:(void (^)(void))aBlock {
- (void)pushDatabaseBackInPool:(FMDatabase*)db {
+ if (!db) { // db can be null if we set an upper bound on the # of databases to create.
+ return;
+ }
+
[self executeLocked:^() {
if ([_databaseInPool containsObject:db]) {
@@ -65,8 +77,6 @@ - (void)pushDatabaseBackInPool:(FMDatabase*)db {
[_databaseInPool addObject:db];
[_databaseOutPool removeObject:db];
- [db setPool:0x00];
-
}];
}
@@ -112,8 +122,6 @@ - (FMDatabase*)db {
NSLog(@"Could not open up the database at path %@", _path);
db = 0x00;
}
-
- [db setPool:self];
}];
return db;
@@ -160,11 +168,11 @@ - (void)releaseAllDatabases {
- (void)inDatabase:(void (^)(FMDatabase *db))block {
- FMDatabase *db = [[self db] popFromPool];
+ FMDatabase *db = [self db];
block(db);
- [db pushToPool];
+ [self pushDatabaseBackInPool:db];
}
- (void)beginTransaction:(BOOL)useDeferred withBlock:(void (^)(FMDatabase *db, BOOL *rollback))block {
@@ -189,6 +197,8 @@ - (void)beginTransaction:(BOOL)useDeferred withBlock:(void (^)(FMDatabase *db, B
else {
[db commit];
}
+
+ [self pushDatabaseBackInPool:db];
}
- (void)inDeferredTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block {
@@ -212,6 +222,7 @@ - (NSError*)inSavePoint:(void (^)(FMDatabase *db, BOOL *rollback))block {
NSError *err = 0x00;
if (![db startSavePointWithName:name error:&err]) {
+ [self pushDatabaseBackInPool:db];
return err;
}
@@ -224,6 +235,8 @@ - (NSError*)inSavePoint:(void (^)(FMDatabase *db, BOOL *rollback))block {
[db releaseSavePointWithName:name error:&err];
}
+ [self pushDatabaseBackInPool:db];
+
return err;
}
#endif
View
350 src/fmdb.m
@@ -624,8 +624,16 @@ int main (int argc, const char * argv[]) {
[queue inDatabase:^(FMDatabase *db) {
+
+ [db executeUpdate:@"create table qfoo (foo text)"];
+ [db executeUpdate:@"insert into qfoo values ('hi')"];
+ [db executeUpdate:@"insert into qfoo values ('hello')"];
+ [db executeUpdate:@"insert into qfoo values ('not')"];
+
+
+
int count = 0;
- FMResultSet *rsl = [db executeQuery:@"select * from likefoo where foo like 'h%'"];
+ FMResultSet *rsl = [db executeQuery:@"select * from qfoo where foo like 'h%'"];
while ([rsl next]) {
count++;
}
@@ -633,7 +641,7 @@ int main (int argc, const char * argv[]) {
FMDBQuickCheck(count == 2);
count = 0;
- rsl = [db executeQuery:@"select * from likefoo where foo like ?", @"h%"];
+ rsl = [db executeQuery:@"select * from qfoo where foo like ?", @"h%"];
while ([rsl next]) {
count++;
}
@@ -659,7 +667,7 @@ int main (int argc, const char * argv[]) {
[queue inTransaction:^(FMDatabase *db, BOOL *rollback) {
NSLog(@"Starting query %ld", nby);
- FMResultSet *rsl = [db executeQuery:@"select * from likefoo where foo like 'h%'"];
+ FMResultSet *rsl = [db executeQuery:@"select * from qfoo where foo like 'h%'"];
while ([rsl next]) {
;// whatever.
}
@@ -675,9 +683,9 @@ int main (int argc, const char * argv[]) {
[queue inTransaction:^(FMDatabase *db, BOOL *rollback) {
NSLog(@"Starting update %ld", nby);
- [db executeUpdate:@"insert into likefoo values ('1')"];
- [db executeUpdate:@"insert into likefoo values ('2')"];
- [db executeUpdate:@"insert into likefoo values ('3')"];
+ [db executeUpdate:@"insert into qfoo values ('1')"];
+ [db executeUpdate:@"insert into qfoo values ('2')"];
+ [db executeUpdate:@"insert into qfoo values ('3')"];
NSLog(@"Ending update %ld", nby);
}];
});
@@ -685,7 +693,7 @@ int main (int argc, const char * argv[]) {
[queue close];
[queue inDatabase:^(FMDatabase *db) {
- FMDBQuickCheck([db executeUpdate:@"insert into likefoo values ('1')"]);
+ FMDBQuickCheck([db executeUpdate:@"insert into qfoo values ('1')"]);
}];
}
@@ -734,6 +742,52 @@ int main (int argc, const char * argv[]) {
}];
}
+ // hey, let's make a custom function!
+
+ [queue inDatabase:^(FMDatabase *db) {
+
+ [db executeUpdate:@"create table ftest (foo text)"];
+ [db executeUpdate:@"insert into ftest values ('hello')"];
+ [db executeUpdate:@"insert into ftest values ('hi')"];
+ [db executeUpdate:@"insert into ftest values ('not h!')"];
+ [db executeUpdate:@"insert into ftest values ('definitely not h!')"];
+
+ [db makeFunctionNamed:@"StringStartsWithH" maximumArguments:1 withBlock:^(sqlite3_context *context, int argc, sqlite3_value **argv) {
+ if (sqlite3_value_type(argv[0]) == SQLITE_TEXT) {
+
+ @autoreleasepool {
+
+ const char *c = (const char *)sqlite3_value_text(argv[0]);
+
+ NSString *s = [NSString stringWithUTF8String:c];
+
+ sqlite3_result_int(context, [s hasPrefix:@"h"]);
+ }
+ }
+ else {
+ NSLog(@"Unknown formart for StringStartsWithH (%d) %s:%d", sqlite3_value_type(argv[0]), __FUNCTION__, __LINE__);
+ sqlite3_result_null(context);
+ }
+ }];
+
+ int rowCount = 0;
+ FMResultSet *rs = [db executeQuery:@"select * from ftest where StringStartsWithH(foo)"];
+ while ([rs next]) {
+ rowCount++;
+
+ NSLog(@"Does %@ start with 'h'?", [rs stringForColumnIndex:0]);
+
+ }
+ FMDBQuickCheck(rowCount == 2);
+
+
+
+
+
+
+ }];
+
+
NSLog(@"That was version %@ of sqlite", [FMDatabase sqliteLibVersion]);
@@ -753,36 +807,40 @@ void testPool(NSString *dbPath) {
FMDBQuickCheck([dbPool countOfOpenDatabases] == 0);
- FMDatabase *db = [dbPool db];
-
- FMDBQuickCheck([dbPool countOfOpenDatabases] == 1);
-
- FMDBQuickCheck([db tableExists:@"t4"]);
-
- FMDBQuickCheck(![db pool]);
+ __block FMDatabase *db1;
- FMDatabase *db2 = [dbPool db];
+ [dbPool inDatabase:^(FMDatabase *db) {
+
+
+
+ FMDBQuickCheck([dbPool countOfOpenDatabases] == 1);
+
+ FMDBQuickCheck([db tableExists:@"t4"]);
+
+ db1 = db;
+
+ }];
- FMDBQuickCheck(db2 == db);
+ [dbPool inDatabase:^(FMDatabase *db) {
+ FMDBQuickCheck(db1 == db);
+
+ [dbPool inDatabase:^(FMDatabase *db2) {
+ FMDBQuickCheck(db2 != db);
+ }];
+
+ }];
- db = [dbPool db];
- FMDBQuickCheck(db2 != db);
- FMDBQuickCheck([db pool]);
- FMDBQuickCheck([db2 pool]);
FMDBQuickCheck([dbPool countOfOpenDatabases] == 2);
- FMDBQuickCheck([db executeUpdate:@"create table easy (a text)"]);
- FMDBQuickCheck([db2 executeUpdate:@"create table easy2 (a text)"]);
-
- db = [dbPool db];
- FMDBQuickCheck([dbPool countOfOpenDatabases] == 2);
- [db pushToPool];
+ [dbPool inDatabase:^(FMDatabase *db) {
+ [db executeUpdate:@"create table easy (a text)"];
+ [db executeUpdate:@"create table easy2 (a text)"];
+
+ }];
- [[dbPool db] pushToPool];
- [[dbPool db] pushToPool];
FMDBQuickCheck([dbPool countOfOpenDatabases] == 2);
@@ -818,92 +876,43 @@ void testPool(NSString *dbPath) {
{
- db = [[dbPool db] popFromPool];
-
- [db executeUpdate:@"insert into easy values (?)", [NSNumber numberWithInt:1]];
- [db executeUpdate:@"insert into easy values (?)", [NSNumber numberWithInt:2]];
- [db executeUpdate:@"insert into easy values (?)", [NSNumber numberWithInt:3]];
-
- FMDBQuickCheck([dbPool countOfCheckedInDatabases] == 0);
- FMDBQuickCheck([dbPool countOfCheckedOutDatabases] == 1);
-
- [db pushToPool];
- }
-
-
- {
- // double pop!
- db = [[dbPool db] popFromPool];
-
- [db popFromPool];
- [db executeUpdate:@"insert into easy values (?)", [NSNumber numberWithInt:1]];
-
- FMDBQuickCheck([dbPool countOfCheckedInDatabases] == 0);
- FMDBQuickCheck([dbPool countOfCheckedOutDatabases] == 1);
-
- [db pushToPool];
- [db pushToPool];
+ [dbPool inDatabase:^(FMDatabase *db) {
- FMDBQuickCheck([dbPool countOfCheckedInDatabases] == 1);
- FMDBQuickCheck([dbPool countOfCheckedOutDatabases] == 0);
+ [db executeUpdate:@"insert into easy values (?)", [NSNumber numberWithInt:1]];
+ [db executeUpdate:@"insert into easy values (?)", [NSNumber numberWithInt:2]];
+ [db executeUpdate:@"insert into easy values (?)", [NSNumber numberWithInt:3]];
+
+ FMDBQuickCheck([dbPool countOfCheckedInDatabases] == 0);
+ FMDBQuickCheck([dbPool countOfCheckedOutDatabases] == 1);
+ }];
}
- [[dbPool db] pushToPool];
FMDBQuickCheck([dbPool countOfOpenDatabases] == 1);
[dbPool setMaximumNumberOfDatabasesToCreate:2];
- FMDatabase *adb = [dbPool db];
- FMDatabase *bbd = [dbPool db];
- FMDBQuickCheck(![dbPool db]);
-
- FMDBQuickCheck([adb tableExists:@"t4"]);
- FMDBQuickCheck([bbd tableExists:@"t4"]);
-
- FMDBQuickCheck([dbPool countOfOpenDatabases] == 2);
+ [dbPool inDatabase:^(FMDatabase *db) {
+ [dbPool inDatabase:^(FMDatabase *db2) {
+ [dbPool inDatabase:^(FMDatabase *db3) {
+ FMDBQuickCheck([dbPool countOfOpenDatabases] == 2);
+ FMDBQuickCheck(!db3);
+ }];
+
+ }];
+ }];
[dbPool setMaximumNumberOfDatabasesToCreate:0];
- adb = [dbPool db];
- bbd = [dbPool db];
- FMDatabase *cbd = [dbPool db];
-
- FMDBQuickCheck([adb tableExists:@"t4"]);
- FMDBQuickCheck([bbd tableExists:@"t4"]);
- FMDBQuickCheck([cbd tableExists:@"t4"]);
-
[dbPool releaseAllDatabases];
FMDBQuickCheck([dbPool countOfOpenDatabases] == 0);
-
- {
-
- db = [dbPool db];
-
- [db beginTransaction];
-
- [db executeUpdate:@"insert into easy values (?)", [NSNumber numberWithInt:1]];
- [db executeUpdate:@"insert into easy values (?)", [NSNumber numberWithInt:2]];
+ [dbPool inDatabase:^(FMDatabase *db) {
[db executeUpdate:@"insert into easy values (?)", [NSNumber numberWithInt:3]];
-
- FMDBQuickCheck([dbPool countOfCheckedInDatabases] == 0);
- FMDBQuickCheck([dbPool countOfCheckedOutDatabases] == 1);
-
- [db popFromPool];
-
- [db commit];
-
- [db pushToPool];
-
- FMDBQuickCheck([dbPool countOfCheckedInDatabases] == 1);
- FMDBQuickCheck([dbPool countOfCheckedOutDatabases] == 0);
-
- }
+ }];
- [db executeUpdate:@"insert into easy values (?)", [NSNumber numberWithInt:3]];
FMDBQuickCheck([dbPool countOfOpenDatabases] == 1);
@@ -924,9 +933,12 @@ void testPool(NSString *dbPath) {
FMDBQuickCheck([dbPool countOfCheckedOutDatabases] == 0);
- FMResultSet *rs2 = [[dbPool db] executeQuery:@"select * from easy where a = ?", [NSNumber numberWithInt:1001]];
- FMDBQuickCheck([rs2 next]);
- FMDBQuickCheck(![rs2 next]);
+ [dbPool inDatabase:^(FMDatabase *db) {
+ FMResultSet *rs2 = [db executeQuery:@"select * from easy where a = ?", [NSNumber numberWithInt:1001]];
+ FMDBQuickCheck([rs2 next]);
+ FMDBQuickCheck(![rs2 next]);
+ }];
+
[dbPool inDeferredTransaction:^(FMDatabase *adb, BOOL *rollback) {
@@ -939,48 +951,12 @@ void testPool(NSString *dbPath) {
FMDBQuickCheck([dbPool countOfOpenDatabases] == 1);
FMDBQuickCheck([dbPool countOfCheckedInDatabases] == 1);
FMDBQuickCheck([dbPool countOfCheckedOutDatabases] == 0);
-
- rs2 = [[dbPool db] executeQuery:@"select * from easy where a = ?", [NSNumber numberWithInt:1004]];
- FMDBQuickCheck(![rs2 next]);
-
- rs2 = [[dbPool db] executeQuery:@"select * from easy where a = ?", [NSNumber numberWithInt:1005]];
- FMDBQuickCheck(![rs2 next]);
-
- FMDBQuickCheck([dbPool countOfOpenDatabases] == 1);
-
-
+
NSError *err = [dbPool inSavePoint:^(FMDatabase *db, BOOL *rollback) {
- FMDBQuickCheck(![adb hadError]);
- [adb executeUpdate:@"insert into easy values (?)", [NSNumber numberWithInt:1006]];
+ [db executeUpdate:@"insert into easy values (?)", [NSNumber numberWithInt:1006]];
}];
- rs2 = [[dbPool db] executeQuery:@"select * from easy where a = ?", [NSNumber numberWithInt:1006]];
- FMDBQuickCheck([rs2 next]);
- [rs2 close];
-
- {
- db = [dbPool db];
- FMDBQuickCheck([db startSavePointWithName:@"a" error:nil]);
-
- [db executeUpdate:@"insert into easy values (?)", [NSNumber numberWithInt:1007]];
-
- FMDBQuickCheck([db startSavePointWithName:@"b" error:nil]);
-
- FMDBQuickCheck(([db executeUpdate:@"insert into easy values (?)", [NSNumber numberWithInt:1008]]));
-
- FMDBQuickCheck([db releaseSavePointWithName:@"b" error:nil]);
-
- FMDBQuickCheck([db releaseSavePointWithName:@"a" error:nil]);
-
- rs2 = [[dbPool db] executeQuery:@"select * from easy where a = ?", [NSNumber numberWithInt:1007]];
- FMDBQuickCheck([rs2 next]);
- FMDBQuickCheck(![rs2 next]); // close it out.
-
- rs2 = [[dbPool db] executeQuery:@"select * from easy where a = ?", [NSNumber numberWithInt:1008]];
- FMDBQuickCheck([rs2 next]);
- FMDBQuickCheck(![rs2 next]); // close it out.
- }
-
+ FMDBQuickCheck(!err);
{
@@ -994,12 +970,20 @@ void testPool(NSString *dbPath) {
}];
}];
- rs2 = [[dbPool db] executeQuery:@"select * from easy where a = ?", [NSNumber numberWithInt:1009]];
- FMDBQuickCheck([rs2 next]);
- FMDBQuickCheck(![rs2 next]); // close it out.
- rs2 = [[dbPool db] executeQuery:@"select * from easy where a = ?", [NSNumber numberWithInt:1010]];
- FMDBQuickCheck(![rs2 next]);
+ FMDBQuickCheck(!err);
+
+ [dbPool inDatabase:^(FMDatabase *db) {
+
+
+ FMResultSet *rs2 = [db executeQuery:@"select * from easy where a = ?", [NSNumber numberWithInt:1009]];
+ FMDBQuickCheck([rs2 next]);
+ FMDBQuickCheck(![rs2 next]); // close it out.
+
+ rs2 = [db executeQuery:@"select * from easy where a = ?", [NSNumber numberWithInt:1010]];
+ FMDBQuickCheck(![rs2 next]);
+ }];
+
}
@@ -1028,8 +1012,88 @@ void testPool(NSString *dbPath) {
FMDBQuickCheck(count == 2);
}];
+ }
+
+
+ {
+
+ int ops = 128;
+
+ dispatch_queue_t dqueue = dispatch_get_global_queue(0, DISPATCH_QUEUE_PRIORITY_HIGH);
+
+ dispatch_apply(ops, dqueue, ^(size_t nby) {
+
+ // just mix things up a bit for demonstration purposes.
+ if (nby % 2 == 1) {
+
+ [NSThread sleepForTimeInterval:.1];
+ }
+
+ [dbPool inDatabase:^(FMDatabase *db) {
+ NSLog(@"Starting query %ld", nby);
+
+ FMResultSet *rsl = [db executeQuery:@"select * from likefoo where foo like 'h%'"];
+ while ([rsl next]) {
+ if (nby % 3 == 1) {
+ [NSThread sleepForTimeInterval:.05];
+ }
+ }
+
+ NSLog(@"Ending query %ld", nby);
+ }];
+ });
+
+ NSLog(@"Number of open databases after crazy gcd stuff: %ld", [dbPool countOfOpenDatabases]);
+ }
+
+
+ // if you want to see a deadlock, just uncomment this line and run:
+ //#define ONLY_USE_THE_POOL_IF_YOU_ARE_DOING_READS_OTHERWISE_YOULL_DEADLOCK_USE_FMDATABASEQUEUE_INSTEAD 1
+#ifdef ONLY_USE_THE_POOL_IF_YOU_ARE_DOING_READS_OTHERWISE_YOULL_DEADLOCK_USE_FMDATABASEQUEUE_INSTEAD
+ {
+
+ int ops = 16;
+
+ dispatch_queue_t dqueue = dispatch_get_global_queue(0, DISPATCH_QUEUE_PRIORITY_HIGH);
+
+ dispatch_apply(ops, dqueue, ^(size_t nby) {
+
+ // just mix things up a bit for demonstration purposes.
+ if (nby % 2 == 1) {
+ [NSThread sleepForTimeInterval:.1];
+
+ [dbPool inTransaction:^(FMDatabase *db, BOOL *rollback) {
+ NSLog(@"Starting query %ld", nby);
+
+ FMResultSet *rsl = [db executeQuery:@"select * from likefoo where foo like 'h%'"];
+ while ([rsl next]) {
+ ;// whatever.
+ }
+
+ NSLog(@"Ending query %ld", nby);
+ }];
+
+ }
+
+ if (nby % 3 == 1) {
+ [NSThread sleepForTimeInterval:.1];
+ }
+
+ [dbPool inTransaction:^(FMDatabase *db, BOOL *rollback) {
+ NSLog(@"Starting update %ld", nby);
+ [db executeUpdate:@"insert into likefoo values ('1')"];
+ [db executeUpdate:@"insert into likefoo values ('2')"];
+ [db executeUpdate:@"insert into likefoo values ('3')"];
+ NSLog(@"Ending update %ld", nby);
+ }];
+ });
+ [dbPool releaseAllDatabases];
+ [dbPool inDatabase:^(FMDatabase *db) {
+ FMDBQuickCheck([db executeUpdate:@"insert into likefoo values ('1')"]);
+ }];
}
+#endif
}
Please sign in to comment.
Something went wrong with that request. Please try again.