FMDatabaseQueue.m 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. //
  2. // FMDatabaseQueue.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. */
  15. @implementation FMDatabaseQueue
  16. @synthesize path = _path;
  17. + (id)databaseQueueWithPath:(NSString*)aPath {
  18. FMDatabaseQueue *q = [[self alloc] initWithPath:aPath];
  19. FMDBAutorelease(q);
  20. return q;
  21. }
  22. - (id)initWithPath:(NSString*)aPath {
  23. self = [super init];
  24. if (self != nil) {
  25. _db = [FMDatabase databaseWithPath:aPath];
  26. FMDBRetain(_db);
  27. if (![_db open]) {
  28. NSLog(@"Could not create database queue for path %@", aPath);
  29. FMDBRelease(self);
  30. return 0x00;
  31. }
  32. _path = FMDBReturnRetained(aPath);
  33. _queue = dispatch_queue_create([[NSString stringWithFormat:@"fmdb.%@", self] UTF8String], NULL);
  34. }
  35. return self;
  36. }
  37. - (void)dealloc {
  38. FMDBRelease(_db);
  39. FMDBRelease(_path);
  40. if (_queue) {
  41. FMDBDispatchQueueRelease(_queue);
  42. _queue = 0x00;
  43. }
  44. #if ! __has_feature(objc_arc)
  45. [super dealloc];
  46. #endif
  47. }
  48. - (void)close {
  49. FMDBRetain(self);
  50. dispatch_sync(_queue, ^() {
  51. [_db close];
  52. FMDBRelease(_db);
  53. _db = 0x00;
  54. });
  55. FMDBRelease(self);
  56. }
  57. - (FMDatabase*)database {
  58. if (!_db) {
  59. _db = FMDBReturnRetained([FMDatabase databaseWithPath:_path]);
  60. if (![_db open]) {
  61. NSLog(@"FMDatabaseQueue could not reopen database for path %@", _path);
  62. FMDBRelease(_db);
  63. _db = 0x00;
  64. return 0x00;
  65. }
  66. }
  67. return _db;
  68. }
  69. - (void)inDatabase:(void (^)(FMDatabase *db))block {
  70. FMDBRetain(self);
  71. dispatch_sync(_queue, ^() {
  72. FMDatabase *db = [self database];
  73. block(db);
  74. if ([db hasOpenResultSets]) {
  75. NSLog(@"Warning: there is at least one open result set around after performing [FMDatabaseQueue inDatabase:]");
  76. }
  77. });
  78. FMDBRelease(self);
  79. }
  80. - (void)beginTransaction:(BOOL)useDeferred withBlock:(void (^)(FMDatabase *db, BOOL *rollback))block {
  81. FMDBRetain(self);
  82. dispatch_sync(_queue, ^() {
  83. BOOL shouldRollback = NO;
  84. if (useDeferred) {
  85. [[self database] beginDeferredTransaction];
  86. }
  87. else {
  88. [[self database] beginTransaction];
  89. }
  90. block([self database], &shouldRollback);
  91. if (shouldRollback) {
  92. [[self database] rollback];
  93. }
  94. else {
  95. [[self database] commit];
  96. }
  97. });
  98. FMDBRelease(self);
  99. }
  100. - (void)inDeferredTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block {
  101. [self beginTransaction:YES withBlock:block];
  102. }
  103. - (void)inTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block {
  104. [self beginTransaction:NO withBlock:block];
  105. }
  106. #if SQLITE_VERSION_NUMBER >= 3007000
  107. - (NSError*)inSavePoint:(void (^)(FMDatabase *db, BOOL *rollback))block {
  108. static unsigned long savePointIdx = 0;
  109. __block NSError *err = 0x00;
  110. FMDBRetain(self);
  111. dispatch_sync(_queue, ^() {
  112. NSString *name = [NSString stringWithFormat:@"savePoint%ld", savePointIdx++];
  113. BOOL shouldRollback = NO;
  114. if ([[self database] startSavePointWithName:name error:&err]) {
  115. block([self database], &shouldRollback);
  116. if (shouldRollback) {
  117. [[self database] rollbackToSavePointWithName:name error:&err];
  118. }
  119. else {
  120. [[self database] releaseSavePointWithName:name error:&err];
  121. }
  122. }
  123. });
  124. FMDBRelease(self);
  125. return err;
  126. }
  127. #endif
  128. @end