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的主要内容,如果未能解决你的问题,请参考以下文章

原FMDB源码阅读

FMDB源码阅读FMDatabase

iOS 开发之 FMDB 源码分析

Python代码阅读(第19篇):合并多个字典

Python代码阅读(第26篇):将列表映射成字典

如何进行 Java 代码阅读分析?