diff --git a/CoreZen.xcodeproj/project.pbxproj b/CoreZen.xcodeproj/project.pbxproj index 567039d..7ef43a3 100644 --- a/CoreZen.xcodeproj/project.pbxproj +++ b/CoreZen.xcodeproj/project.pbxproj @@ -7,6 +7,12 @@ objects = { /* Begin PBXBuildFile section */ + AA0000020000000000000001 /* Database.h in Headers */ = {isa = PBXBuildFile; fileRef = AA0000010000000000000001 /* Database.h */; settings = {ATTRIBUTES = (Public, ); }; }; + AA0000020000000000000002 /* Database.m in Sources */ = {isa = PBXBuildFile; fileRef = AA0000010000000000000002 /* Database.m */; }; + AA0000020000000000000003 /* Database+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = AA0000010000000000000003 /* Database+Private.h */; }; + AA0000020000000000000004 /* ResultSet.h in Headers */ = {isa = PBXBuildFile; fileRef = AA0000010000000000000004 /* ResultSet.h */; settings = {ATTRIBUTES = (Public, ); }; }; + AA0000020000000000000005 /* ResultSet.m in Sources */ = {isa = PBXBuildFile; fileRef = AA0000010000000000000005 /* ResultSet.m */; }; + AA0000020000000000000006 /* ResultSet+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = AA0000010000000000000006 /* ResultSet+Private.h */; }; 5309C3AE2885A1DC00BC0AAE /* CoreZen.docc in Sources */ = {isa = PBXBuildFile; fileRef = 5309C3AD2885A1DC00BC0AAE /* CoreZen.docc */; }; 5309C3B42885A1DC00BC0AAE /* CoreZen.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5309C3A92885A1DC00BC0AAE /* CoreZen.framework */; }; 5309C3B92885A1DC00BC0AAE /* CoreZenTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5309C3B82885A1DC00BC0AAE /* CoreZenTests.m */; }; @@ -220,6 +226,12 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + AA0000010000000000000001 /* Database.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Database.h; sourceTree = ""; }; + AA0000010000000000000002 /* Database.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Database.m; sourceTree = ""; }; + AA0000010000000000000003 /* Database+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Database+Private.h"; sourceTree = ""; }; + AA0000010000000000000004 /* ResultSet.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ResultSet.h; sourceTree = ""; }; + AA0000010000000000000005 /* ResultSet.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ResultSet.m; sourceTree = ""; }; + AA0000010000000000000006 /* ResultSet+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ResultSet+Private.h"; sourceTree = ""; }; 5309C3A92885A1DC00BC0AAE /* CoreZen.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = CoreZen.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 5309C3AC2885A1DC00BC0AAE /* CoreZen.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CoreZen.h; sourceTree = ""; }; 5309C3AD2885A1DC00BC0AAE /* CoreZen.docc */ = {isa = PBXFileReference; lastKnownFileType = folder.documentationcatalog; path = CoreZen.docc; sourceTree = ""; }; @@ -629,6 +641,9 @@ 5309C4112885B66000BC0AAE /* Database */ = { isa = PBXGroup; children = ( + AA0000010000000000000001 /* Database.h */, + AA0000010000000000000002 /* Database.m */, + AA0000010000000000000003 /* Database+Private.h */, 5309C4122885C86500BC0AAE /* DatabaseQueue.h */, 5309C4132885C86500BC0AAE /* DatabaseQueue.m */, 5309C4232885CDA500BC0AAE /* DatabaseSchema.h */, @@ -636,6 +651,9 @@ 5309C4272885D19400BC0AAE /* DatabaseTable.h */, 5309C41F2885CB1400BC0AAE /* DataTransferObject.h */, 5309C4202885CB1400BC0AAE /* DataTransferObject.m */, + AA0000010000000000000004 /* ResultSet.h */, + AA0000010000000000000005 /* ResultSet.m */, + AA0000010000000000000006 /* ResultSet+Private.h */, ); path = Database; sourceTree = ""; @@ -1081,8 +1099,12 @@ 5309C3F92885A86000BC0AAE /* Identifiable.h in Headers */, 5309C3F12885A74A00BC0AAE /* ObjectIdentifier.h in Headers */, 5309C3EC2885A43100BC0AAE /* PreferenceViewController.h in Headers */, + AA0000020000000000000001 /* Database.h in Headers */, + AA0000020000000000000003 /* Database+Private.h in Headers */, 5309C4252885CDA500BC0AAE /* DatabaseSchema.h in Headers */, 5309C4292885D19400BC0AAE /* DatabaseTable.h in Headers */, + AA0000020000000000000004 /* ResultSet.h in Headers */, + AA0000020000000000000006 /* ResultSet+Private.h in Headers */, 5350F8C22886194200F8CA68 /* MediaFile.h in Headers */, 5309C3E82885A39C00BC0AAE /* PreferencesWindowController.h in Headers */, 538E05072885DD1D00CE9DE7 /* DomainCallbacks.h in Headers */, @@ -1228,7 +1250,9 @@ 532CA22B291B0CFB008FA673 /* LibAVInfoController.m in Sources */, 5396533A288F4DF9007B53EC /* MPVFunctions.m in Sources */, 532CA224291B090E008FA673 /* FrameRenderer.m in Sources */, + AA0000020000000000000002 /* Database.m in Sources */, 5309C4262885CDA500BC0AAE /* DatabaseSchema.m in Sources */, + AA0000020000000000000005 /* ResultSet.m in Sources */, 5309C3AE2885A1DC00BC0AAE /* CoreZen.docc in Sources */, 538E05142885ED2200CE9DE7 /* ObjectRepository.m in Sources */, 5350FB0728889E7400F8CA68 /* Node.m in Sources */, diff --git a/CoreZen/CoreZen.h b/CoreZen/CoreZen.h index 1553961..f02ae28 100644 --- a/CoreZen/CoreZen.h +++ b/CoreZen/CoreZen.h @@ -25,11 +25,12 @@ FOUNDATION_EXPORT const unsigned char CoreZenVersionString[]; #import #pragma mark - Database +#import +#import #import #import #import #import -@import FMDB; #pragma mark - Domain #import diff --git a/CoreZen/Database/Database+Private.h b/CoreZen/Database/Database+Private.h new file mode 100644 index 0000000..dd4f082 --- /dev/null +++ b/CoreZen/Database/Database+Private.h @@ -0,0 +1,23 @@ +// +// Database+Private.h +// CoreZen +// +// Created by Zach Nelson on 4/1/26. +// + +#import "Database.h" + +@class FMDatabase; + +@interface ZENDatabase (Private) + ++ (instancetype)databaseWithFMDatabase:(FMDatabase *)fmDatabase; + +- (void)beginTransaction; +- (void)commit; +- (void)rollback; + +- (void)setShouldCacheStatements:(BOOL)value; +- (void)setTraceExecution:(BOOL)value; + +@end diff --git a/CoreZen/Database/Database.h b/CoreZen/Database/Database.h new file mode 100644 index 0000000..f1a0d16 --- /dev/null +++ b/CoreZen/Database/Database.h @@ -0,0 +1,22 @@ +// +// Database.h +// CoreZen +// +// Created by Zach Nelson on 4/1/26. +// + +#import + +@class ZENResultSet; + +@interface ZENDatabase : NSObject + +- (BOOL)executeUpdate:(NSString *)sql, ...; +- (BOOL)executeUpdate:(NSString *)sql withArgumentsInArray:(NSArray *)arguments; + +- (ZENResultSet *)executeQuery:(NSString *)sql, ...; +- (ZENResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray *)arguments; + +- (NSString *)lastErrorMessage; + +@end diff --git a/CoreZen/Database/Database.m b/CoreZen/Database/Database.m new file mode 100644 index 0000000..effccfa --- /dev/null +++ b/CoreZen/Database/Database.m @@ -0,0 +1,85 @@ +// +// Database.m +// CoreZen +// +// Created by Zach Nelson on 4/1/26. +// + +#import "Database.h" +#import "Database+Private.h" +#import "ResultSet+Private.h" + +@import FMDB; + +@interface ZENDatabase () +@property (nonatomic, strong, readonly) FMDatabase *fmDatabase; +@end + +@implementation ZENDatabase + ++ (instancetype)databaseWithFMDatabase:(FMDatabase *)fmDatabase { + ZENDatabase *db = [[ZENDatabase alloc] init]; + if (db) { + db->_fmDatabase = fmDatabase; + } + return db; +} + +#pragma mark - Updates + +- (BOOL)executeUpdate:(NSString *)sql, ... { + va_list args; + va_start(args, sql); + BOOL result = [self.fmDatabase executeUpdate:sql withVAList:args]; + va_end(args); + return result; +} + +- (BOOL)executeUpdate:(NSString *)sql withArgumentsInArray:(NSArray *)arguments { + return [self.fmDatabase executeUpdate:sql withArgumentsInArray:arguments]; +} + +#pragma mark - Queries + +- (ZENResultSet *)executeQuery:(NSString *)sql, ... { + va_list args; + va_start(args, sql); + FMResultSet *rs = [self.fmDatabase executeQuery:sql withVAList:args]; + va_end(args); + return rs ? [ZENResultSet resultSetWithFMResultSet:rs] : nil; +} + +- (ZENResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray *)arguments { + FMResultSet *rs = [self.fmDatabase executeQuery:sql withArgumentsInArray:arguments]; + return rs ? [ZENResultSet resultSetWithFMResultSet:rs] : nil; +} + +#pragma mark - Error + +- (NSString *)lastErrorMessage { + return [self.fmDatabase lastErrorMessage]; +} + +#pragma mark - Private + +- (void)beginTransaction { + [self.fmDatabase beginTransaction]; +} + +- (void)commit { + [self.fmDatabase commit]; +} + +- (void)rollback { + [self.fmDatabase rollback]; +} + +- (void)setShouldCacheStatements:(BOOL)value { + [self.fmDatabase setShouldCacheStatements:value]; +} + +- (void)setTraceExecution:(BOOL)value { + [self.fmDatabase setTraceExecution:value]; +} + +@end diff --git a/CoreZen/Database/DatabaseQueue.h b/CoreZen/Database/DatabaseQueue.h index e5c4ece..46dbbff 100644 --- a/CoreZen/Database/DatabaseQueue.h +++ b/CoreZen/Database/DatabaseQueue.h @@ -7,9 +7,9 @@ #import -@class FMDatabase; +@class ZENDatabase; -typedef void (^ZENDatabaseBlock)(FMDatabase *database); +typedef void (^ZENDatabaseBlock)(ZENDatabase *database); @interface ZENDatabaseQueue : NSObject diff --git a/CoreZen/Database/DatabaseQueue.m b/CoreZen/Database/DatabaseQueue.m index 750b970..509d16b 100644 --- a/CoreZen/Database/DatabaseQueue.m +++ b/CoreZen/Database/DatabaseQueue.m @@ -6,6 +6,7 @@ // #import "DatabaseQueue.h" +#import "Database+Private.h" #import "WorkQueue.h" #import @@ -17,7 +18,7 @@ @interface ZENDatabaseQueue () - (void)internalInit:(NSString *)queueLabel; - (instancetype)initInMemory; - (instancetype)initWithURL:(NSURL *)URL; -- (FMDatabase *)threadDatabase; +- (ZENDatabase *)threadDatabase; @property (nonatomic, strong, readonly) NSURL *databaseURL; @property (nonatomic, copy, readonly) NSString *databaseKey; @@ -80,7 +81,7 @@ - (void)shutdown:(ZENDatabaseBlock)updateBlock { [self.workQueue terminate:^{ if (updateBlock) { @autoreleasepool { - FMDatabase *database = self.threadDatabase; + ZENDatabase *database = self.threadDatabase; updateBlock(database); } } @@ -88,27 +89,30 @@ - (void)shutdown:(ZENDatabaseBlock)updateBlock { }]; } -- (FMDatabase *)threadDatabase { - // Make an instance of FMDatabase for the thread, store it in the thread dictionary. +- (ZENDatabase *)threadDatabase { + // Make an instance of ZENDatabase for the thread, store it in the thread dictionary. // FMDB wants a different database instance per thread, and serial queue may run on different threads. // (Serial queue is guaranteed to be serial, not necessary on a single thread.) NSMutableDictionary *threadDictionary = NSThread.currentThread.threadDictionary; - FMDatabase *database = [threadDictionary objectForKey:self.databaseKey]; + ZENDatabase *database = [threadDictionary objectForKey:self.databaseKey]; if (database == nil) { NSLog(@"Creating database for thread %@ at %@", [NSThread currentThread], self.databaseURL); + FMDatabase *fmdb; if (self.databaseURL) { - database = [FMDatabase databaseWithURL:self.databaseURL]; + fmdb = [FMDatabase databaseWithURL:self.databaseURL]; } else { - database = [FMDatabase databaseWithPath:self.databaseKey]; + fmdb = [FMDatabase databaseWithPath:self.databaseKey]; } - if (![database open]) { + if (![fmdb open]) { NSLog(@"ERROR: Failed to open database at %@", self.databaseURL); return nil; } + + database = [ZENDatabase databaseWithFMDatabase:fmdb]; [database executeUpdate:@"PRAGMA synchronous = 1;"]; [database setShouldCacheStatements:YES]; @@ -125,7 +129,7 @@ - (void)transactionAsync:(ZENDatabaseBlock)updateBlock { [self.workQueue async:^(ZENWorkQueueToken *canceled) { if (!canceled.canceled) { @autoreleasepool { - FMDatabase *database = self.threadDatabase; + ZENDatabase *database = self.threadDatabase; [database beginTransaction]; updateBlock(database); [database commit]; @@ -137,7 +141,7 @@ - (void)transactionAsync:(ZENDatabaseBlock)updateBlock { - (void)transactionSync:(ZENDatabaseBlock)updateBlock { [self.workQueue sync:^{ @autoreleasepool { - FMDatabase *database = self.threadDatabase; + ZENDatabase *database = self.threadDatabase; [database beginTransaction]; updateBlock(database); [database commit]; @@ -149,7 +153,7 @@ - (void)fetchAsync:(ZENDatabaseBlock)fetchBlock { [self.workQueue async:^(ZENWorkQueueToken *canceled) { if (!canceled.canceled) { @autoreleasepool { - FMDatabase *database = self.threadDatabase; + ZENDatabase *database = self.threadDatabase; fetchBlock(database); } } @@ -159,7 +163,7 @@ - (void)fetchAsync:(ZENDatabaseBlock)fetchBlock { - (void)fetchSync:(ZENDatabaseBlock)fetchBlock { [self.workQueue sync:^{ @autoreleasepool { - FMDatabase *database = self.threadDatabase; + ZENDatabase *database = self.threadDatabase; fetchBlock(database); } }]; @@ -169,7 +173,7 @@ - (void)vacuumAsync { [self.workQueue async:^(ZENWorkQueueToken *canceled) { if (!canceled.canceled) { @autoreleasepool { - FMDatabase *database = self.threadDatabase; + ZENDatabase *database = self.threadDatabase; [database executeUpdate:@"VACUUM;"]; } } diff --git a/CoreZen/Database/DatabaseSchema.h b/CoreZen/Database/DatabaseSchema.h index d4b997c..629ce34 100644 --- a/CoreZen/Database/DatabaseSchema.h +++ b/CoreZen/Database/DatabaseSchema.h @@ -7,12 +7,12 @@ #import -@class FMDatabase; +@class ZENDatabase; @interface ZENDatabaseSchema : NSObject + (instancetype)schemaWithTableClasses:(NSArray *)tables; -- (void)initializeDatabase:(FMDatabase *)database; +- (void)initializeDatabase:(ZENDatabase *)database; @end diff --git a/CoreZen/Database/DatabaseSchema.m b/CoreZen/Database/DatabaseSchema.m index 58aeb68..95017c8 100644 --- a/CoreZen/Database/DatabaseSchema.m +++ b/CoreZen/Database/DatabaseSchema.m @@ -7,10 +7,10 @@ #import "DatabaseSchema.h" #import "DatabaseTable.h" +#import "Database+Private.h" +#import "ResultSet.h" #import "ObjectIdentifier.h" -@import FMDB; - @interface ZENDatabaseSchema () @property (nonatomic, strong) NSArray *tableClasses; @@ -19,8 +19,8 @@ - (instancetype)initWithTableClasses:(NSArray *)tableClasses; - (NSArray *)tableNames; -- (BOOL)updateDatabaseSchema:(FMDatabase *)database; -- (void)initializeIdentifiers:(FMDatabase *)database; +- (BOOL)updateDatabaseSchema:(ZENDatabase *)database; +- (void)initializeIdentifiers:(ZENDatabase *)database; @end @@ -38,7 +38,7 @@ + (instancetype)schemaWithTableClasses:(NSArray *)tables { return [[ZENDatabaseSchema alloc] initWithTableClasses:tables]; } -- (void)initializeDatabase:(FMDatabase *)database { +- (void)initializeDatabase:(ZENDatabase *)database { // Update the database schema to the latest version [database beginTransaction]; if ([self updateDatabaseSchema:database]) { @@ -58,9 +58,9 @@ - (NSArray *)tableNames { return tableNames; } -- (BOOL)updateDatabaseSchema:(FMDatabase *)database { +- (BOOL)updateDatabaseSchema:(ZENDatabase *)database { NSUInteger startingVersion = 0; - FMResultSet *rs = [database executeQuery:@"PRAGMA user_version"]; + ZENResultSet *rs = [database executeQuery:@"PRAGMA user_version"]; if ([rs next]) { startingVersion = [rs unsignedLongLongIntForColumnIndex:0]; } @@ -89,10 +89,10 @@ - (BOOL)updateDatabaseSchema:(FMDatabase *)database { return versionChanged; } -- (void)initializeIdentifiers:(FMDatabase *)database { +- (void)initializeIdentifiers:(ZENDatabase *)database { for (NSString *tableName in self.tableNames) { NSString *statement = [NSString stringWithFormat:@"SELECT identifier FROM %@ ORDER BY identifier DESC LIMIT 1;", tableName]; - FMResultSet *rs = [database executeQuery:statement]; + ZENResultSet *rs = [database executeQuery:statement]; if ([rs next]) { ZENIdentifier largestIdentifier = [rs longLongIntForColumnIndex:0]; NSLog(@"Setting largest identifier to %lli (from %@)", largestIdentifier, tableName); diff --git a/CoreZen/Database/DatabaseTable.h b/CoreZen/Database/DatabaseTable.h index d00c85b..0444dad 100644 --- a/CoreZen/Database/DatabaseTable.h +++ b/CoreZen/Database/DatabaseTable.h @@ -7,8 +7,8 @@ #import -@class FMDatabase; -@class FMResultSet; +@class ZENDatabase; +@class ZENResultSet; @class ZENDataTransferObject; #import @@ -19,41 +19,41 @@ + (NSString *)tableName; -+ (BOOL)updateSchema:(FMDatabase *)database ++ (BOOL)updateSchema:(ZENDatabase *)database version:(NSUInteger)version; #pragma mark - Create - (BOOL)insertDTO:(ZENDataTransferObject *)dto - database:(FMDatabase *)database; + database:(ZENDatabase *)database; #pragma mark - Update - (BOOL)updateDTO:(ZENDataTransferObject *)dto - database:(FMDatabase *)database; + database:(ZENDatabase *)database; #pragma mark - Delete - (BOOL)deleteByIdentifier:(ZENIdentifier)identifier - database:(FMDatabase *)database; + database:(ZENDatabase *)database; #pragma mark - Read -- (ZENDataTransferObject *)dtoFromRow:(FMResultSet *)row; +- (ZENDataTransferObject *)dtoFromRow:(ZENResultSet *)row; -- (FMResultSet *)allRows:(FMDatabase *)database; +- (ZENResultSet *)allRows:(ZENDatabase *)database; -- (FMResultSet *)rowByIdentifier:(ZENIdentifier)identifier - database:(FMDatabase *)database; +- (ZENResultSet *)rowByIdentifier:(ZENIdentifier)identifier + database:(ZENDatabase *)database; #pragma mark - Count -- (NSUInteger)countAllRows:(FMDatabase *)database; +- (NSUInteger)countAllRows:(ZENDatabase *)database; #pragma mark - [optional] Count @optional -- (NSUInteger)sumAllVideoDuration:(FMDatabase *)database; +- (NSUInteger)sumAllVideoDuration:(ZENDatabase *)database; @end diff --git a/CoreZen/Database/ResultSet+Private.h b/CoreZen/Database/ResultSet+Private.h new file mode 100644 index 0000000..eb299a9 --- /dev/null +++ b/CoreZen/Database/ResultSet+Private.h @@ -0,0 +1,16 @@ +// +// ResultSet+Private.h +// CoreZen +// +// Created by Zach Nelson on 4/1/26. +// + +#import "ResultSet.h" + +@class FMResultSet; + +@interface ZENResultSet (Private) + ++ (instancetype)resultSetWithFMResultSet:(FMResultSet *)fmResultSet; + +@end diff --git a/CoreZen/Database/ResultSet.h b/CoreZen/Database/ResultSet.h new file mode 100644 index 0000000..079c76c --- /dev/null +++ b/CoreZen/Database/ResultSet.h @@ -0,0 +1,37 @@ +// +// ResultSet.h +// CoreZen +// +// Created by Zach Nelson on 4/1/26. +// + +#import + +@interface ZENResultSet : NSObject + +- (BOOL)next; +- (void)close; + +#pragma mark - By column index + +- (int)intForColumnIndex:(int)columnIdx; +- (long long)longLongIntForColumnIndex:(int)columnIdx; +- (unsigned long long)unsignedLongLongIntForColumnIndex:(int)columnIdx; +- (double)doubleForColumnIndex:(int)columnIdx; +- (BOOL)boolForColumnIndex:(int)columnIdx; +- (NSString *)stringForColumnIndex:(int)columnIdx; +- (NSData *)dataForColumnIndex:(int)columnIdx; +- (NSDate *)dateForColumnIndex:(int)columnIdx; + +#pragma mark - By column name + +- (int)intForColumn:(NSString *)columnName; +- (long long)longLongIntForColumn:(NSString *)columnName; +- (unsigned long long)unsignedLongLongIntForColumn:(NSString *)columnName; +- (double)doubleForColumn:(NSString *)columnName; +- (BOOL)boolForColumn:(NSString *)columnName; +- (NSString *)stringForColumn:(NSString *)columnName; +- (NSData *)dataForColumn:(NSString *)columnName; +- (NSDate *)dateForColumn:(NSString *)columnName; + +@end diff --git a/CoreZen/Database/ResultSet.m b/CoreZen/Database/ResultSet.m new file mode 100644 index 0000000..cb8b519 --- /dev/null +++ b/CoreZen/Database/ResultSet.m @@ -0,0 +1,98 @@ +// +// ResultSet.m +// CoreZen +// +// Created by Zach Nelson on 4/1/26. +// + +#import "ResultSet.h" +#import "ResultSet+Private.h" + +@import FMDB; + +@interface ZENResultSet () +@property (nonatomic, strong, readonly) FMResultSet *fmResultSet; +@end + +@implementation ZENResultSet + ++ (instancetype)resultSetWithFMResultSet:(FMResultSet *)fmResultSet { + ZENResultSet *rs = [[ZENResultSet alloc] init]; + if (rs) { + rs->_fmResultSet = fmResultSet; + } + return rs; +} + +- (BOOL)next { return [self.fmResultSet next]; } +- (void)close { [self.fmResultSet close]; } + +#pragma mark - By column index + +- (int)intForColumnIndex:(int)columnIdx { + return [self.fmResultSet intForColumnIndex:columnIdx]; +} + +- (long long)longLongIntForColumnIndex:(int)columnIdx { + return [self.fmResultSet longLongIntForColumnIndex:columnIdx]; +} + +- (unsigned long long)unsignedLongLongIntForColumnIndex:(int)columnIdx { + return [self.fmResultSet unsignedLongLongIntForColumnIndex:columnIdx]; +} + +- (double)doubleForColumnIndex:(int)columnIdx { + return [self.fmResultSet doubleForColumnIndex:columnIdx]; +} + +- (BOOL)boolForColumnIndex:(int)columnIdx { + return [self.fmResultSet boolForColumnIndex:columnIdx]; +} + +- (NSString *)stringForColumnIndex:(int)columnIdx { + return [self.fmResultSet stringForColumnIndex:columnIdx]; +} + +- (NSData *)dataForColumnIndex:(int)columnIdx { + return [self.fmResultSet dataForColumnIndex:columnIdx]; +} + +- (NSDate *)dateForColumnIndex:(int)columnIdx { + return [self.fmResultSet dateForColumnIndex:columnIdx]; +} + +#pragma mark - By column name + +- (int)intForColumn:(NSString *)columnName { + return [self.fmResultSet intForColumn:columnName]; +} + +- (long long)longLongIntForColumn:(NSString *)columnName { + return [self.fmResultSet longLongIntForColumn:columnName]; +} + +- (unsigned long long)unsignedLongLongIntForColumn:(NSString *)columnName { + return [self.fmResultSet unsignedLongLongIntForColumn:columnName]; +} + +- (double)doubleForColumn:(NSString *)columnName { + return [self.fmResultSet doubleForColumn:columnName]; +} + +- (BOOL)boolForColumn:(NSString *)columnName { + return [self.fmResultSet boolForColumn:columnName]; +} + +- (NSString *)stringForColumn:(NSString *)columnName { + return [self.fmResultSet stringForColumn:columnName]; +} + +- (NSData *)dataForColumn:(NSString *)columnName { + return [self.fmResultSet dataForColumn:columnName]; +} + +- (NSDate *)dateForColumn:(NSString *)columnName { + return [self.fmResultSet dateForColumn:columnName]; +} + +@end diff --git a/CoreZen/Domain/ObjectRepository.m b/CoreZen/Domain/ObjectRepository.m index e115019..4d17e33 100644 --- a/CoreZen/Domain/ObjectRepository.m +++ b/CoreZen/Domain/ObjectRepository.m @@ -9,10 +9,10 @@ #import "ObjectCache.h" #import "DatabaseTable.h" #import "DatabaseQueue.h" +#import "Database.h" +#import "ResultSet.h" #import "DomainCommon.h" -@import FMDB; - @interface ZENObjectRepository () @property (nonatomic, strong, readonly) NSObject *table; @@ -21,14 +21,12 @@ @interface ZENObjectRepository () @property (nonatomic, strong, readonly) ZENObjectCache *cache; @property (nonatomic, weak, readonly) id dataModel; -// Runs asynchronously on a thread pool. - // Runs synchronously. To be called on database queue. -- (id)createObjectFromRow:(FMResultSet *)row; +- (id)createObjectFromRow:(ZENResultSet *)row; // Runs synchronously. To be called on database queue. - (id)fetchObjectByIdentifier:(ZENIdentifier)identifier - database:(FMDatabase *)database; + database:(ZENDatabase *)database; @end @@ -54,7 +52,7 @@ - (instancetype)initWithDataModel:(id)dataModel #pragma mark - [private] Create -- (id)createObjectFromRow:(FMResultSet *)row { +- (id)createObjectFromRow:(ZENResultSet *)row { ZENDataTransferObject *dto = [self.table dtoFromRow:row]; id object = [[(Class)self.embryo alloc] initWithDTO:dto]; return object; @@ -63,9 +61,9 @@ - (instancetype)initWithDataModel:(id)dataModel #pragma mark - [private] Fetch - (id)fetchObjectByIdentifier:(ZENIdentifier)identifier - database:(FMDatabase *)database { + database:(ZENDatabase *)database { - FMResultSet *rs = [self.table rowByIdentifier:identifier database:database]; + ZENResultSet *rs = [self.table rowByIdentifier:identifier database:database]; id object = nil; if ([rs next]) { object = [self createObjectFromRow:rs]; @@ -77,7 +75,7 @@ - (instancetype)initWithDataModel:(id)dataModel #pragma mark - Count - (void)countAllObjects:(ZENAsyncCountCompletionBlock)countBlock { - [self.queue fetchAsync:^(FMDatabase *database) { + [self.queue fetchAsync:^(ZENDatabase *database) { NSUInteger count = [self.table countAllRows:database]; ZENCallAsyncCountCompletionBlockOnThreadPool(countBlock, count); }]; @@ -92,7 +90,7 @@ - (void)countAllObjectsForUI:(ZENAsyncCountCompletionBlock)countBlock { - (void)sumAllVideoDuration:(ZENAsyncCountCompletionBlock)countBlock { if ([self.table respondsToSelector:@selector(sumAllVideoDuration:)]) { - [self.queue fetchAsync:^(FMDatabase *database) { + [self.queue fetchAsync:^(ZENDatabase *database) { NSUInteger count = [self.table sumAllVideoDuration:database]; ZENCallAsyncCountCompletionBlockOnThreadPool(countBlock, count); }]; @@ -121,7 +119,7 @@ - (void)fetchObjectByIdentifier:(ZENIdentifier)identifier } // Bounce to the database queue to fetch this object - [self.queue fetchAsync:^(FMDatabase *database) { + [self.queue fetchAsync:^(ZENDatabase *database) { // Check again if this object has shown up in the cache since we looked earlier id object = [self.cache cachedObject:identifier]; @@ -159,9 +157,9 @@ - (void)fetchObjectByIdentifier:(ZENIdentifier)identifier - (void)fetchAllObjects:(ZENFetchResultsBlock)resultsBlock { // We can't rely on the cache for early return like in objectByIdentifier: because we don't know // the full list of the object identifiers without a query. - [self.queue fetchAsync:^(FMDatabase *database) { + [self.queue fetchAsync:^(ZENDatabase *database) { NSMutableArray *objects = [NSMutableArray array]; - FMResultSet *rs = [self.table allRows:database]; + ZENResultSet *rs = [self.table allRows:database]; while ([rs next]) { // Check if an object with this identifier is in the cache // TODO: Consider batching all identifiers together to a single cache call @@ -202,7 +200,7 @@ - (void)addObject:(ZENDomainObject *)domainObject ZENObjectRepositoryNotificationObjectKey: domainObject }; - [self.queue transactionAsync:^(FMDatabase *database) { + [self.queue transactionAsync:^(ZENDatabase *database) { if ([self.table insertDTO:domainObject.basicDTO database:database]) { [self.cache cacheObject:domainObject]; ZENDeliverNotificationOnMainThread(ZENObjectRepositoryObjectAddedNotification, self, notificationData); @@ -241,7 +239,7 @@ - (void)updateObject:(ZENDomainObject *)domainObject ZENObjectRepositoryNotificationObjectKey: domainObject }; - [self.queue transactionAsync:^(FMDatabase *database) { + [self.queue transactionAsync:^(ZENDatabase *database) { [self.table updateDTO:domainObject.basicDTO database:database]; ZENDeliverNotificationOnMainThread(ZENObjectRepositoryObjectUpdatedNotification, self, notificationData); ZENCallAsyncContinueBlockOnThreadPool(completion); @@ -264,7 +262,7 @@ - (void)deleteObject:(ZENDomainObject *)domainObject ZENObjectRepositoryNotificationObjectKey: domainObject }; - [self.queue transactionAsync:^(FMDatabase *database) { + [self.queue transactionAsync:^(ZENDatabase *database) { if ([self.table deleteByIdentifier:domainObject.identifier database:database]) { [self.cache removeObject:domainObject.identifier]; ZENDeliverNotificationOnMainThread(ZENObjectRepositoryObjectDeletedNotification, self, notificationData);