FMDatabaseQueue.m 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. //
  2. // FMDatabasePool.m
  3. // fmdb
  4. //
  5. // Created by August Mueller on 6/22/11.
  6. // Copyright 2011 Flying Meat Inc. All rights reserved.
  7. //
  8. #import "FMDatabaseQueue.h"
  9. #import "FMDatabase.h"
  10. /*
  11. Note: we call [self retain]; before using dispatch_sync, just incase
  12. FMDatabaseQueue is released on another thread and we're in the middle of doing
  13. something in dispatch_sync
  14. Another Note:
  15. Some day, I think it would be awesome to add support for creating a queue with
  16. DISPATCH_QUEUE_CONCURRENT, and then make dispatch_barrier_async the default
  17. way to execute things- but give the option to use dispatch_sync for cases where
  18. we know we're going to make read only operations for the database.
  19. */
  20. @implementation FMDatabaseQueue
  21. @synthesize path = _path;
  22. + (id)databaseQueueWithPath:(NSString*)aPath {
  23. FMDatabaseQueue *q = [[self alloc] initWithPath:aPath];
  24. FMDBAutorelease(q);
  25. return q;
  26. }
  27. - (id)initWithPath:(NSString*)aPath {
  28. self = [super init];
  29. if (self != nil) {
  30. _db = [FMDatabase databaseWithPath:aPath];
  31. FMDBRetain(_db);
  32. if (![_db open]) {
  33. NSLog(@"Could not create database queue for path %@", aPath);
  34. FMDBRelease(self);
  35. return 0x00;
  36. }
  37. _path = FMDBReturnRetained(aPath);
  38. _queue = dispatch_queue_create([[NSString stringWithFormat:@"fmdb.%@", self] UTF8String], NULL);
  39. }
  40. return self;
  41. }
  42. - (void)dealloc {
  43. FMDBRelease(_db);
  44. FMDBRelease(_path);
  45. if (_queue) {
  46. dispatch_release(_queue);
  47. _queue = 0x00;
  48. }
  49. #if ! __has_feature(objc_arc)
  50. [super dealloc];
  51. #endif
  52. }
  53. - (void)close {
  54. FMDBRetain(self);
  55. dispatch_sync(_queue, ^() {
  56. [_db close];
  57. FMDBRelease(_db);
  58. _db = 0x00;
  59. });
  60. FMDBRelease(self);
  61. }
  62. - (FMDatabase*)database {
  63. if (!_db) {
  64. _db = FMDBReturnRetained([FMDatabase databaseWithPath:_path]);
  65. if (![_db open]) {
  66. NSLog(@"FMDatabaseQueue could not reopen database for path %@", _path);
  67. FMDBRelease(_db);
  68. _db = 0x00;
  69. return 0x00;
  70. }
  71. }
  72. return _db;
  73. }
  74. - (void)inDatabase:(void (^)(FMDatabase *db))block {
  75. FMDBRetain(self);
  76. dispatch_sync(_queue, ^() {
  77. FMDatabase *db = [self database];
  78. block(db);
  79. if ([db hasOpenResultSets]) {
  80. NSLog(@"Warning: there is at least one open result set around after performing [FMDatabaseQueue inDatabase:]");
  81. }
  82. });
  83. FMDBRelease(self);
  84. }
  85. - (void)beginTransaction:(BOOL)useDeferred withBlock:(void (^)(FMDatabase *db, BOOL *rollback))block {
  86. FMDBRetain(self);
  87. dispatch_sync(_queue, ^() {
  88. BOOL shouldRollback = NO;
  89. if (useDeferred) {
  90. [[self database] beginDeferredTransaction];
  91. }
  92. else {
  93. [[self database] beginTransaction];
  94. }
  95. block([self database], &shouldRollback);
  96. if (shouldRollback) {
  97. [[self database] rollback];
  98. }
  99. else {
  100. [[self database] commit];
  101. }
  102. });
  103. FMDBRelease(self);
  104. }
  105. - (void)inDeferredTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block {
  106. [self beginTransaction:YES withBlock:block];
  107. }
  108. - (void)inTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block {
  109. [self beginTransaction:NO withBlock:block];
  110. }
  111. #if SQLITE_VERSION_NUMBER >= 3007000
  112. - (NSError*)inSavePoint:(void (^)(FMDatabase *db, BOOL *rollback))block {
  113. static unsigned long savePointIdx = 0;
  114. __block NSError *err = 0x00;
  115. FMDBRetain(self);
  116. dispatch_sync(_queue, ^() {
  117. NSString *name = [NSString stringWithFormat:@"savePoint%ld", savePointIdx++];
  118. BOOL shouldRollback = NO;
  119. if ([[self database] startSavePointWithName:name error:&err]) {
  120. block([self database], &shouldRollback);
  121. if (shouldRollback) {
  122. [[self database] rollbackToSavePointWithName:name error:&err];
  123. }
  124. else {
  125. [[self database] releaseSavePointWithName:name error:&err];
  126. }
  127. }
  128. });
  129. FMDBRelease(self);
  130. return err;
  131. }
  132. #endif
  133. @end