FMDB源码阅读FMDatabase.m
Posted CHM
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了FMDB源码阅读FMDatabase.m相关的知识,希望对你有一定的参考价值。
FMDatabase.m
1 @interface FMDatabase () { 2 void* _db; 3 BOOL _isExecutingStatement; 4 NSTimeInterval _startBusyRetryTime; 5 6 NSMutableSet *_openResultSets; 7 NSMutableSet *_openFunctions; 8 9 NSDateFormatter *_dateFormat; 10 }
成员变量。
1 NS_ASSUME_NONNULL_BEGIN 2 3 - (FMResultSet * _Nullable)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray * _Nullable)arrayArgs orDictionary:(NSDictionary * _Nullable)dictionaryArgs orVAList:(va_list)args; 4 - (BOOL)executeUpdate:(NSString *)sql error:(NSError * _Nullable *)outErr withArgumentsInArray:(NSArray * _Nullable)arrayArgs orDictionary:(NSDictionary * _Nullable)dictionaryArgs orVAList:(va_list)args; 5 6 NS_ASSUME_NONNULL_END
两个很长的执行数据库更新和查询的方法。
1 // Because these two properties have all of their accessor methods implemented, 2 // we have to synthesize them to get the corresponding ivars. The rest of the 3 // properties have their ivars synthesized automatically for us. 4 5 @synthesize shouldCacheStatements = _shouldCacheStatements; 6 @synthesize maxBusyRetryTimeInterval = _maxBusyRetryTimeInterval;
给成员变量指定新的名字(是否缓存 SQL 语句和描述即将到来的)。
数据库实例化和存储单元分配:
1 + (instancetype)databaseWithPath:(NSString *)aPath { 2 return FMDBReturnAutoreleased([[self alloc] initWithPath:aPath]); 3 } 4 5 + (instancetype)databaseWithURL:(NSURL *)url { 6 return FMDBReturnAutoreleased([[self alloc] initWithURL:url]); 7 } 8 9 - (instancetype)init { 10 return [self initWithPath:nil]; 11 } 12 13 - (instancetype)initWithURL:(NSURL *)url { 14 return [self initWithPath:url.path]; 15 } 16 17 - (instancetype)initWithPath:(NSString *)path { 18 19 assert(sqlite3_threadsafe()); // whoa there big boy- gotta make sure sqlite it happy with what we‘re going to do. 20 21 self = [super init]; 22 23 if (self) { 24 _databasePath = [path copy]; 25 _openResultSets = [[NSMutableSet alloc] init]; 26 _db = nil; 27 _logsErrors = YES; 28 _crashOnErrors = NO; 29 _maxBusyRetryTimeInterval = 2; 30 } 31 32 return self; 33 }
指定路径初始化数据库。
1 #define assert(e) 2 (__builtin_expect(!(e), 0) ? __assert_rtn(__func__, __FILE__, __LINE__, #e) : (void)0)
1 #if ! __has_feature(objc_arc) 2 - (void)finalize { 3 [self close]; 4 [super finalize]; 5 } 6 #endif 7 8 - (void)dealloc { 9 [self close]; 10 FMDBRelease(_openResultSets); 11 FMDBRelease(_cachedStatements); 12 FMDBRelease(_dateFormat); 13 FMDBRelease(_databasePath); 14 FMDBRelease(_openFunctions); 15 16 #if ! __has_feature(objc_arc) 17 [super dealloc]; 18 #endif 19 }
内存释放,兼容 ARC 和 MRC。
1 - (NSURL *)databaseURL { 2 return _databasePath ? [NSURL fileURLWithPath:_databasePath] : nil; 3 } 4 5 + (NSString*)FMDBUserVersion { 6 return @"2.7.2"; 7 }
返回路径和返回 FMDB 使用版本。
1 // returns 0x0240 for version 2.4. This makes it super easy to do things like: 2 // /* need to make sure to do X with FMDB version 2.4 or later */ 3 // if ([FMDatabase FMDBVersion] >= 0x0240) { … } 4 5 + (SInt32)FMDBVersion { 6 7 // we go through these hoops so that we only have to change the version number in a single spot. 8 static dispatch_once_t once; 9 static SInt32 FMDBVersionVal = 0; 10 11 dispatch_once(&once, ^{ 12 NSString *prodVersion = [self FMDBUserVersion]; 13 14 if ([[prodVersion componentsSeparatedByString:@"."] count] < 3) { 15 prodVersion = [prodVersion stringByAppendingString:@".0"]; 16 } 17 18 NSString *junk = [prodVersion stringByReplacingOccurrencesOfString:@"." withString:@""]; 19 20 char *e = nil; 21 FMDBVersionVal = (int) strtoul([junk UTF8String], &e, 16); 22 23 }); 24 25 return FMDBVersionVal; 26 }
返回 FMDB 版本,补0去处英语句号返回一个无符号 long。
1 unsigned long 2 strtoul(const char *__str, char **__endptr, int __base);
SQLite 的信息:
1 + (NSString*)sqliteLibVersion { 2 return [NSString stringWithFormat:@"%s", sqlite3_libversion()]; 3 } 4 5 + (BOOL)isSQLiteThreadSafe { 6 // make sure to read the sqlite headers on this guy! 7 return sqlite3_threadsafe() != 0; 8 } 9 10 - (void*)sqliteHandle { 11 return _db; 12 } 13 14 - (const char*)sqlitePath { 15 16 if (!_databasePath) { 17 return ":memory:"; 18 } 19 20 if ([_databasePath length] == 0) { 21 return ""; // this creates a temporary database (it‘s an sqlite thing). 22 } 23 24 return [_databasePath fileSystemRepresentation]; 25 26 }
SQLiteLit 版本、SQLite 是否是线程安全的、返回数据库、返回三条路径之一。
打开和关闭数据库:
1 - (BOOL)open { 2 if (_db) { 3 return YES; 4 } 5 6 int err = sqlite3_open([self sqlitePath], (sqlite3**)&_db ); 7 if(err != SQLITE_OK) { 8 NSLog(@"error opening!: %d", err); 9 return NO; 10 } 11 12 if (_maxBusyRetryTimeInterval > 0.0) { 13 // set the handler 14 [self setMaxBusyRetryTimeInterval:_maxBusyRetryTimeInterval]; 15 } 16 17 18 return YES; 19 }
1 - (BOOL)openWithFlags:(int)flags { 2 return [self openWithFlags:flags vfs:nil]; 3 } 4 - (BOOL)openWithFlags:(int)flags vfs:(NSString *)vfsName { 5 #if SQLITE_VERSION_NUMBER >= 3005000 6 if (_db) { 7 return YES; 8 } 9 10 int err = sqlite3_open_v2([self sqlitePath], (sqlite3**)&_db, flags, [vfsName UTF8String]); 11 if(err != SQLITE_OK) { 12 NSLog(@"error opening!: %d", err); 13 return NO; 14 } 15 16 if (_maxBusyRetryTimeInterval > 0.0) { 17 // set the handler 18 [self setMaxBusyRetryTimeInterval:_maxBusyRetryTimeInterval]; 19 } 20 21 return YES; 22 #else 23 NSLog(@"openWithFlags requires SQLite 3.5"); 24 return NO; 25 #endif 26 }
1 SQLITE_API int SQLITE_STDCALL sqlite3_open( 2 const char *filename, /* Database filename (UTF-8) */ 3 sqlite3 **ppDb /* OUT: SQLite db handle */ 4 ); 5 SQLITE_API int SQLITE_STDCALL sqlite3_open16( 6 const void *filename, /* Database filename (UTF-16) */ 7 sqlite3 **ppDb /* OUT: SQLite db handle */ 8 ); 9 SQLITE_API int SQLITE_STDCALL sqlite3_open_v2( 10 const char *filename, /* Database filename (UTF-8) */ 11 sqlite3 **ppDb, /* OUT: SQLite db handle */ 12 int flags, /* Flags */ 13 const char *zVfs /* Name of VFS module to use */ 14 );
携带标志打开数据库。
1 - (BOOL)close { 2 3 [self clearCachedStatements]; 4 [self closeOpenResultSets]; 5 6 if (!_db) { 7 return YES; 8 } 9 10 int rc; 11 BOOL retry; 12 BOOL triedFinalizingOpenStatements = NO; 13 14 do { 15 retry = NO; 16 rc = sqlite3_close(_db); 17 if (SQLITE_BUSY == rc || SQLITE_LOCKED == rc) { 18 if (!triedFinalizingOpenStatements) { 19 triedFinalizingOpenStatements = YES; 20 sqlite3_stmt *pStmt; 21 while ((pStmt = sqlite3_next_stmt(_db, nil)) !=0) { 22 NSLog(@"Closing leaked statement"); 23 sqlite3_finalize(pStmt); 24 retry = YES; 25 } 26 } 27 } 28 else if (SQLITE_OK != rc) { 29 NSLog(@"error closing!: %d", rc); 30 } 31 } 32 while (retry); 33 34 _db = nil; 35 return YES; 36 }
以上是关于FMDB源码阅读FMDatabase.m的主要内容,如果未能解决你的问题,请参考以下文章