diff options
author | August Mueller <gus@flyingmeat.com> | 2016-05-09 22:22:43 +0300 |
---|---|---|
committer | August Mueller <gus@flyingmeat.com> | 2016-05-09 22:22:43 +0300 |
commit | d9dd0aff1b3fa5522397dde24ab7ac1b6c3275d3 (patch) | |
tree | f5197c8824e0519141d937d9af6bf65f2fdfc194 | |
parent | 05780fb3918a399f63b4750cfb003fad24ee8a54 (diff) |
Sketching out some ideas.
-rw-r--r-- | src/fmdb/FMDatabase.h | 33 | ||||
-rw-r--r-- | src/fmdb/FMDatabase.m | 152 | ||||
-rw-r--r-- | src/sample/main.m | 64 |
3 files changed, 242 insertions, 7 deletions
diff --git a/src/fmdb/FMDatabase.h b/src/fmdb/FMDatabase.h index 9f11bda..21484f1 100644 --- a/src/fmdb/FMDatabase.h +++ b/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 + + diff --git a/src/fmdb/FMDatabase.m b/src/fmdb/FMDatabase.m index b7250e5..187c994 100644 --- a/src/fmdb/FMDatabase.m +++ b/src/fmdb/FMDatabase.m @@ -811,6 +811,8 @@ static int FMDBDatabaseBusyHandler(void *f, int count) { _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 FMDBBlockSQLiteCallBackFunction(sqlite3_context *context, int argc, sqlite3 #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 @@ void FMDBBlockSQLiteCallBackFunction(sqlite3_context *context, int argc, sqlite3 @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 + diff --git a/src/sample/main.m b/src/sample/main.m index ea2e407..1649fef 100644 --- a/src/sample/main.m +++ b/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", @""])); |