Browse Source

More sketching.

August Mueller 9 years ago
parent
commit
abc2388524
5 changed files with 60 additions and 256 deletions
  1. 0 29
      src/fmdb/FMDatabase.h
  2. 2 177
      src/fmdb/FMDatabase.m
  3. 2 0
      src/fmdb/FMDatabaseQueue.h
  4. 12 1
      src/fmdb/FMDatabaseQueue.m
  5. 44 49
      src/sample/main.m

+ 0 - 29
src/fmdb/FMDatabase.h

@@ -328,11 +328,6 @@ typedef int(^FMDBExecuteStatementsCallbackBlock)(NSDictionary *resultsDictionary
 
 - (BOOL)executeUpdate:(NSString*)sql, ...;
 
-
-- (void)executeUpdateInBackground:(FMDBQ*)q completion:(void (^)(NSError *error))callback;
-
-
-
 /** Execute single update statement
  
  This method executes a single SQL update statement (i.e. any SQL that does not return results, such as `UPDATE`, `INSERT`, or `DELETE`. This method employs [`sqlite3_prepare_v2`](http://sqlite.org/c3ref/prepare.html) and [`sqlite3_bind`](http://sqlite.org/c3ref/bind_blob.html) binding any `?` placeholders in the SQL with the optional list of parameters.
@@ -1051,12 +1046,6 @@ typedef int(^FMDBExecuteStatementsCallbackBlock)(NSDictionary *resultsDictionary
 
 
 
-/////////// 33333333333333333333333333333333
-
-- (FMDBQ*)u:(NSString*)sql, ...;
-
-
-
 @end
 
 
@@ -1118,21 +1107,3 @@ typedef int(^FMDBExecuteStatementsCallbackBlock)(NSDictionary *resultsDictionary
 #pragma clang diagnostic pop
 
 
-#pragma message "FIXME: This name is temporary"
-@interface FMDBQ : NSObject {
-    
-}
-
-
-@property (atomic, weak) FMDatabase *db;
-@property (atomic, assign) void *statement;
-@property (atomic, strong) NSString *query;
-@property (atomic, strong) NSArray *arguments;
-
-
-- (BOOL)executeUpdate:(NSError * __autoreleasing *)outErr;
-- (void)executeUpdateInBackground:(void (^)(NSError *error))callback;
-
-@end
-
-

+ 2 - 177
src/fmdb/FMDatabase.m

@@ -838,7 +838,8 @@ - (BOOL)executeUpdate:(NSString*)sql error:(NSError* __autoreleasing*)outErr wit
             }
             
             if (_crashOnErrors) {
-                NSAssert(false, @"DB Error: %d \"%@\"", [self lastErrorCode], [self lastErrorMessage]);
+                NSLog(@"DB Error: %d \"%@\"", [self lastErrorCode], [self lastErrorMessage]);
+                assert(NO);
                 abort();
             }
             
@@ -1290,56 +1291,6 @@ - (void)makeFunctionNamed:(NSString*)name maximumArguments:(int)count withBlock:
 #endif
 }
 
-- (FMDBQ*)u:(NSString*)sql, ... {
-    
-    #pragma message "FIXME: this will go kabom if it's not on a queue."
-    
-    FMDBQ *q = [FMDBQ new];
-    
-    va_list args;
-    va_start(args, sql);
-    
-    sqlite3_stmt *pStmt = nil;
-    
-    int rc = sqlite3_prepare_v2(_db, [sql UTF8String], -1, &pStmt, 0);
-    
-    if (SQLITE_OK != rc) {
-        if (_logsErrors) {
-            NSLog(@"DB Error: %d \"%@\"", [self lastErrorCode], [self lastErrorMessage]);
-            NSLog(@"DB Query: %@", sql);
-            NSLog(@"DB Path: %@", _databasePath);
-        }
-        
-        if (_crashOnErrors) {
-            NSAssert(false, @"DB Error: %d \"%@\"", [self lastErrorCode], [self lastErrorMessage]);
-            abort();
-        }
-        
-        sqlite3_finalize(pStmt);
-        
-        return nil;
-    }
-    
-    int idx = 0;
-    int queryCount = sqlite3_bind_parameter_count(pStmt); // pointed out by Dominic Yu (thanks!)
-
-    while (idx < queryCount) {
-        
-        id obj = va_arg(args, id);
-        
-        idx++;
-        
-        [self bindObject:obj toColumn:idx inStatement:pStmt];
-    }
-    
-    va_end(args);
-    
-    [q setStatement:pStmt];
-    [q setDb:self];
-    
-    return q;
-}
-
 @end
 
 
@@ -1381,131 +1332,5 @@ - (NSString*)description {
     return [NSString stringWithFormat:@"%@ %ld hit(s) for query %@", [super description], _useCount, _query];
 }
 
-
-@end
-
-
-@implementation FMDBQ
-
-- (void)executeUpdateSync:(BOOL)isSync callback:(void (^)(NSError *))callback {
-    
-    static dispatch_queue_t FMDBQ_queue;
-    
-    static dispatch_once_t onceToken;
-    dispatch_once(&onceToken, ^{
-        FMDBQ_queue = dispatch_queue_create([[NSString stringWithFormat:@"fmdb.%@", self] UTF8String], DISPATCH_QUEUE_SERIAL);
-    });
-    
-    
-    void (*dispatch_function)(dispatch_queue_t queue, dispatch_block_t block) = isSync ? dispatch_sync : dispatch_async;
-    
-    dispatch_function(FMDBQ_queue, ^{
-        
-        NSError *outErr = nil;
-        
-        if (![self executeUpdateInt:&outErr]) {
-            callback(outErr);
-        }
-        else {
-            callback(nil);
-        }
-        
-    });
-}
-
-- (void)executeUpdateInBackground:(void (^)(NSError *error))callback {
-    
-    [self executeUpdateSync:NO callback:callback];
-}
-
-
-- (BOOL)executeUpdate:(NSError * __autoreleasing *)outErr {
-    
-    __block BOOL worked = NO;
-    [self executeUpdateSync:YES callback:^(NSError *e) {
-        
-        worked = e == nil;
-        if (e) {
-            *outErr = e;
-        }
-    }];
-    
-    
-    return worked;
-}
-
-
-- (BOOL)executeUpdateInt:(NSError * __autoreleasing *)outErr {
-    
-    // FIXME: ref the db here instead of using an ivar.
-    BOOL _logsErrors = NO;
-    NSString *sql = nil;
-    
-    
-    /* Call sqlite3_step() to run the virtual machine. Since the SQL being
-     ** executed is not a SELECT statement, we assume no data will be returned.
-     */
-    
-    int rc = sqlite3_step(_statement);
-    
-    if (SQLITE_DONE == rc) {
-        // all is well, let's return.
-    }
-    else if (rc == SQLITE_ROW) {
-        NSString *message = [NSString stringWithFormat:@"A executeUpdate is being called with a query string '%@'", sql];
-        if (_logsErrors) {
-            NSLog(@"%@", message);
-            NSLog(@"DB Query: %@", sql);
-        }
-        if (outErr) {
-            *outErr = [[self db] errorWithMessage:message];
-        }
-    }
-    else {
-        if (outErr) {
-            *outErr = [[self db] errorWithMessage:[NSString stringWithUTF8String:sqlite3_errmsg([[self db] sqliteHandle])]];
-        }
-        
-        if (SQLITE_ERROR == rc) {
-            if (_logsErrors) {
-                NSLog(@"Error calling sqlite3_step (%d: %s) SQLITE_ERROR", rc, sqlite3_errmsg([[self db] sqliteHandle]));
-                NSLog(@"DB Query: %@", sql);
-            }
-        }
-        else if (SQLITE_MISUSE == rc) {
-            // uh oh.
-            if (_logsErrors) {
-                NSLog(@"Error calling sqlite3_step (%d: %s) SQLITE_MISUSE", rc, sqlite3_errmsg([[self db] sqliteHandle]));
-                NSLog(@"DB Query: %@", sql);
-            }
-        }
-        else {
-            // wtf?
-            if (_logsErrors) {
-                NSLog(@"Unknown error calling sqlite3_step (%d: %s) eu", rc, sqlite3_errmsg([[self db] sqliteHandle]));
-                NSLog(@"DB Query: %@", sql);
-            }
-        }
-    }
-    
-    /* Finalize the virtual machine. This releases all memory and other
-     ** resources allocated by the sqlite3_prepare() call above.
-     */
-    
-    int closeErrorCode = sqlite3_finalize(_statement);
-    
-    
-    if (closeErrorCode != SQLITE_OK) {
-        if (_logsErrors) {
-            #pragma message "FIXME: set something in the outErr here."
-            NSLog(@"Unknown error finalizing or resetting statement (%d: %s)", closeErrorCode, sqlite3_errmsg([[self db] sqliteHandle]));
-            NSLog(@"DB Query: %@", sql);
-        }
-    }
-    
-    return (rc == SQLITE_DONE || rc == SQLITE_OK);
-}
-
-
 @end
 

+ 2 - 0
src/fmdb/FMDatabaseQueue.h

@@ -156,6 +156,8 @@
 
 - (void)inDatabase:(void (^)(FMDatabase *db))block;
 
+- (void)inBackground:(void (^)(FMDatabase *db))block;
+
 /** Synchronously perform database operations on queue, using transactions.
 
  @param block The code to be run on the queue of `FMDatabaseQueue`

+ 12 - 1
src/fmdb/FMDatabaseQueue.m

@@ -149,6 +149,14 @@ - (FMDatabase*)database {
 }
 
 - (void)inDatabase:(void (^)(FMDatabase *db))block {
+    [self inDatabase:block isAsync:NO];
+}
+
+- (void)inBackground:(void (^)(FMDatabase *db))block {
+    [self inDatabase:block isAsync:YES];
+}
+
+- (void)inDatabase:(void (^)(FMDatabase *db))block isAsync:(BOOL)isAsync {
     /* Get the currently executing queue (which should probably be nil, but in theory could be another DB queue
      * and then check it against self to make sure we're not about to deadlock. */
     FMDatabaseQueue *currentSyncQueue = (__bridge id)dispatch_get_specific(kDispatchQueueSpecificKey);
@@ -156,7 +164,10 @@ - (void)inDatabase:(void (^)(FMDatabase *db))block {
     
     FMDBRetain(self);
     
-    dispatch_sync(_queue, ^() {
+    void (*dispatch_function)(dispatch_queue_t queue, dispatch_block_t block) = isAsync ? dispatch_async : dispatch_sync;
+
+    
+    dispatch_function(_queue, ^() {
         
         FMDatabase *db = [self database];
         block(db);

+ 44 - 49
src/sample/main.m

@@ -45,70 +45,61 @@ int main (int argc, const char * argv[]) {
     }
     
     // kind of experimentalish.
-    //[db setShouldCacheStatements:YES];
-    
-    
-    
-    
-    
-    
+    [db setShouldCacheStatements:YES];
     
     
     
-    ////////////////////////////////////////////// 3
+    FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:dbPath];
     
     {
         
+        // 3.0, async stuff.
         
         
-        NSError *err = nil;
-        FMDBQuickCheck([[db u:@"create table test3 (a text, b text, c integer, d double, e double)"] executeUpdate:&err]);
-        FMDBQuickCheck(err == nil);
-        
-        
-        
-        __block int allGoodCount = NO;
         
-        [[db u:@"create table test3 (a text, b text, c integer, d double, e double)"] executeUpdateInBackground:^(NSError *error) {
-            FMDBQuickCheck(error != nil);
-            allGoodCount++;
+        [queue inDatabase:^(FMDatabase *adb) {
+            [adb setShouldCacheStatements:YES];
+            [adb setCrashOnErrors:YES];
+            [adb executeUpdate:@"create table threeasync (foo text)"];
         }];
         
+        static int32_t updateCount = 0;
+        static int32_t submitCount = 0;
         
-        
-        dispatch_apply(20, dispatch_get_global_queue(0, DISPATCH_QUEUE_PRIORITY_HIGH), ^(size_t i) {
-            
-            NSLog(@"idx: %ld", i);
+        dispatch_apply(40, dispatch_get_global_queue(0, DISPATCH_QUEUE_PRIORITY_DEFAULT), ^(size_t idx) {
             
-            [[db u:@"insert into test3 (a, b, c, d, e) values (?, ?, ?, ?, ?)" ,
-              @"hi'", // look!  I put in a ', and I'm not escaping it!
-              [NSString stringWithFormat:@"number %ld", i],
-              @(i),
-              [NSDate date],
-              [NSNumber numberWithFloat:2.2f]] executeUpdateInBackground:^(NSError *error) {
+            [queue inBackground:^(FMDatabase *adb) {
+                
+                if (idx % 2 == 0) {
+                    usleep(50); // artificial delay.
+                }
+                
+                if (idx % 3 == 0) {
+                    usleep(100); // another artificial delay.
+                }
+                
+                [adb executeUpdate:@"insert into threeasync (foo) values (?)", [NSString stringWithFormat:@"%ld", idx]];
+                
+                FMDBQuickCheck(![adb hadError]);
+                
+                OSAtomicIncrement32(&updateCount);
                 
-                FMDBQuickCheck(error == nil);
-                allGoodCount++;
             }];
+            
+            
+            OSAtomicIncrement32(&submitCount);
         });
         
-        sleep(2);
-        
-        FMDBQuickCheck(allGoodCount == 21);
-        
-        
-        NSLog(@"yay");
-        
-        
-        
-        
-        
-        return 0;
-        
-        
+        NSLog(@"submitCount: %d", submitCount);
         
+        FMDBQuickCheck(submitCount == 40);
         
         
+        // This will block till all the above async stuff is done.
+        [queue inDatabase:^(FMDatabase *adb) {
+            NSLog(@"done?");
+            FMDBQuickCheck(updateCount == 40);
+        }];
         
     }
     
@@ -120,8 +111,6 @@ int main (int argc, const char * argv[]) {
     
     
     
-    
-    
     // create a bad statement, just to test the error code.
     [db executeUpdate:@"blah blah blah"];
     
@@ -761,6 +750,8 @@ int main (int argc, const char * argv[]) {
     
     
     {
+        FMDBQuickCheck([db executeUpdate:@"create table t5 (a text, b int, c blob, d text, e text)"]);
+        
         FMDBQuickCheck(([db executeUpdate:@"insert into t5 values (?, ?, ?, ?, ?)" withErrorAndBindings:&err, @"text", [NSNumber numberWithInt:42], @"BLOB", @"d", [NSNumber numberWithInt:0]]));
         
     }
@@ -870,7 +861,7 @@ int main (int argc, const char * argv[]) {
     
     
     
-    FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:dbPath];
+    
     
     FMDBQuickCheck(queue);
     
@@ -1073,11 +1064,13 @@ int main (int argc, const char * argv[]) {
         }];
         
         int rowCount = 0;
-        FMResultSet *ars = [adb executeQuery:@"select * from ftest where StringStartsWithH(foo)"];
+        FMResultSet *ars = [adb executeQuery:@"select foo from ftest where StringStartsWithH(foo)"];
         while ([ars next]) {
             rowCount++;
             
-            NSLog(@"Does %@ start with 'h'?", [rs stringForColumnIndex:0]);
+            FMDBQuickCheck([[ars stringForColumnIndex:0] hasPrefix:@"h"]);
+            
+            NSLog(@"Does %@ start with 'h'?", [ars stringForColumnIndex:0]);
             
         }
         FMDBQuickCheck(rowCount == 2);
@@ -1086,6 +1079,8 @@ int main (int argc, const char * argv[]) {
         
     }];
     
+    
+    
     NSLog(@"That was version %@ of sqlite", [FMDatabase sqliteLibVersion]);