Selaa lähdekoodia

Sketching out some ideas.

August Mueller 9 vuotta sitten
vanhempi
commit
d9dd0aff1b
3 muutettua tiedostoa jossa 242 lisäystä ja 7 poistoa
  1. 32 1
      src/fmdb/FMDatabase.h
  2. 148 4
      src/fmdb/FMDatabase.m
  3. 62 2
      src/sample/main.m

+ 32 - 1
src/fmdb/FMDatabase.h

@@ -2,7 +2,6 @@
 #import "FMResultSet.h"
 #import "FMDatabasePool.h"
 
-
 #if ! __has_feature(objc_arc)
     #define FMDBAutorelease(__v) ([__v autorelease]);
     #define FMDBReturnAutoreleased FMDBAutorelease
@@ -37,6 +36,7 @@
     #define instancetype id
 #endif
 
+@class FMDBQ;
 
 typedef int(^FMDBExecuteStatementsCallbackBlock)(NSDictionary *resultsDictionary);
 
@@ -329,6 +329,9 @@ typedef int(^FMDBExecuteStatementsCallbackBlock)(NSDictionary *resultsDictionary
 - (BOOL)executeUpdate:(NSString*)sql, ...;
 
 
+- (void)executeUpdateInBackground:(FMDBQ*)q completion:(void (^)(NSError *error))callback;
+
+
 
 /** Execute single update statement
  
@@ -1045,6 +1048,15 @@ typedef int(^FMDBExecuteStatementsCallbackBlock)(NSDictionary *resultsDictionary
 
 - (NSString *)stringFromDate:(NSDate *)date;
 
+
+
+
+/////////// 33333333333333333333333333333333
+
+- (FMDBQ*)u:(NSString*)sql, ...;
+
+
+
 @end
 
 
@@ -1105,3 +1117,22 @@ 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
+
+

+ 148 - 4
src/fmdb/FMDatabase.m

@@ -811,6 +811,8 @@ - (BOOL)executeUpdate:(NSString*)sql error:(NSError* __autoreleasing*)outErr wit
     
     _isExecutingStatement = YES;
     
+    #pragma message "FIXME: chagne all the 0x00's to nils."
+    
     int rc                   = 0x00;
     sqlite3_stmt *pStmt      = 0x00;
     FMStatement *cachedStmt  = 0x00;
@@ -1288,16 +1290,60 @@ - (void)makeFunctionNamed:(NSString*)name maximumArguments:(int)count withBlock:
 #endif
 }
 
+- (FMDBQ*)u:(NSString*)sql, ... {
+    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);
+        
+    }
+    
+    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
 
 
 
 @implementation FMStatement
-@synthesize statement=_statement;
-@synthesize query=_query;
-@synthesize useCount=_useCount;
-@synthesize inUse=_inUse;
 
+#pragma message "FIXME: kill all the finalizes"
 - (void)finalize {
     [self close];
     [super finalize];
@@ -1335,3 +1381,101 @@ - (NSString*)description {
 
 @end
 
+
+@implementation FMDBQ
+
+- (void)executeUpdateInBackground:(void (^)(NSError *error))callback {
+    
+    
+    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
+        
+        NSError *outErr = nil;
+        
+        if (![self executeUpdate:&outErr]) {
+            callback(outErr);
+        }
+        else {
+            callback(nil);
+        }
+        
+        
+        
+    });
+    
+}
+
+
+- (BOOL)executeUpdate:(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
+

+ 62 - 2
src/sample/main.m

@@ -47,6 +47,68 @@ int main (int argc, const char * argv[]) {
     // kind of experimentalish.
     [db setShouldCacheStatements:YES];
     
+    
+    
+    
+    
+    
+    
+    
+    
+    ////////////////////////////////////////////// 3
+    
+    {
+        
+        
+        
+        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 BOOL allGood = NO;
+        
+        [[db u:@"create table test3 (a text, b text, c integer, d double, e double)"] executeUpdateInBackground:^(NSError *error) {
+            
+            
+            FMDBQuickCheck(error != nil);
+            
+            allGood = YES;
+        }];
+                        
+        
+        
+        sleep(2);
+        
+        FMDBQuickCheck(allGood);
+        
+        
+        NSLog(@"yay");
+        
+        
+        
+        
+        
+        return 0;
+        
+        
+        
+        
+        
+        
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
     // create a bad statement, just to test the error code.
     [db executeUpdate:@"blah blah blah"];
     
@@ -62,8 +124,6 @@ int main (int argc, const char * argv[]) {
     FMDBQuickCheck([err code] == SQLITE_ERROR);
     NSLog(@"err: '%@'", err);
     
-    
-    
     // empty strings should still return a value.
     FMDBQuickCheck(([db boolForQuery:@"SELECT ? not null", @""]));