appjam 0.1.8.6 → 0.1.8.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. data/lib/appjam.rb +1 -1
  2. data/lib/appjam/generators/blank.rb +133 -0
  3. data/lib/appjam/generators/help.rb +5 -3
  4. data/lib/appjam/generators/templates/blank/EiffelApplication.xcodeproj/project.pbxproj +855 -0
  5. data/lib/appjam/generators/templates/blank/EiffelApplication.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
  6. data/lib/appjam/generators/templates/blank/EiffelApplication.xcodeproj/project.xcworkspace/xcuserdata/eiffel.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  7. data/lib/appjam/generators/templates/blank/EiffelApplication.xcodeproj/xcuserdata/eiffel.xcuserdatad/xcschemes/EiffelApplication.xcscheme +96 -0
  8. data/lib/appjam/generators/templates/blank/EiffelApplication.xcodeproj/xcuserdata/eiffel.xcuserdatad/xcschemes/xcschememanagement.plist +27 -0
  9. data/lib/appjam/generators/templates/blank/EiffelApplication/AppDelegate.h.tt +22 -0
  10. data/lib/appjam/generators/templates/blank/EiffelApplication/AppDelegate.m.tt +156 -0
  11. data/lib/appjam/generators/templates/blank/EiffelApplication/EiffelApplication-Info.plist +45 -0
  12. data/lib/appjam/generators/templates/blank/EiffelApplication/EiffelApplication-Prefix.pch.tt +30 -0
  13. data/lib/appjam/generators/templates/blank/EiffelApplication/en.lproj/InfoPlist.strings +2 -0
  14. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/AFNetworking/AFHTTPClient.h +636 -0
  15. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/AFNetworking/AFHTTPClient.m +1359 -0
  16. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/AFNetworking/AFHTTPRequestOperation.h +133 -0
  17. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/AFNetworking/AFHTTPRequestOperation.m +318 -0
  18. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/AFNetworking/AFImageRequestOperation.h +108 -0
  19. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/AFNetworking/AFImageRequestOperation.m +234 -0
  20. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/AFNetworking/AFJSONRequestOperation.h +71 -0
  21. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/AFNetworking/AFJSONRequestOperation.m +142 -0
  22. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/AFNetworking/AFNetworkActivityIndicatorManager.h +75 -0
  23. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/AFNetworking/AFNetworkActivityIndicatorManager.m +145 -0
  24. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/AFNetworking/AFNetworking.h +43 -0
  25. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/AFNetworking/AFPropertyListRequestOperation.h +68 -0
  26. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/AFNetworking/AFPropertyListRequestOperation.m +142 -0
  27. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/AFNetworking/AFURLConnectionOperation.h +379 -0
  28. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/AFNetworking/AFURLConnectionOperation.m +818 -0
  29. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/AFNetworking/AFXMLRequestOperation.h +89 -0
  30. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/AFNetworking/AFXMLRequestOperation.m +166 -0
  31. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/AFNetworking/UIImageView+AFNetworking.h +78 -0
  32. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/AFNetworking/UIImageView+AFNetworking.m +184 -0
  33. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/JSONKit/JSONKit.h +251 -0
  34. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/JSONKit/JSONKit.m +3067 -0
  35. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/fmdb/FMDatabase.h +155 -0
  36. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/fmdb/FMDatabase.m +1162 -0
  37. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/fmdb/FMDatabaseAdditions.h +37 -0
  38. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/fmdb/FMDatabaseAdditions.m +163 -0
  39. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/fmdb/FMDatabasePool.h +75 -0
  40. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/fmdb/FMDatabasePool.m +244 -0
  41. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/fmdb/FMDatabaseQueue.h +38 -0
  42. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/fmdb/FMDatabaseQueue.m +176 -0
  43. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/fmdb/FMResultSet.h +104 -0
  44. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/fmdb/FMResultSet.m +413 -0
  45. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/EGOCache/EGOCache.h +78 -0
  46. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/EGOCache/EGOCache.m +370 -0
  47. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/Lumberjack/DDASLLogger.h +41 -0
  48. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/Lumberjack/DDASLLogger.m +99 -0
  49. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/Lumberjack/DDAbstractDatabaseLogger.h +102 -0
  50. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/Lumberjack/DDAbstractDatabaseLogger.m +727 -0
  51. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/Lumberjack/DDFileLogger.h +334 -0
  52. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/Lumberjack/DDFileLogger.m +1353 -0
  53. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/Lumberjack/DDLog.h +601 -0
  54. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/Lumberjack/DDLog.m +1083 -0
  55. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/Lumberjack/DDTTYLogger.h +167 -0
  56. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/Lumberjack/DDTTYLogger.m +1479 -0
  57. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/Lumberjack/Extensions/ContextFilterLogFormatter.h +65 -0
  58. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/Lumberjack/Extensions/ContextFilterLogFormatter.m +191 -0
  59. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/Lumberjack/Extensions/DispatchQueueLogFormatter.h +116 -0
  60. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/Lumberjack/Extensions/DispatchQueueLogFormatter.m +251 -0
  61. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/ObjectiveMixin/Mixin.h +33 -0
  62. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/ObjectiveMixin/Mixin.m +122 -0
  63. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/Underscore/USArrayWrapper.h +72 -0
  64. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/Underscore/USArrayWrapper.m +305 -0
  65. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/Underscore/USConstants.h +38 -0
  66. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/Underscore/USDictionaryWrapper.h +57 -0
  67. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/Underscore/USDictionaryWrapper.m +188 -0
  68. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/Underscore/Underscore+Functional.h +89 -0
  69. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/Underscore/Underscore+Functional.m +261 -0
  70. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/Underscore/Underscore-Prefix.pch +7 -0
  71. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/Underscore/Underscore.h +50 -0
  72. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/Underscore/Underscore.m +100 -0
  73. data/lib/appjam/generators/templates/blank/EiffelApplication/main.m.tt +18 -0
  74. data/lib/appjam/generators/templates/blank/EiffelApplicationTests/EiffelApplicationTests-Info.plist +22 -0
  75. data/lib/appjam/generators/templates/blank/EiffelApplicationTests/EiffelApplicationTests.h.tt +13 -0
  76. data/lib/appjam/generators/templates/blank/EiffelApplicationTests/EiffelApplicationTests.m.tt +32 -0
  77. data/lib/appjam/generators/templates/blank/EiffelApplicationTests/en.lproj/InfoPlist.strings +2 -0
  78. data/lib/appjam/generators/templates/resources/Default-568h@2x.png +0 -0
  79. data/lib/appjam/generators/templates/resources/Default.png +0 -0
  80. data/lib/appjam/generators/templates/resources/Default@2x.png +0 -0
  81. data/lib/appjam/generators/templates/resources/contents.tt +4 -0
  82. data/lib/appjam/version.rb +1 -1
  83. metadata +462 -326
  84. data/test/helper.rb +0 -132
  85. data/test/test_model_generator.rb +0 -28
  86. data/test/test_project_generator.rb +0 -38
@@ -0,0 +1,37 @@
1
+ //
2
+ // FMDatabaseAdditions.h
3
+ // fmkit
4
+ //
5
+ // Created by August Mueller on 10/30/05.
6
+ // Copyright 2005 Flying Meat Inc.. All rights reserved.
7
+ //
8
+
9
+ #import <Foundation/Foundation.h>
10
+ @interface FMDatabase (FMDatabaseAdditions)
11
+
12
+
13
+ - (int)intForQuery:(NSString*)objs, ...;
14
+ - (long)longForQuery:(NSString*)objs, ...;
15
+ - (BOOL)boolForQuery:(NSString*)objs, ...;
16
+ - (double)doubleForQuery:(NSString*)objs, ...;
17
+ - (NSString*)stringForQuery:(NSString*)objs, ...;
18
+ - (NSData*)dataForQuery:(NSString*)objs, ...;
19
+ - (NSDate*)dateForQuery:(NSString*)objs, ...;
20
+
21
+ // Notice that there's no dataNoCopyForQuery:.
22
+ // That would be a bad idea, because we close out the result set, and then what
23
+ // happens to the data that we just didn't copy? Who knows, not I.
24
+
25
+
26
+ - (BOOL)tableExists:(NSString*)tableName;
27
+ - (FMResultSet*)getSchema;
28
+ - (FMResultSet*)getTableSchema:(NSString*)tableName;
29
+
30
+ - (BOOL)columnExists:(NSString*)columnName inTableWithName:(NSString*)tableName;
31
+
32
+ - (BOOL)validateSQL:(NSString*)sql error:(NSError**)error;
33
+
34
+ // deprecated - use columnExists:inTableWithName: instead.
35
+ - (BOOL)columnExists:(NSString*)tableName columnName:(NSString*)columnName __attribute__ ((deprecated));
36
+
37
+ @end
@@ -0,0 +1,163 @@
1
+ //
2
+ // FMDatabaseAdditions.m
3
+ // fmkit
4
+ //
5
+ // Created by August Mueller on 10/30/05.
6
+ // Copyright 2005 Flying Meat Inc.. All rights reserved.
7
+ //
8
+
9
+ #import "FMDatabase.h"
10
+ #import "FMDatabaseAdditions.h"
11
+
12
+ @interface FMDatabase (PrivateStuff)
13
+ - (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray*)arrayArgs orDictionary:(NSDictionary *)dictionaryArgs orVAList:(va_list)args;
14
+ @end
15
+
16
+ @implementation FMDatabase (FMDatabaseAdditions)
17
+
18
+ #define RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(type, sel) \
19
+ va_list args; \
20
+ va_start(args, query); \
21
+ FMResultSet *resultSet = [self executeQuery:query withArgumentsInArray:0x00 orDictionary:0x00 orVAList:args]; \
22
+ va_end(args); \
23
+ if (![resultSet next]) { return (type)0; } \
24
+ type ret = [resultSet sel:0]; \
25
+ [resultSet close]; \
26
+ [resultSet setParentDB:nil]; \
27
+ return ret;
28
+
29
+
30
+ - (NSString*)stringForQuery:(NSString*)query, ... {
31
+ RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(NSString *, stringForColumnIndex);
32
+ }
33
+
34
+ - (int)intForQuery:(NSString*)query, ... {
35
+ RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(int, intForColumnIndex);
36
+ }
37
+
38
+ - (long)longForQuery:(NSString*)query, ... {
39
+ RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(long, longForColumnIndex);
40
+ }
41
+
42
+ - (BOOL)boolForQuery:(NSString*)query, ... {
43
+ RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(BOOL, boolForColumnIndex);
44
+ }
45
+
46
+ - (double)doubleForQuery:(NSString*)query, ... {
47
+ RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(double, doubleForColumnIndex);
48
+ }
49
+
50
+ - (NSData*)dataForQuery:(NSString*)query, ... {
51
+ RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(NSData *, dataForColumnIndex);
52
+ }
53
+
54
+ - (NSDate*)dateForQuery:(NSString*)query, ... {
55
+ RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(NSDate *, dateForColumnIndex);
56
+ }
57
+
58
+
59
+ - (BOOL)tableExists:(NSString*)tableName {
60
+
61
+ tableName = [tableName lowercaseString];
62
+
63
+ FMResultSet *rs = [self executeQuery:@"select [sql] from sqlite_master where [type] = 'table' and lower(name) = ?", tableName];
64
+
65
+ //if at least one next exists, table exists
66
+ BOOL returnBool = [rs next];
67
+
68
+ //close and free object
69
+ [rs close];
70
+
71
+ return returnBool;
72
+ }
73
+
74
+ /*
75
+ get table with list of tables: result colums: type[STRING], name[STRING],tbl_name[STRING],rootpage[INTEGER],sql[STRING]
76
+ check if table exist in database (patch from OZLB)
77
+ */
78
+ - (FMResultSet*)getSchema {
79
+
80
+ //result colums: type[STRING], name[STRING],tbl_name[STRING],rootpage[INTEGER],sql[STRING]
81
+ FMResultSet *rs = [self executeQuery:@"SELECT type, name, tbl_name, rootpage, sql FROM (SELECT * FROM sqlite_master UNION ALL SELECT * FROM sqlite_temp_master) WHERE type != 'meta' AND name NOT LIKE 'sqlite_%' ORDER BY tbl_name, type DESC, name"];
82
+
83
+ return rs;
84
+ }
85
+
86
+ /*
87
+ get table schema: result colums: cid[INTEGER], name,type [STRING], notnull[INTEGER], dflt_value[],pk[INTEGER]
88
+ */
89
+ - (FMResultSet*)getTableSchema:(NSString*)tableName {
90
+
91
+ //result colums: cid[INTEGER], name,type [STRING], notnull[INTEGER], dflt_value[],pk[INTEGER]
92
+ FMResultSet *rs = [self executeQuery:[NSString stringWithFormat: @"PRAGMA table_info('%@')", tableName]];
93
+
94
+ return rs;
95
+ }
96
+
97
+ - (BOOL)columnExists:(NSString*)columnName inTableWithName:(NSString*)tableName {
98
+
99
+ BOOL returnBool = NO;
100
+
101
+ tableName = [tableName lowercaseString];
102
+ columnName = [columnName lowercaseString];
103
+
104
+ FMResultSet *rs = [self getTableSchema:tableName];
105
+
106
+ //check if column is present in table schema
107
+ while ([rs next]) {
108
+ if ([[[rs stringForColumn:@"name"] lowercaseString] isEqualToString:columnName]) {
109
+ returnBool = YES;
110
+ break;
111
+ }
112
+ }
113
+
114
+ //If this is not done FMDatabase instance stays out of pool
115
+ [rs close];
116
+
117
+ return returnBool;
118
+ }
119
+
120
+ #pragma clang diagnostic push
121
+ #pragma clang diagnostic ignored "-Wdeprecated-implementations"
122
+
123
+ - (BOOL)columnExists:(NSString*)tableName columnName:(NSString*)columnName __attribute__ ((deprecated)) {
124
+ return [self columnExists:columnName inTableWithName:tableName];
125
+ }
126
+
127
+ #pragma clang diagnostic pop
128
+
129
+ - (BOOL)validateSQL:(NSString*)sql error:(NSError**)error {
130
+ sqlite3_stmt *pStmt = NULL;
131
+ BOOL validationSucceeded = YES;
132
+ BOOL keepTrying = YES;
133
+ int numberOfRetries = 0;
134
+
135
+ while (keepTrying == YES) {
136
+ keepTrying = NO;
137
+ int rc = sqlite3_prepare_v2(_db, [sql UTF8String], -1, &pStmt, 0);
138
+ if (rc == SQLITE_BUSY || rc == SQLITE_LOCKED) {
139
+ keepTrying = YES;
140
+ usleep(20);
141
+
142
+ if (_busyRetryTimeout && (numberOfRetries++ > _busyRetryTimeout)) {
143
+ NSLog(@"%s:%d Database busy (%@)", __FUNCTION__, __LINE__, [self databasePath]);
144
+ NSLog(@"Database busy");
145
+ }
146
+ }
147
+ else if (rc != SQLITE_OK) {
148
+ validationSucceeded = NO;
149
+ if (error) {
150
+ *error = [NSError errorWithDomain:NSCocoaErrorDomain
151
+ code:[self lastErrorCode]
152
+ userInfo:[NSDictionary dictionaryWithObject:[self lastErrorMessage]
153
+ forKey:NSLocalizedDescriptionKey]];
154
+ }
155
+ }
156
+ }
157
+
158
+ sqlite3_finalize(pStmt);
159
+
160
+ return validationSucceeded;
161
+ }
162
+
163
+ @end
@@ -0,0 +1,75 @@
1
+ //
2
+ // FMDatabasePool.h
3
+ // fmdb
4
+ //
5
+ // Created by August Mueller on 6/22/11.
6
+ // Copyright 2011 Flying Meat Inc. All rights reserved.
7
+ //
8
+
9
+ #import <Foundation/Foundation.h>
10
+ #import "sqlite3.h"
11
+
12
+ /*
13
+
14
+ ***README OR SUFFER***
15
+ Before using FMDatabasePool, please consider using FMDatabaseQueue instead.
16
+
17
+ If you really really really know what you're doing and FMDatabasePool is what
18
+ you really really need (ie, you're using a read only database), OK you can use
19
+ it. But just be careful not to deadlock!
20
+
21
+ For an example on deadlocking, search for:
22
+ ONLY_USE_THE_POOL_IF_YOU_ARE_DOING_READS_OTHERWISE_YOULL_DEADLOCK_USE_FMDATABASEQUEUE_INSTEAD
23
+ in the main.m file.
24
+
25
+ */
26
+
27
+
28
+
29
+ @class FMDatabase;
30
+
31
+ @interface FMDatabasePool : NSObject {
32
+ NSString *_path;
33
+
34
+ dispatch_queue_t _lockQueue;
35
+
36
+ NSMutableArray *_databaseInPool;
37
+ NSMutableArray *_databaseOutPool;
38
+
39
+ __unsafe_unretained id _delegate;
40
+
41
+ NSUInteger _maximumNumberOfDatabasesToCreate;
42
+ }
43
+
44
+ @property (atomic, retain) NSString *path;
45
+ @property (atomic, assign) id delegate;
46
+ @property (atomic, assign) NSUInteger maximumNumberOfDatabasesToCreate;
47
+
48
+ + (id)databasePoolWithPath:(NSString*)aPath;
49
+ - (id)initWithPath:(NSString*)aPath;
50
+
51
+ - (NSUInteger)countOfCheckedInDatabases;
52
+ - (NSUInteger)countOfCheckedOutDatabases;
53
+ - (NSUInteger)countOfOpenDatabases;
54
+ - (void)releaseAllDatabases;
55
+
56
+ - (void)inDatabase:(void (^)(FMDatabase *db))block;
57
+
58
+ - (void)inTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block;
59
+ - (void)inDeferredTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block;
60
+
61
+ #if SQLITE_VERSION_NUMBER >= 3007000
62
+ // NOTE: you can not nest these, since calling it will pull another database out of the pool and you'll get a deadlock.
63
+ // If you need to nest, use FMDatabase's startSavePointWithName:error: instead.
64
+ - (NSError*)inSavePoint:(void (^)(FMDatabase *db, BOOL *rollback))block;
65
+ #endif
66
+
67
+ @end
68
+
69
+
70
+ @interface NSObject (FMDatabasePoolDelegate)
71
+
72
+ - (BOOL)databasePool:(FMDatabasePool*)pool shouldAddDatabaseToPool:(FMDatabase*)database;
73
+
74
+ @end
75
+
@@ -0,0 +1,244 @@
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
+
9
+ #import "FMDatabasePool.h"
10
+ #import "FMDatabase.h"
11
+
12
+ @interface FMDatabasePool()
13
+
14
+ - (void)pushDatabaseBackInPool:(FMDatabase*)db;
15
+ - (FMDatabase*)db;
16
+
17
+ @end
18
+
19
+
20
+ @implementation FMDatabasePool
21
+ @synthesize path=_path;
22
+ @synthesize delegate=_delegate;
23
+ @synthesize maximumNumberOfDatabasesToCreate=_maximumNumberOfDatabasesToCreate;
24
+
25
+
26
+ + (id)databasePoolWithPath:(NSString*)aPath {
27
+ return FMDBReturnAutoreleased([[self alloc] initWithPath:aPath]);
28
+ }
29
+
30
+ - (id)initWithPath:(NSString*)aPath {
31
+
32
+ self = [super init];
33
+
34
+ if (self != nil) {
35
+ _path = [aPath copy];
36
+ _lockQueue = dispatch_queue_create([[NSString stringWithFormat:@"fmdb.%@", self] UTF8String], NULL);
37
+ _databaseInPool = FMDBReturnRetained([NSMutableArray array]);
38
+ _databaseOutPool = FMDBReturnRetained([NSMutableArray array]);
39
+ }
40
+
41
+ return self;
42
+ }
43
+
44
+ - (void)dealloc {
45
+
46
+ _delegate = 0x00;
47
+ FMDBRelease(_path);
48
+ FMDBRelease(_databaseInPool);
49
+ FMDBRelease(_databaseOutPool);
50
+
51
+ if (_lockQueue) {
52
+ FMDBDispatchQueueRelease(_lockQueue);
53
+ _lockQueue = 0x00;
54
+ }
55
+ #if ! __has_feature(objc_arc)
56
+ [super dealloc];
57
+ #endif
58
+ }
59
+
60
+
61
+ - (void)executeLocked:(void (^)(void))aBlock {
62
+ dispatch_sync(_lockQueue, aBlock);
63
+ }
64
+
65
+ - (void)pushDatabaseBackInPool:(FMDatabase*)db {
66
+
67
+ if (!db) { // db can be null if we set an upper bound on the # of databases to create.
68
+ return;
69
+ }
70
+
71
+ [self executeLocked:^() {
72
+
73
+ if ([_databaseInPool containsObject:db]) {
74
+ [[NSException exceptionWithName:@"Database already in pool" reason:@"The FMDatabase being put back into the pool is already present in the pool" userInfo:nil] raise];
75
+ }
76
+
77
+ [_databaseInPool addObject:db];
78
+ [_databaseOutPool removeObject:db];
79
+
80
+ }];
81
+ }
82
+
83
+ - (FMDatabase*)db {
84
+
85
+ __block FMDatabase *db;
86
+
87
+ [self executeLocked:^() {
88
+ db = [_databaseInPool lastObject];
89
+
90
+ if (db) {
91
+ [_databaseOutPool addObject:db];
92
+ [_databaseInPool removeLastObject];
93
+ }
94
+ else {
95
+
96
+ if (_maximumNumberOfDatabasesToCreate) {
97
+ NSUInteger currentCount = [_databaseOutPool count] + [_databaseInPool count];
98
+
99
+ if (currentCount >= _maximumNumberOfDatabasesToCreate) {
100
+ NSLog(@"Maximum number of databases (%ld) has already been reached!", (long)currentCount);
101
+ return;
102
+ }
103
+ }
104
+
105
+ db = [FMDatabase databaseWithPath:_path];
106
+ }
107
+
108
+ //This ensures that the db is opened before returning
109
+ if ([db open]) {
110
+ if ([_delegate respondsToSelector:@selector(databasePool:shouldAddDatabaseToPool:)] && ![_delegate databasePool:self shouldAddDatabaseToPool:db]) {
111
+ [db close];
112
+ db = 0x00;
113
+ }
114
+ else {
115
+ //It should not get added in the pool twice if lastObject was found
116
+ if (![_databaseOutPool containsObject:db]) {
117
+ [_databaseOutPool addObject:db];
118
+ }
119
+ }
120
+ }
121
+ else {
122
+ NSLog(@"Could not open up the database at path %@", _path);
123
+ db = 0x00;
124
+ }
125
+ }];
126
+
127
+ return db;
128
+ }
129
+
130
+ - (NSUInteger)countOfCheckedInDatabases {
131
+
132
+ __block NSUInteger count;
133
+
134
+ [self executeLocked:^() {
135
+ count = [_databaseInPool count];
136
+ }];
137
+
138
+ return count;
139
+ }
140
+
141
+ - (NSUInteger)countOfCheckedOutDatabases {
142
+
143
+ __block NSUInteger count;
144
+
145
+ [self executeLocked:^() {
146
+ count = [_databaseOutPool count];
147
+ }];
148
+
149
+ return count;
150
+ }
151
+
152
+ - (NSUInteger)countOfOpenDatabases {
153
+ __block NSUInteger count;
154
+
155
+ [self executeLocked:^() {
156
+ count = [_databaseOutPool count] + [_databaseInPool count];
157
+ }];
158
+
159
+ return count;
160
+ }
161
+
162
+ - (void)releaseAllDatabases {
163
+ [self executeLocked:^() {
164
+ [_databaseOutPool removeAllObjects];
165
+ [_databaseInPool removeAllObjects];
166
+ }];
167
+ }
168
+
169
+ - (void)inDatabase:(void (^)(FMDatabase *db))block {
170
+
171
+ FMDatabase *db = [self db];
172
+
173
+ block(db);
174
+
175
+ [self pushDatabaseBackInPool:db];
176
+ }
177
+
178
+ - (void)beginTransaction:(BOOL)useDeferred withBlock:(void (^)(FMDatabase *db, BOOL *rollback))block {
179
+
180
+ BOOL shouldRollback = NO;
181
+
182
+ FMDatabase *db = [self db];
183
+
184
+ if (useDeferred) {
185
+ [db beginDeferredTransaction];
186
+ }
187
+ else {
188
+ [db beginTransaction];
189
+ }
190
+
191
+
192
+ block(db, &shouldRollback);
193
+
194
+ if (shouldRollback) {
195
+ [db rollback];
196
+ }
197
+ else {
198
+ [db commit];
199
+ }
200
+
201
+ [self pushDatabaseBackInPool:db];
202
+ }
203
+
204
+ - (void)inDeferredTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block {
205
+ [self beginTransaction:YES withBlock:block];
206
+ }
207
+
208
+ - (void)inTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block {
209
+ [self beginTransaction:NO withBlock:block];
210
+ }
211
+ #if SQLITE_VERSION_NUMBER >= 3007000
212
+ - (NSError*)inSavePoint:(void (^)(FMDatabase *db, BOOL *rollback))block {
213
+
214
+ static unsigned long savePointIdx = 0;
215
+
216
+ NSString *name = [NSString stringWithFormat:@"savePoint%ld", savePointIdx++];
217
+
218
+ BOOL shouldRollback = NO;
219
+
220
+ FMDatabase *db = [self db];
221
+
222
+ NSError *err = 0x00;
223
+
224
+ if (![db startSavePointWithName:name error:&err]) {
225
+ [self pushDatabaseBackInPool:db];
226
+ return err;
227
+ }
228
+
229
+ block(db, &shouldRollback);
230
+
231
+ if (shouldRollback) {
232
+ [db rollbackToSavePointWithName:name error:&err];
233
+ }
234
+ else {
235
+ [db releaseSavePointWithName:name error:&err];
236
+ }
237
+
238
+ [self pushDatabaseBackInPool:db];
239
+
240
+ return err;
241
+ }
242
+ #endif
243
+
244
+ @end