From 1daeb29efc7f2ecbcc07fcd0c9b9aaf8069f7ab6 Mon Sep 17 00:00:00 2001 From: Thomas Andersen Date: Mon, 1 Jul 2013 18:41:42 +0200 Subject: [PATCH 1/6] SharedGroup error handling done. --- .../TightDbObjcDyn.xcodeproj/project.pbxproj | 8 +- src/tightdb/objc/group_objc.mm | 14 +-- src/tightdb/objc/group_shared.h | 7 +- src/tightdb/objc/group_shared_objc.mm | 85 ++++++++++--------- src/tightdb/objc/query_objc.mm | 52 ++++++------ src/tightdb/objc/table_objc.mm | 68 +++++++-------- .../test/{shared_group.m => shared_group.mm} | 38 ++++----- src/tightdb/objc/util.hpp | 10 +-- 8 files changed, 142 insertions(+), 140 deletions(-) rename src/tightdb/objc/test/{shared_group.m => shared_group.mm} (76%) diff --git a/TightDbObjcDyn/TightDbObjcDyn.xcodeproj/project.pbxproj b/TightDbObjcDyn/TightDbObjcDyn.xcodeproj/project.pbxproj index d13d513305..e6f2a0151c 100644 --- a/TightDbObjcDyn/TightDbObjcDyn.xcodeproj/project.pbxproj +++ b/TightDbObjcDyn/TightDbObjcDyn.xcodeproj/project.pbxproj @@ -37,7 +37,7 @@ E91890FA177B71E400653D7A /* group.m in Sources */ = {isa = PBXBuildFile; fileRef = E91890EC177B71E400653D7A /* group.m */; }; E91890FB177B71E400653D7A /* mixed.m in Sources */ = {isa = PBXBuildFile; fileRef = E91890ED177B71E400653D7A /* mixed.m */; }; E91890FC177B71E400653D7A /* query.m in Sources */ = {isa = PBXBuildFile; fileRef = E91890EE177B71E400653D7A /* query.m */; }; - E91890FD177B71E400653D7A /* shared_group.m in Sources */ = {isa = PBXBuildFile; fileRef = E91890EF177B71E400653D7A /* shared_group.m */; }; + E91890FD177B71E400653D7A /* shared_group.mm in Sources */ = {isa = PBXBuildFile; fileRef = E91890EF177B71E400653D7A /* shared_group.mm */; }; E91890FE177B71E400653D7A /* subtable.m in Sources */ = {isa = PBXBuildFile; fileRef = E91890F0177B71E400653D7A /* subtable.m */; }; E91890FF177B71E400653D7A /* table_delete_all.m in Sources */ = {isa = PBXBuildFile; fileRef = E91890F1177B71E400653D7A /* table_delete_all.m */; }; E9189100177B71E400653D7A /* table.m in Sources */ = {isa = PBXBuildFile; fileRef = E91890F2177B71E400653D7A /* table.m */; }; @@ -91,7 +91,7 @@ E91890EC177B71E400653D7A /* group.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = group.m; path = ../../src/tightdb/objc/test/group.m; sourceTree = ""; }; E91890ED177B71E400653D7A /* mixed.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = mixed.m; path = ../../src/tightdb/objc/test/mixed.m; sourceTree = ""; }; E91890EE177B71E400653D7A /* query.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = query.m; path = ../../src/tightdb/objc/test/query.m; sourceTree = ""; }; - E91890EF177B71E400653D7A /* shared_group.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = shared_group.m; path = ../../src/tightdb/objc/test/shared_group.m; sourceTree = ""; }; + E91890EF177B71E400653D7A /* shared_group.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = shared_group.mm; path = ../../src/tightdb/objc/test/shared_group.mm; sourceTree = ""; }; E91890F0177B71E400653D7A /* subtable.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = subtable.m; path = ../../src/tightdb/objc/test/subtable.m; sourceTree = ""; }; E91890F1177B71E400653D7A /* table_delete_all.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = table_delete_all.m; path = ../../src/tightdb/objc/test/table_delete_all.m; sourceTree = ""; }; E91890F2177B71E400653D7A /* table.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = table.m; path = ../../src/tightdb/objc/test/table.m; sourceTree = ""; }; @@ -204,7 +204,7 @@ E91890EC177B71E400653D7A /* group.m */, E91890ED177B71E400653D7A /* mixed.m */, E91890EE177B71E400653D7A /* query.m */, - E91890EF177B71E400653D7A /* shared_group.m */, + E91890EF177B71E400653D7A /* shared_group.mm */, E91890F0177B71E400653D7A /* subtable.m */, E91890F1177B71E400653D7A /* table_delete_all.m */, E91890F2177B71E400653D7A /* table.m */, @@ -364,7 +364,7 @@ E91890FA177B71E400653D7A /* group.m in Sources */, E91890FB177B71E400653D7A /* mixed.m in Sources */, E91890FC177B71E400653D7A /* query.m in Sources */, - E91890FD177B71E400653D7A /* shared_group.m in Sources */, + E91890FD177B71E400653D7A /* shared_group.mm in Sources */, E91890FE177B71E400653D7A /* subtable.m in Sources */, E91890FF177B71E400653D7A /* table_delete_all.m in Sources */, E9189100177B71E400653D7A /* table.m in Sources */, diff --git a/src/tightdb/objc/group_objc.mm b/src/tightdb/objc/group_objc.mm index 6045d1a2b4..0b044e9532 100644 --- a/src/tightdb/objc/group_objc.mm +++ b/src/tightdb/objc/group_objc.mm @@ -34,7 +34,7 @@ +(TightdbGroup *)groupWithError:(NSError *__autoreleasing *)error TightdbGroup *group = [[TightdbGroup alloc] init]; TIGHTDB_EXCEPTION_ERRHANDLER( group.group = new tightdb::Group(); - , @"com.tightdb.group", nil); + , @"com.tightdb.group", return nil); group.readOnly = NO; return group; } @@ -59,7 +59,7 @@ +(TightdbGroup *)groupWithFilename:(NSString *)filename error:(NSError **)error tightdb::Group* group; TIGHTDB_EXCEPTION_ERRHANDLER( group = new tightdb::Group(tightdb::StringData(ObjcStringAccessor(filename))); - , @"com.tightdb.group", nil); + , @"com.tightdb.group", return nil); TightdbGroup* group2 = [[TightdbGroup alloc] init]; if (group2) { group2.group = group; @@ -78,7 +78,7 @@ +(TightdbGroup *)groupWithBuffer:(const char *)data size:(size_t)size error:(NSE tightdb::Group* group; TIGHTDB_EXCEPTION_ERRHANDLER( group = new tightdb::Group(tightdb::BinaryData(data, size)); - , @"com.tightdb.group", nil); + , @"com.tightdb.group", return nil); TightdbGroup* group2 = [[TightdbGroup alloc] init]; group2.group = group; group2.readOnly = NO; @@ -117,7 +117,7 @@ -(BOOL)write:(NSString *)filePath error:(NSError *__autoreleasing *)error { TIGHTDB_EXCEPTION_ERRHANDLER( _group->write(tightdb::StringData(ObjcStringAccessor(filePath))); - , @"com.tightdb.group", NO); + , @"com.tightdb.group", return NO); return YES; } @@ -132,7 +132,7 @@ -(const char*)writeToMem:(size_t*)size error:(NSError *__autoreleasing *)error tightdb::BinaryData buffer = _group->write_to_mem(); *size = buffer.size(); return buffer.data(); - , @"com.tightdb.group", nil); + , @"com.tightdb.group", return nil); } -(BOOL)hasTable:(NSString *)name @@ -161,7 +161,7 @@ -(id)getTable:(NSString *)name error:(NSError *__autoreleasing *)error if (TIGHTDB_UNLIKELY(!table)) return nil; TIGHTDB_EXCEPTION_ERRHANDLER( [table setTable:_group->get_table(ObjcStringAccessor(name))]; - , @"com.tightdb.group", nil); + , @"com.tightdb.group", return nil); [table setParent:self]; [table setReadOnly:_readOnly]; return table; @@ -181,7 +181,7 @@ -(id)getTable:(NSString *)name withClass:(__unsafe_unretained Class)classObj err tightdb::TableRef r = tightdb::LangBindHelper::get_table_ptr(_group, ObjcStringAccessor(name), was_created)->get_table_ref(); [table setTable:move(r)]; - , @"com.tightdb.group", nil); + , @"com.tightdb.group", return nil); [table setParent:self]; [table setReadOnly:_readOnly]; if (was_created) { diff --git a/src/tightdb/objc/group_shared.h b/src/tightdb/objc/group_shared.h index 61f6f5b555..7b71485dfb 100644 --- a/src/tightdb/objc/group_shared.h +++ b/src/tightdb/objc/group_shared.h @@ -26,8 +26,11 @@ typedef BOOL(^TightdbSharedGroupWriteTransactionBlock)(TightdbGroup *group); @interface TightdbSharedGroup: NSObject +(TightdbSharedGroup *)groupWithFilename:(NSString *)filename; ++(TightdbSharedGroup *)groupWithFilename:(NSString *)filename error:(NSError *__autoreleasing *)error; --(void)readTransaction:(TightdbSharedGroupReadTransactionBlock)block; --(void)writeTransaction:(TightdbSharedGroupWriteTransactionBlock)block; +-(BOOL)readTransaction:(TightdbSharedGroupReadTransactionBlock)block; +-(BOOL)readTransaction:(TightdbSharedGroupReadTransactionBlock)block error:(NSError *__autoreleasing *)error; +-(BOOL)writeTransaction:(TightdbSharedGroupWriteTransactionBlock)block; +-(BOOL)writeTransaction:(TightdbSharedGroupWriteTransactionBlock)block error:(NSError *__autoreleasing *)error; @end diff --git a/src/tightdb/objc/group_shared_objc.mm b/src/tightdb/objc/group_shared_objc.mm index d91d642ea2..922aef1abd 100644 --- a/src/tightdb/objc/group_shared_objc.mm +++ b/src/tightdb/objc/group_shared_objc.mm @@ -14,22 +14,18 @@ @implementation TightdbSharedGroup } +(TightdbSharedGroup *)groupWithFilename:(NSString *)filename +{ + return [self groupWithFilename:filename error:nil]; +} + ++(TightdbSharedGroup *)groupWithFilename:(NSString *)filename error:(NSError *__autoreleasing *)error { tightdb::SharedGroup* shared_group; - try { - shared_group = new tightdb::SharedGroup(tightdb::StringData(ObjcStringAccessor(filename))); - } - catch (...) { - // FIXME: Diffrent exception types mean different things. More - // details must be made available. We should proably have - // special catches for at least these: - // tightdb::File::AccessError (and various derivatives), - // tightdb::ResourceAllocError, std::bad_alloc. In general, - // any core library function or operator that is not declared - // 'noexcept' must be considered as being able to throw - // anything derived from std::exception. - return nil; - } + TIGHTDB_EXCEPTION_ERRHANDLER( + shared_group = new tightdb::SharedGroup(tightdb::StringData(ObjcStringAccessor(filename))); + , @"com.tightdb.sharedgroup", + return nil; + ); TightdbSharedGroup* shared_group2 = [[TightdbSharedGroup alloc] init]; if (shared_group2) { shared_group2->_sharedGroup = shared_group; @@ -43,39 +39,46 @@ -(void)dealloc _sharedGroup = 0; } - --(void)readTransaction:(TightdbSharedGroupReadTransactionBlock)block +-(BOOL)readTransaction:(TightdbSharedGroupReadTransactionBlock)block +{ + return [self readTransaction:block error:nil]; +} +-(BOOL)readTransaction:(TightdbSharedGroupReadTransactionBlock)block error:(NSError *__autoreleasing *)error { TightdbGroup* group; - @try { - group = [TightdbGroup groupTightdbGroup:(tightdb::Group *)&_sharedGroup->begin_read() readOnly:YES]; - block(group); - } - @catch (NSException *exception) { - @throw exception; - } - @finally { - _sharedGroup->end_read(); - [group clearGroup]; - } + TIGHTDB_EXCEPTION_ERRHANDLER( + group = [TightdbGroup groupTightdbGroup:(tightdb::Group *)&_sharedGroup->begin_read() readOnly:YES]; + block(group); + _sharedGroup->end_read(); + [group clearGroup]; + , @"com.tightdb.sharedgroup", + _sharedGroup->end_read(); + [group clearGroup]; + return NO; + ); + return YES; } --(void)writeTransaction:(TightdbSharedGroupWriteTransactionBlock)block +-(BOOL)writeTransaction:(TightdbSharedGroupWriteTransactionBlock)block +{ + return [self writeTransaction:block error:nil]; +} +-(BOOL)writeTransaction:(TightdbSharedGroupWriteTransactionBlock)block error:(NSError *__autoreleasing *)error { TightdbGroup* group; - @try { - group = [TightdbGroup groupTightdbGroup:&_sharedGroup->begin_write() readOnly:NO]; - if (block(group)) - _sharedGroup->commit(); - else - _sharedGroup->rollback(); - [group clearGroup]; - } - @catch (NSException *exception) { - _sharedGroup->rollback(); - [group clearGroup]; - @throw exception; - } + TIGHTDB_EXCEPTION_ERRHANDLER( + group = [TightdbGroup groupTightdbGroup:&_sharedGroup->begin_write() readOnly:NO]; + if (block(group)) + _sharedGroup->commit(); + else + _sharedGroup->rollback(); + [group clearGroup]; + , @"com.tightdb.sharedgroup", + _sharedGroup->rollback(); + [group clearGroup]; + return NO; + ); + return YES; } diff --git a/src/tightdb/objc/query_objc.mm b/src/tightdb/objc/query_objc.mm index a3b2453b7d..3d1c723dd0 100644 --- a/src/tightdb/objc/query_objc.mm +++ b/src/tightdb/objc/query_objc.mm @@ -49,7 +49,7 @@ -(id)initWithTable:(TightdbTable *)table error:(NSError *__autoreleasing *)error _table = table; TIGHTDB_EXCEPTION_ERRHANDLER( _query = new tightdb::Query([_table getTable].where()); - , @"com.tightdb.query", nil); + , @"com.tightdb.query", return nil); } return self; } @@ -120,21 +120,21 @@ -(TightdbQuery *)group { TIGHTDB_EXCEPTION_ERRHANDLER_EX( _query->group(); - , @"com.tightdb.query", self, &_error); + , @"com.tightdb.query", return self, &_error); return self; } -(TightdbQuery *)or { TIGHTDB_EXCEPTION_ERRHANDLER_EX( _query->Or(); - , @"com.tightdb.query", self, &_error); + , @"com.tightdb.query", return self, &_error); return self; } -(TightdbQuery *)endgroup { TIGHTDB_EXCEPTION_ERRHANDLER_EX( _query->end_group(); - , @"com.tightdb.query", self, &_error); + , @"com.tightdb.query", return self, &_error); return self; } -(void)subtable:(size_t)column @@ -161,7 +161,7 @@ -(NSNumber *)countWithError:(NSError *__autoreleasing *)error } TIGHTDB_EXCEPTION_ERRHANDLER( return [NSNumber TIGHTDB_OBJC_SIZE_T_NUMBER_IN:_query->count()]; - , @"com.tightdb.query", nil); + , @"com.tightdb.query", return nil); } -(NSNumber *)remove @@ -180,7 +180,7 @@ -(NSNumber *)removeWithError:(NSError *__autoreleasing *)error } TIGHTDB_EXCEPTION_ERRHANDLER( return [NSNumber TIGHTDB_OBJC_SIZE_T_NUMBER_IN:_query->remove()]; - , @"com.tightdb.query", nil); + , @"com.tightdb.query", return nil); } -(NSNumber *)minInt:(size_t)col_ndx @@ -198,7 +198,7 @@ -(NSNumber *)minInt:(size_t)col_ndx error:(NSError *__autoreleasing *)error } TIGHTDB_EXCEPTION_ERRHANDLER( return [NSNumber numberWithLongLong:_query->minimum(col_ndx)]; - , @"com.tightdb.query", nil); + , @"com.tightdb.query", return nil); } -(NSNumber *)minFloat:(size_t)col_ndx @@ -216,7 +216,7 @@ -(NSNumber *)minFloat:(size_t)col_ndx error:(NSError *__autoreleasing *)error } TIGHTDB_EXCEPTION_ERRHANDLER( return [NSNumber numberWithFloat:_query->minimum_float(col_ndx)]; - , @"com.tightdb.query", nil); + , @"com.tightdb.query", return nil); } -(NSNumber *)minDouble:(size_t)col_ndx @@ -234,7 +234,7 @@ -(NSNumber *)minDouble:(size_t)col_ndx error:(NSError *__autoreleasing *)error } TIGHTDB_EXCEPTION_ERRHANDLER( return [NSNumber numberWithDouble:_query->minimum_double(col_ndx)]; - , @"com.tightdb.query", nil); + , @"com.tightdb.query", return nil); } -(NSNumber *)maxInt:(size_t)col_ndx @@ -252,7 +252,7 @@ -(NSNumber *)maxInt:(size_t)col_ndx error:(NSError *__autoreleasing *)error } TIGHTDB_EXCEPTION_ERRHANDLER( return [NSNumber numberWithLongLong:_query->maximum(col_ndx)]; - , @"com.tightdb.query", nil); + , @"com.tightdb.query", return nil); } -(NSNumber *)maxFloat:(size_t)col_ndx { @@ -269,7 +269,7 @@ -(NSNumber *)maxFloat:(size_t)col_ndx error:(NSError *__autoreleasing *)error } TIGHTDB_EXCEPTION_ERRHANDLER( return [NSNumber numberWithFloat:_query->maximum_float(col_ndx)]; - , @"com.tightdb.query", nil); + , @"com.tightdb.query", return nil); } -(NSNumber *)maxDouble:(size_t)col_ndx @@ -287,7 +287,7 @@ -(NSNumber *)maxDouble:(size_t)col_ndx error:(NSError *__autoreleasing *)error } TIGHTDB_EXCEPTION_ERRHANDLER( return [NSNumber numberWithDouble:_query->maximum_double(col_ndx)]; - , @"com.tightdb.query", nil); + , @"com.tightdb.query", return nil); } -(NSNumber *)sumInt:(size_t)col_ndx @@ -305,7 +305,7 @@ -(NSNumber *)sumInt:(size_t)col_ndx error:(NSError *__autoreleasing *)error } TIGHTDB_EXCEPTION_ERRHANDLER( return [NSNumber numberWithLongLong:_query->sum(col_ndx)]; - , @"com.tightdb.query", nil); + , @"com.tightdb.query", return nil); } -(NSNumber *)sumFloat:(size_t)col_ndx @@ -323,7 +323,7 @@ -(NSNumber *)sumFloat:(size_t)col_ndx error:(NSError *__autoreleasing *)error } TIGHTDB_EXCEPTION_ERRHANDLER( return [NSNumber numberWithFloat:_query->sum_float(col_ndx)]; - , @"com.tightdb.query", nil); + , @"com.tightdb.query", return nil); } -(NSNumber *)sumDouble:(size_t)col_ndx @@ -341,7 +341,7 @@ -(NSNumber *)sumDouble:(size_t)col_ndx error:(NSError *__autoreleasing *)error } TIGHTDB_EXCEPTION_ERRHANDLER( return [NSNumber numberWithDouble:_query->sum_double(col_ndx)]; - , @"com.tightdb.query", nil); + , @"com.tightdb.query", return nil); } -(NSNumber *)avgInt:(size_t)col_ndx @@ -359,7 +359,7 @@ -(NSNumber *)avgInt:(size_t)col_ndx error:(NSError *__autoreleasing *)error } TIGHTDB_EXCEPTION_ERRHANDLER( return [NSNumber numberWithDouble:_query->average(col_ndx)]; - , @"com.tightdb.query", nil); + , @"com.tightdb.query", return nil); } -(NSNumber *)avgFloat:(size_t)col_ndx { @@ -376,7 +376,7 @@ -(NSNumber *)avgFloat:(size_t)col_ndx error:(NSError *__autoreleasing *)error } TIGHTDB_EXCEPTION_ERRHANDLER( return [NSNumber numberWithDouble:_query->average_float(col_ndx)]; - , @"com.tightdb.query", nil); + , @"com.tightdb.query", return nil); } -(NSNumber *)avgDouble:(size_t)col_ndx @@ -394,7 +394,7 @@ -(NSNumber *)avgDouble:(size_t)col_ndx error:(NSError *__autoreleasing *)error } TIGHTDB_EXCEPTION_ERRHANDLER( return [NSNumber numberWithDouble:_query->average_double(col_ndx)]; - , @"com.tightdb.query", nil); + , @"com.tightdb.query", return nil); } -(tightdb::TableView)getTableView @@ -417,7 +417,7 @@ -(size_t)findNext:(size_t)last error:(NSError *__autoreleasing *)error } TIGHTDB_EXCEPTION_ERRHANDLER( return _query->find_next(last); - , @"com.tightdb.query", size_t(-1)); + , @"com.tightdb.query", return size_t(-1)); } -(TightdbQuery *)betweenInt:(int64_t)from to:(int64_t)to colNdx:(size_t)colNdx { @@ -478,7 +478,7 @@ -(TightdbQuery *)equal:(int64_t)value { TIGHTDB_EXCEPTION_ERRHANDLER_EX( [_query getQuery]->equal(_column_ndx, value); - , @"com.tightdb.queryaccessor", _query, &_query->_error); + , @"com.tightdb.queryaccessor", return _query, &_query->_error); return _query; } @@ -486,7 +486,7 @@ -(TightdbQuery *)notEqual:(int64_t)value { TIGHTDB_EXCEPTION_ERRHANDLER_EX( [_query getQuery]->not_equal(_column_ndx, value); - , @"com.tightdb.queryaccessor", _query, &_query->_error); + , @"com.tightdb.queryaccessor", return _query, &_query->_error); return _query; } @@ -494,7 +494,7 @@ -(TightdbQuery *)greater:(int64_t)value { TIGHTDB_EXCEPTION_ERRHANDLER_EX( [_query getQuery]->greater(_column_ndx, value); - , @"com.tightdb.queryaccessor", _query, &_query->_error); + , @"com.tightdb.queryaccessor", return _query, &_query->_error); return _query; } @@ -502,7 +502,7 @@ -(TightdbQuery *)greaterEqual:(int64_t)value { TIGHTDB_EXCEPTION_ERRHANDLER_EX( [_query getQuery]->greater_equal(_column_ndx, value); - , @"com.tightdb.queryaccessor", _query, &_query->_error); + , @"com.tightdb.queryaccessor", return _query, &_query->_error); return _query; } @@ -510,7 +510,7 @@ -(TightdbQuery *)less:(int64_t)value { TIGHTDB_EXCEPTION_ERRHANDLER_EX( [_query getQuery]->less(_column_ndx, value); - , @"com.tightdb.queryaccessor", _query, &_query->_error); + , @"com.tightdb.queryaccessor", return _query, &_query->_error); return _query; } @@ -518,7 +518,7 @@ -(TightdbQuery *)lessEqual:(int64_t)value { TIGHTDB_EXCEPTION_ERRHANDLER_EX( [_query getQuery]->less_equal(_column_ndx, value); - , @"com.tightdb.queryaccessor", _query, &_query->_error); + , @"com.tightdb.queryaccessor", return _query, &_query->_error); return _query; } @@ -526,7 +526,7 @@ -(TightdbQuery *)between:(int64_t)from to:(int64_t)to { TIGHTDB_EXCEPTION_ERRHANDLER_EX( [_query getQuery]->between(_column_ndx, from, to); - , @"com.tightdb.queryaccessor", _query, &_query->_error); + , @"com.tightdb.queryaccessor", return _query, &_query->_error); return _query; } diff --git a/src/tightdb/objc/table_objc.mm b/src/tightdb/objc/table_objc.mm index 5e989fea08..4350869891 100644 --- a/src/tightdb/objc/table_objc.mm +++ b/src/tightdb/objc/table_objc.mm @@ -232,7 +232,7 @@ +(TightdbSpec *)specWithSpec:(tightdb::Spec *)spec readOnly:(BOOL)readOnly isOwn if (isOwned) { TIGHTDB_EXCEPTION_ERRHANDLER( spec2.spec = new tightdb::Spec(*spec); - , @"com.tightdb.spec", nil); + , @"com.tightdb.spec", return nil); spec2.isOwned = TRUE; } else { @@ -258,7 +258,7 @@ -(BOOL)addColumn:(TightdbType)type name:(NSString *)name error:(NSError *__autor } TIGHTDB_EXCEPTION_ERRHANDLER( _spec->add_column(tightdb::DataType(type), ObjcStringAccessor(name)); - , @"com.tightdb.spec", NO); + , @"com.tightdb.spec", return NO); return YES; } @@ -277,7 +277,7 @@ -(TightdbSpec *)addColumnTable:(NSString *)name error:(NSError *__autoreleasing TIGHTDB_EXCEPTION_ERRHANDLER( tightdb::Spec tmp = _spec->add_subtable_column(ObjcStringAccessor(name)); return [TightdbSpec specWithSpec:&tmp readOnly:FALSE isOwned:TRUE error:error]; - , @"com.tightdb.spec", nil); + , @"com.tightdb.spec", return nil); } -(TightdbSpec *)getSubspec:(size_t)col_ndx @@ -290,7 +290,7 @@ -(TightdbSpec *)getSubspec:(size_t)col_ndx error:(NSError *__autoreleasing *)err TIGHTDB_EXCEPTION_ERRHANDLER( tightdb::Spec subspec = _spec->get_subtable_spec(col_ndx); return [TightdbSpec specWithSpec:&subspec readOnly:_readOnly isOwned:TRUE error:error]; - , @"com.tightdb.spec", nil); + , @"com.tightdb.spec", return nil); } -(size_t)getColumnCount @@ -468,7 +468,7 @@ -(BOOL)updateFromSpecWithError:(NSError *__autoreleasing *)error { TIGHTDB_EXCEPTION_ERRHANDLER( static_cast(&*self.table)->update_from_spec(); - , @"com.tightdb.table", NO); + , @"com.tightdb.table", return NO); return YES; } @@ -643,7 +643,7 @@ -(size_t)addRowWithError:(NSError *__autoreleasing *)error } TIGHTDB_EXCEPTION_ERRHANDLER( return _table->add_empty_row(); - , @"com.tightdb.table", 0); + , @"com.tightdb.table", return 0); } -(size_t)addRows:(size_t)rowCount @@ -660,7 +660,7 @@ -(size_t)addRows:(size_t)rowCount error:(NSError *__autoreleasing *)error } TIGHTDB_EXCEPTION_ERRHANDLER( return _table->add_empty_row(rowCount); - , @"com.tightdb.table", 0); + , @"com.tightdb.table", return 0); } -(BOOL)clear @@ -676,7 +676,7 @@ -(BOOL)clearWithError:(NSError *__autoreleasing *)error } TIGHTDB_EXCEPTION_ERRHANDLER( _table->clear(); - , @"com.tightdb.table", NO); + , @"com.tightdb.table", return NO); return YES; } @@ -694,7 +694,7 @@ -(BOOL)remove:(size_t)ndx error:(NSError *__autoreleasing *)error } TIGHTDB_EXCEPTION_ERRHANDLER( _table->remove(ndx); - , @"com.tightdb.table", NO); + , @"com.tightdb.table", return NO); return YES; } @@ -712,7 +712,7 @@ -(BOOL)removeLastWithError:(NSError *__autoreleasing *)error } TIGHTDB_EXCEPTION_ERRHANDLER( _table->remove_last(); - , @"com.tightdb.table", NO); + , @"com.tightdb.table", return NO); return YES; } -(int64_t)get:(size_t)col_ndx ndx:(size_t)ndx @@ -734,7 +734,7 @@ -(BOOL)set:(size_t)col_ndx ndx:(size_t)ndx value:(int64_t)value error:(NSError * } TIGHTDB_EXCEPTION_ERRHANDLER( _table->set_int(col_ndx, ndx, value); - , @"com.tightdb.table", NO); + , @"com.tightdb.table", return NO); return YES; } @@ -757,7 +757,7 @@ -(BOOL)setBool:(size_t)col_ndx ndx:(size_t)ndx value:(BOOL)value error:(NSError } TIGHTDB_EXCEPTION_ERRHANDLER( _table->set_bool(col_ndx, ndx, value); - , @"com.tightdb.table", NO); + , @"com.tightdb.table", return NO); return YES; } @@ -780,7 +780,7 @@ -(BOOL)setFloat:(size_t)col_ndx ndx:(size_t)ndx value:(float)value error:(NSErro } TIGHTDB_EXCEPTION_ERRHANDLER( _table->set_float(col_ndx, ndx, value); - , @"com.tightdb.table", NO); + , @"com.tightdb.table", return NO); return YES; } @@ -803,7 +803,7 @@ -(BOOL)setDouble:(size_t)col_ndx ndx:(size_t)ndx value:(double)value error:(NSEr } TIGHTDB_EXCEPTION_ERRHANDLER( _table->set_double(col_ndx, ndx, value); - , @"com.tightdb.table", NO); + , @"com.tightdb.table", return NO); return YES; } @@ -826,7 +826,7 @@ -(BOOL)setDate:(size_t)col_ndx ndx:(size_t)ndx value:(time_t)value error:(NSErro } TIGHTDB_EXCEPTION_ERRHANDLER( _table->set_date(col_ndx, ndx, value); - , @"com.tightdb.table", NO); + , @"com.tightdb.table", return NO); return YES; } @@ -844,7 +844,7 @@ -(BOOL)insertBool:(size_t)col_ndx ndx:(size_t)ndx value:(BOOL)value error:(NSErr } TIGHTDB_EXCEPTION_ERRHANDLER( _table->insert_bool(col_ndx, ndx, value); - , @"com.tightdb.table", NO); + , @"com.tightdb.table", return NO); return YES; } @@ -863,7 +863,7 @@ -(BOOL)insertInt:(size_t)col_ndx ndx:(size_t)ndx value:(int64_t)value error:(NSE } TIGHTDB_EXCEPTION_ERRHANDLER( _table->insert_int(col_ndx, ndx, value); - , @"com.tightdb.table", NO); + , @"com.tightdb.table", return NO); return YES; } @@ -881,7 +881,7 @@ -(BOOL)insertFloat:(size_t)col_ndx ndx:(size_t)ndx value:(float)value error:(NSE } TIGHTDB_EXCEPTION_ERRHANDLER( _table->insert_float(col_ndx, ndx, value); - , @"com.tightdb.table", NO); + , @"com.tightdb.table", return NO); return YES; } @@ -899,7 +899,7 @@ -(BOOL)insertDouble:(size_t)col_ndx ndx:(size_t)ndx value:(double)value error:(N } TIGHTDB_EXCEPTION_ERRHANDLER( _table->insert_double(col_ndx, ndx, value); - , @"com.tightdb.table", NO); + , @"com.tightdb.table", return NO); return YES; } @@ -917,7 +917,7 @@ -(BOOL)insertString:(size_t)col_ndx ndx:(size_t)ndx value:(NSString *)value erro } TIGHTDB_EXCEPTION_ERRHANDLER( _table->insert_string(col_ndx, ndx, ObjcStringAccessor(value)); - , @"com.tightdb.table", NO); + , @"com.tightdb.table", return NO); return YES; } @@ -935,7 +935,7 @@ -(BOOL)insertBinary:(size_t)col_ndx ndx:(size_t)ndx value:(TightdbBinary *)value } TIGHTDB_EXCEPTION_ERRHANDLER( _table->insert_binary(col_ndx, ndx, [value getBinary]); - , @"com.tightdb.table", NO); + , @"com.tightdb.table", return NO); return YES; } @@ -953,7 +953,7 @@ -(BOOL)insertBinary:(size_t)col_ndx ndx:(size_t)ndx data:(const char *)data size } TIGHTDB_EXCEPTION_ERRHANDLER( _table->insert_binary(col_ndx, ndx, tightdb::BinaryData(data, size)); - , @"com.tightdb.table", NO); + , @"com.tightdb.table", return NO); return YES; } @@ -971,7 +971,7 @@ -(BOOL)insertDate:(size_t)col_ndx ndx:(size_t)ndx value:(time_t)value error:(NSE } TIGHTDB_EXCEPTION_ERRHANDLER( _table->insert_date(col_ndx, ndx, value); - , @"com.tightdb.table", NO); + , @"com.tightdb.table", return NO); return YES; } @@ -984,7 +984,7 @@ -(BOOL)insertDoneWithError:(NSError *__autoreleasing *)error { TIGHTDB_EXCEPTION_ERRHANDLER( _table->insert_done(); - , @"com.tightdb.table", NO); + , @"com.tightdb.table", return NO); return YES; } @@ -1006,7 +1006,7 @@ -(BOOL)setString:(size_t)col_ndx ndx:(size_t)ndx value:(NSString *)value error:( } TIGHTDB_EXCEPTION_ERRHANDLER( _table->set_string(col_ndx, ndx, ObjcStringAccessor(value)); - , @"com.tightdb.table", NO); + , @"com.tightdb.table", return NO); return YES; } @@ -1029,7 +1029,7 @@ -(BOOL)setBinary:(size_t)col_ndx ndx:(size_t)ndx value:(TightdbBinary *)value er } TIGHTDB_EXCEPTION_ERRHANDLER( _table->set_binary(col_ndx, ndx, [value getBinary]); - , @"com.tightdb.table", NO); + , @"com.tightdb.table", return NO); return YES; } @@ -1047,7 +1047,7 @@ -(BOOL)setBinary:(size_t)col_ndx ndx:(size_t)ndx data:(const char *)data size:(s } TIGHTDB_EXCEPTION_ERRHANDLER( _table->set_binary(col_ndx, ndx, tightdb::BinaryData(data, size)); - , @"com.tightdb.table", NO); + , @"com.tightdb.table", return NO); return YES; } @@ -1070,7 +1070,7 @@ -(BOOL)insertSubtable:(size_t)col_ndx ndx:(size_t)row_ndx error:(NSError *__auto } TIGHTDB_EXCEPTION_ERRHANDLER( _table->insert_subtable(col_ndx, row_ndx); - , @"com.tightdb.table", NO); + , @"com.tightdb.table", return NO); return YES; } @@ -1089,7 +1089,7 @@ -(BOOL)_insertSubtableCopy:(size_t)col_ndx row:(size_t)row_ndx subtable:(Tightdb } TIGHTDB_EXCEPTION_ERRHANDLER( tightdb::LangBindHelper::insert_subtable(*_table, col_ndx, row_ndx, [subtable getTable]); - , @"com.tightdb.table", NO); + , @"com.tightdb.table", return NO); return YES; } @@ -1106,7 +1106,7 @@ -(BOOL)clearSubtable:(size_t)col_ndx ndx:(size_t)row_ndx error:(NSError *__autor } TIGHTDB_EXCEPTION_ERRHANDLER( _table->clear_subtable(col_ndx, row_ndx); - , @"com.tightdb.table", NO); + , @"com.tightdb.table", return NO); return YES; } @@ -1145,7 +1145,7 @@ -(BOOL)insertMixed:(size_t)col_ndx ndx:(size_t)row_ndx value:(TightdbMixed *)val else { _table->insert_mixed(col_ndx, row_ndx, value.mixed); } - , @"com.tightdb.table", NO); + , @"com.tightdb.table", return NO); return YES; } @@ -1169,7 +1169,7 @@ -(BOOL)setMixed:(size_t)col_ndx ndx:(size_t)row_ndx value:(TightdbMixed *)value else { _table->set_mixed(col_ndx, row_ndx, value.mixed); } - , @"com.tightdb.table", NO); + , @"com.tightdb.table", return NO); return YES; } @@ -1182,7 +1182,7 @@ -(size_t)addColumn:(TightdbType)type name:(NSString *)name error:(NSError *__aut { TIGHTDB_EXCEPTION_ERRHANDLER( return _table->add_column(tightdb::DataType(type), ObjcStringAccessor(name)); - , @"com.tightdb.table", 0); + , @"com.tightdb.table", return 0); } -(size_t)findBool:(size_t)col_ndx value:(BOOL)value @@ -1256,7 +1256,7 @@ -(BOOL)optimizeWithError:(NSError *__autoreleasing *)error { TIGHTDB_EXCEPTION_ERRHANDLER( _table->optimize(); - , @"com.tightdb.table", NO); + , @"com.tightdb.table", return NO); return YES; } diff --git a/src/tightdb/objc/test/shared_group.m b/src/tightdb/objc/test/shared_group.mm similarity index 76% rename from src/tightdb/objc/test/shared_group.m rename to src/tightdb/objc/test/shared_group.mm index 73cb17092d..412b04037f 100644 --- a/src/tightdb/objc/test/shared_group.m +++ b/src/tightdb/objc/test/shared_group.mm @@ -1,5 +1,5 @@ // -// shared_group.m +// shared_group.mm // TightDB // // Demo code for short tutorial using Objective-C interface @@ -10,6 +10,8 @@ #import #import #import +#include +#import TIGHTDB_TABLE_DEF_2(SharedTable2, Hired, Bool, @@ -47,10 +49,9 @@ - (void)testSharedGroup // Read only shared group TightdbSharedGroup *fromDisk = [TightdbSharedGroup groupWithFilename:@"employees.tightdb"]; - @try { [fromDisk readTransaction:^(TightdbGroup *group) { SharedTable2 *diskTable = [group getTable:@"employees" withClass:[SharedTable2 class]]; - NSLog(@"Disktable size: %zu", [diskTable count]); + STAssertEquals(size_t(4), [diskTable count], @"There should be 4 rows"); for (size_t i = 0; i < [diskTable count]; i++) { SharedTable2_Cursor *cursor = [diskTable objectAtIndex:i]; NSLog(@"%zu: %lld", i, [cursor Age]); @@ -59,52 +60,47 @@ - (void)testSharedGroup } [diskTable addHired:YES Age:54]; }]; - } - @catch (NSException *exception) { - NSLog(@"Exception caught: %@", exception); - } // Write shared group and commit // TightdbSharedGroup *fromDisk = [TightdbSharedGroup groupWithFilename:@"employees.tightdb"]; [fromDisk writeTransaction:^(TightdbGroup *group) { SharedTable2 *diskTable = [group getTable:@"employees" withClass:[SharedTable2 class]]; - NSLog(@"Disktable size: %zu", [diskTable count]); + STAssertEquals(size_t(4), [diskTable count], @"There should be 4 rows"); for (size_t i = 0; i < 50; i++) { [diskTable addHired:YES Age:i]; } return YES; // Commit - }]; + } error:nil]; // Write shared group and rollback // TightdbSharedGroup *fromDisk = [TightdbSharedGroup groupWithFilename:@"employees.tightdb"]; [fromDisk writeTransaction:^(TightdbGroup *group) { SharedTable2 *diskTable = [group getTable:@"employees" withClass:[SharedTable2 class]]; - NSLog(@"Disktable size: %zu", [diskTable count]); + STAssertEquals(size_t(54), [diskTable count], @"There should be 54 rows"); for (size_t i = 0; i < 50; i++) { [diskTable addHired:YES Age:i]; } return NO; // rollback }]; - // Write and fail with exception in block (Should rollback) + // Write and fail with exception in block (Should rollback) - Note: Cannot simulate exception, so doing readonly instead // TightdbSharedGroup *fromDisk = [TightdbSharedGroup groupWithFilename:@"employees.tightdb"]; - @try { + __block int addCount = 0; [fromDisk writeTransaction:^(TightdbGroup *group) { SharedTable2 *diskTable = [group getTable:@"employees" withClass:[SharedTable2 class]]; - NSLog(@"Disktable size: %zu", [diskTable count]); + // Fake readonly. + NSLog(@"Fake readonly - should trigger an error"); + [((TightdbTable *)diskTable) setReadOnly:true]; + STAssertEquals(size_t(54), [diskTable count], @"There should be 54 rows"); for (size_t i = 0; i < 50; i++) { - [diskTable addHired:YES Age:i]; + if ([diskTable addHired:YES Age:i]) + ++addCount; } - [NSException raise:@"Test exception" format:@"Program went ballistic"]; return YES; // commit }]; - } - @catch (NSException *exception) { - NSLog(@"Exception caught: %@", exception); - } - + STAssertEquals(0, addCount, @"No rows should be added"); [fromDisk readTransaction:^(TightdbGroup *group) { SharedTable2 *diskTable = [group getTable:@"employees" withClass:[SharedTable2 class]]; - NSLog(@"Disktable size: %zu", [diskTable count]); + STAssertEquals(size_t(54), [diskTable count], @"There should be 54 rows"); }]; } diff --git a/src/tightdb/objc/util.hpp b/src/tightdb/objc/util.hpp index 3f004dd2be..c4d898dfbb 100644 --- a/src/tightdb/objc/util.hpp +++ b/src/tightdb/objc/util.hpp @@ -64,22 +64,22 @@ inline NSError *make_tightdb_error(NSString *domain, TightdbErr code, NSString * #define TIGHTDB_OBJC_SIZE_T_NUMBER_IN numberWithUnsignedLong #define TIGHTDB_OBJC_SIZE_T_NUMBER_OUT unsignedLongValue -#define TIGHTDB_EXCEPTION_ERRHANDLER(action, domain, failReturnValue) TIGHTDB_EXCEPTION_ERRHANDLER_EX(action, domain, failReturnValue, error) -#define TIGHTDB_EXCEPTION_ERRHANDLER_EX(action, domain, failReturnValue, errVar) try { action } \ +#define TIGHTDB_EXCEPTION_ERRHANDLER(action, domain, failAction) TIGHTDB_EXCEPTION_ERRHANDLER_EX(action, domain, failAction, error) +#define TIGHTDB_EXCEPTION_ERRHANDLER_EX(action, domain, failAction, errVar) try { action } \ catch(tightdb::File::AccessError &ex) { \ if (errVar) \ *errVar = make_tightdb_error(domain, tdb_err_FileAccess, [NSString stringWithUTF8String:ex.what()]); \ - return failReturnValue; \ + failAction; \ } \ catch(tightdb::ResourceAllocError &ex) { \ if (errVar) \ *errVar = make_tightdb_error(domain, tdb_err_Resource, [NSString stringWithUTF8String:ex.what()]); \ - return failReturnValue; \ + failAction; \ } \ catch (std::exception &ex) { \ if (errVar) \ *errVar = make_tightdb_error(domain, tdb_err_Fail, [NSString stringWithUTF8String:ex.what()]); \ - return failReturnValue; \ + failAction; \ } From c3ffcab880272c00499bd34a7c25457be58ec5ae Mon Sep 17 00:00:00 2001 From: Thomas Andersen Date: Mon, 1 Jul 2013 20:03:00 +0200 Subject: [PATCH 2/6] Initial allocation check added. Leak found in query accessors. --- .../TightDbObjcDyn.xcodeproj/project.pbxproj | 2 + src/tightdb/objc/cursor_objc.mm | 8 + src/tightdb/objc/group_objc.mm | 16 + src/tightdb/objc/query_objc.mm | 27 +- src/tightdb/objc/table.h | 1 + src/tightdb/objc/table_objc.mm | 47 +- src/tightdb/objc/test/TestHelper.h | 28 + src/tightdb/objc/test/enumerator.m | 88 +- src/tightdb/objc/test/err_handling.mm | 782 +++++++++--------- src/tightdb/objc/test/tutorial.m | 297 +++---- 10 files changed, 731 insertions(+), 565 deletions(-) create mode 100644 src/tightdb/objc/test/TestHelper.h diff --git a/TightDbObjcDyn/TightDbObjcDyn.xcodeproj/project.pbxproj b/TightDbObjcDyn/TightDbObjcDyn.xcodeproj/project.pbxproj index e6f2a0151c..b9caf0c047 100644 --- a/TightDbObjcDyn/TightDbObjcDyn.xcodeproj/project.pbxproj +++ b/TightDbObjcDyn/TightDbObjcDyn.xcodeproj/project.pbxproj @@ -97,6 +97,7 @@ E91890F2177B71E400653D7A /* table.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = table.m; path = ../../src/tightdb/objc/test/table.m; sourceTree = ""; }; E91890F3177B71E400653D7A /* template.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = template.m; path = ../../src/tightdb/objc/test/template.m; sourceTree = ""; }; E91890F4177B71E400653D7A /* tutorial.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = tutorial.m; path = ../../src/tightdb/objc/test/tutorial.m; sourceTree = ""; }; + E9F2A7B11781FAB600292661 /* TestHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TestHelper.h; path = ../../src/tightdb/objc/test/TestHelper.h; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -196,6 +197,7 @@ E91890B4177B677900653D7A /* TightDbObjcDynTests */ = { isa = PBXGroup; children = ( + E9F2A7B11781FAB600292661 /* TestHelper.h */, E91890E7177B71E400653D7A /* data_type.mm */, E91890E8177B71E400653D7A /* enumerator.m */, E91890E9177B71E400653D7A /* err_handling.mm */, diff --git a/src/tightdb/objc/cursor_objc.mm b/src/tightdb/objc/cursor_objc.mm index 800a57cb18..794232eee1 100644 --- a/src/tightdb/objc/cursor_objc.mm +++ b/src/tightdb/objc/cursor_objc.mm @@ -12,6 +12,9 @@ using namespace std; +#ifdef TIGHTDB_DEBUG +int TightdbCursorAllocateCount = 0; +#endif @interface TightdbCursor() @property (nonatomic, weak) TightdbTable *table; @@ -25,6 +28,10 @@ -(id)initWithTable:(TightdbTable *)table ndx:(size_t)ndx { self = [super init]; if (self) { +#ifdef TIGHTDB_DEBUG + NSLog(@"TightdbCursor init"); + ++TightdbCursorAllocateCount; +#endif _table = table; _ndx = ndx; } @@ -38,6 +45,7 @@ -(void)dealloc { #ifdef TIGHTDB_DEBUG NSLog(@"TightdbCursor dealloc"); + --TightdbCursorAllocateCount; #endif _table = nil; } diff --git a/src/tightdb/objc/group_objc.mm b/src/tightdb/objc/group_objc.mm index 0b044e9532..d2cb71852e 100644 --- a/src/tightdb/objc/group_objc.mm +++ b/src/tightdb/objc/group_objc.mm @@ -14,6 +14,9 @@ using namespace std; +#ifdef TIGHTDB_DEBUG +int TightdbGroupAllocateCount = 0; +#endif @interface TightdbGroup() @property(nonatomic) tightdb::Group *group; @@ -36,6 +39,9 @@ +(TightdbGroup *)groupWithError:(NSError *__autoreleasing *)error group.group = new tightdb::Group(); , @"com.tightdb.group", return nil); group.readOnly = NO; +#ifdef TIGHTDB_DEBUG + ++TightdbGroupAllocateCount; +#endif return group; } @@ -45,6 +51,9 @@ +(TightdbGroup *)groupTightdbGroup:(tightdb::Group *)tightdbGroup readOnly:(BOOL TightdbGroup *group = [[TightdbGroup alloc] init]; group.group = tightdbGroup; group.readOnly = readOnly; +#ifdef TIGHTDB_DEBUG + ++TightdbGroupAllocateCount; +#endif return group; } @@ -65,6 +74,9 @@ +(TightdbGroup *)groupWithFilename:(NSString *)filename error:(NSError **)error group2.group = group; group2.readOnly = NO; } +#ifdef TIGHTDB_DEBUG + ++TightdbGroupAllocateCount; +#endif return group2; } @@ -82,6 +94,9 @@ +(TightdbGroup *)groupWithBuffer:(const char *)data size:(size_t)size error:(NSE TightdbGroup* group2 = [[TightdbGroup alloc] init]; group2.group = group; group2.readOnly = NO; +#ifdef TIGHTDB_DEBUG + ++TightdbGroupAllocateCount; +#endif return group2; } @@ -94,6 +109,7 @@ -(void)dealloc { #ifdef TIGHTDB_DEBUG NSLog(@"TightdbGroup dealloc"); + --TightdbGroupAllocateCount; #endif delete _group; } diff --git a/src/tightdb/objc/query_objc.mm b/src/tightdb/objc/query_objc.mm index d1dd101369..76d6a8fe86 100644 --- a/src/tightdb/objc/query_objc.mm +++ b/src/tightdb/objc/query_objc.mm @@ -17,6 +17,10 @@ using namespace std; +#ifdef TIGHTDB_DEBUG +int TightdbQueryAllocateCount = 0; +#endif + @interface TightdbView() +(TightdbView *)tableViewWithTableView:(tightdb::TableView)table; @@ -50,6 +54,10 @@ -(id)initWithTable:(TightdbTable *)table error:(NSError *__autoreleasing *)error TIGHTDB_EXCEPTION_ERRHANDLER( _query = new tightdb::Query([_table getTable].where()); , @"com.tightdb.query", return nil); +#ifdef TIGHTDB_DEBUG + NSLog(@"TightdbQuery init"); + ++TightdbQueryAllocateCount; +#endif } return self; } @@ -102,6 +110,7 @@ -(void)dealloc { #ifdef TIGHTDB_DEBUG NSLog(@"Query dealloc"); + --TightdbQueryAllocateCount; #endif delete _query; } @@ -560,7 +569,7 @@ -(TightdbQuery *)greaterEqualDate:(time_t)value colNdx:(size_t)colNdx @implementation TightdbQueryAccessorBool { - TightdbQuery *_query; + __weak TightdbQuery *_query; size_t _column_ndx; } -(id)initWithColumn:(size_t)columnId query:(TightdbQuery *)query @@ -582,7 +591,7 @@ -(TightdbQuery *)equal:(BOOL)value @implementation TightdbQueryAccessorInt { - TightdbQuery *_query; + __weak TightdbQuery *_query; size_t _column_ndx; } -(id)initWithColumn:(size_t)columnId query:(TightdbQuery *)query @@ -689,7 +698,7 @@ -(NSNumber *)avgWithError:(NSError *__autoreleasing *)error @implementation TightdbQueryAccessorFloat { - TightdbQuery *_query; + __weak TightdbQuery *_query; size_t _column_ndx; } -(id)initWithColumn:(size_t)columnId query:(TightdbQuery *)query @@ -782,7 +791,7 @@ -(NSNumber *)avgWithError:(NSError *__autoreleasing *)error @implementation TightdbQueryAccessorDouble { - TightdbQuery *_query; + __weak TightdbQuery *_query; size_t _column_ndx; } -(id)initWithColumn:(size_t)columnId query:(TightdbQuery *)query @@ -875,7 +884,7 @@ -(NSNumber *)avgWithError:(NSError *__autoreleasing *)error @implementation TightdbQueryAccessorString { - TightdbQuery *_query; + __weak TightdbQuery *_query; size_t _column_ndx; } -(id)initWithColumn:(size_t)columnId query:(TightdbQuery *)query @@ -942,7 +951,7 @@ -(TightdbQuery *)contains:(NSString *)value caseSensitive:(BOOL)caseSensitive @implementation TightdbQueryAccessorBinary { - TightdbQuery *_query; + __weak TightdbQuery *_query; size_t _column_ndx; } -(id)initWithColumn:(size_t)columnId query:(TightdbQuery *)query @@ -984,7 +993,7 @@ -(TightdbQuery *)contains:(TightdbBinary *)value @implementation TightdbQueryAccessorDate { - TightdbQuery *_query; + __weak TightdbQuery *_query; size_t _column_ndx; } -(id)initWithColumn:(size_t)columnId query:(TightdbQuery *)query @@ -1036,7 +1045,7 @@ -(TightdbQuery *)between:(time_t)from to:(time_t)to @implementation TightdbQueryAccessorSubtable { - TightdbQuery *_query; + __weak TightdbQuery *_query; size_t _column_ndx; } -(id)initWithColumn:(size_t)columnId query:(TightdbQuery *)query @@ -1053,7 +1062,7 @@ -(id)initWithColumn:(size_t)columnId query:(TightdbQuery *)query @implementation TightdbQueryAccessorMixed { - TightdbQuery *_query; + __weak TightdbQuery *_query; size_t _column_ndx; } -(id)initWithColumn:(size_t)columnId query:(TightdbQuery *)query diff --git a/src/tightdb/objc/table.h b/src/tightdb/objc/table.h index c50a4d2969..464d3b94ac 100644 --- a/src/tightdb/objc/table.h +++ b/src/tightdb/objc/table.h @@ -77,6 +77,7 @@ @interface TightdbTable: NSObject +-(id)initWithError:(NSError *__autoreleasing *)error; -(BOOL)updateFromSpec; -(BOOL)updateFromSpecWithError:(NSError *__autoreleasing *)error; -(NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id __unsafe_unretained *)stackbuf count:(NSUInteger)len; diff --git a/src/tightdb/objc/table_objc.mm b/src/tightdb/objc/table_objc.mm index 4350869891..deaf32d11c 100644 --- a/src/tightdb/objc/table_objc.mm +++ b/src/tightdb/objc/table_objc.mm @@ -210,6 +210,9 @@ -(TightdbTable *)getTable } @end +#ifdef TIGHTDB_DEBUG +int TightdbSpecAllocateCount = 0; +#endif @interface TightdbSpec() @property (nonatomic) tightdb::Spec *spec; @@ -239,6 +242,9 @@ +(TightdbSpec *)specWithSpec:(tightdb::Spec *)spec readOnly:(BOOL)readOnly isOwn spec2.spec = spec; spec2.isOwned = FALSE; } +#ifdef TIGHTDB_DEBUG + ++TightdbSpecAllocateCount; +#endif return spec2; } @@ -313,6 +319,7 @@ -(void)dealloc { #ifdef TIGHTDB_DEBUG NSLog(@"TightdbSpec dealloc"); + --TightdbSpecAllocateCount; #endif if (_isOwned) delete _spec; } @@ -321,12 +328,16 @@ -(void)dealloc @end +#ifdef TIGHTDB_DEBUG +int TightdbViewAllocateCount = 0; +#endif + @interface TightdbView() @property (nonatomic) tightdb::TableView *tableView; @end @implementation TightdbView { - TightdbTable *_table; + __weak TightdbTable *_table; } @synthesize tableView = _tableView; @@ -337,6 +348,9 @@ -(id)initFromQuery:(TightdbQuery *)query if (self) { _table = [query getTable]; self.tableView = new tightdb::TableView([query getTableView]); +#ifdef TIGHTDB_DEBUG + ++TightdbViewAllocateCount; +#endif } return self; } @@ -351,6 +365,10 @@ +(TightdbView *)tableViewWithTable:(TightdbTable *)table (void)table; TightdbView *tableView = [[TightdbView alloc] init]; tableView.tableView = new tightdb::TableView(); // not longer needs table at construction +#ifdef TIGHTDB_DEBUG + if (tableView) + ++TightdbViewAllocateCount; +#endif return tableView; } @@ -358,6 +376,10 @@ +(TightdbView *)tableViewWithTableView:(tightdb::TableView)table { TightdbView *tableView = [[TightdbView alloc] init]; tableView.tableView = new tightdb::TableView(table); +#ifdef TIGHTDB_DEBUG + if (tableView) + ++TightdbViewAllocateCount; +#endif return tableView; } @@ -365,6 +387,7 @@ -(void)dealloc { #ifdef TIGHTDB_DEBUG NSLog(@"TightdbView dealloc"); + --TightdbViewAllocateCount; #endif _table = nil; delete _tableView; @@ -437,6 +460,10 @@ - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state object @end +#ifdef TIGHTDB_DEBUG +int TightdbTableAllocateCount = 0; +#endif + @implementation TightdbTable { id _parent; @@ -445,11 +472,21 @@ @implementation TightdbTable @synthesize table = _table; -(id)init +{ + return [self initWithError:nil]; +} + +-(id)initWithError:(NSError *__autoreleasing *)error { self = [super init]; if (self) { _readOnly = NO; - _table = tightdb::Table::create(); // FIXME: May throw + TIGHTDB_EXCEPTION_ERRHANDLER( + _table = tightdb::Table::create(); + , @"com.tightdb.table", return nil); +#ifdef TIGHTDB_DEBUG + ++TightdbTableAllocateCount; +#endif } return self; } @@ -457,6 +494,11 @@ -(id)init -(id)_initRaw { self = [super init]; +#ifdef TIGHTDB_DEBUG + if (self) { + ++TightdbTableAllocateCount; + } +#endif return self; } @@ -590,6 +632,7 @@ -(void)dealloc { #ifdef TIGHTDB_DEBUG NSLog(@"TightdbTable dealloc"); + --TightdbTableAllocateCount; #endif _parent = nil; } diff --git a/src/tightdb/objc/test/TestHelper.h b/src/tightdb/objc/test/TestHelper.h new file mode 100644 index 0000000000..7f48e0e229 --- /dev/null +++ b/src/tightdb/objc/test/TestHelper.h @@ -0,0 +1,28 @@ +// +// TestHelper.h +// TightDbObjcDyn +// +// Created by Thomas Andersen on 7/1/13. +// Copyright (c) 2013 Thomas Andersen. All rights reserved. +// + +#ifdef TIGHTDB_DEBUG +extern int TightdbQueryAllocateCount; +extern int TightdbViewAllocateCount; +extern int TightdbCursorAllocateCount; +extern int TightdbGroupAllocateCount; +extern int TightdbSpecAllocateCount; +extern int TightdbTableAllocateCount; +#endif + + +#ifdef TIGHTDB_DEBUG +#define TEST_CHECK_ALLOC STAssertEquals(0, TightdbQueryAllocateCount, @"Zero TightdbQuery allocated"); \ +STAssertEquals(0, TightdbViewAllocateCount, @"Zero TightdbView allocated"); \ +STAssertEquals(0, TightdbCursorAllocateCount, @"Zero TightdbCursor allocated"); \ +STAssertEquals(0, TightdbGroupAllocateCount, @"Zero TightdbGroup allocated"); \ +STAssertEquals(0, TightdbSpecAllocateCount, @"Zero TightdbSpec allocated"); \ +STAssertEquals(0, TightdbTableAllocateCount, @"Zero TightdbTable allocated"); +#else +#define TEST_CHECK_ALLOC +#endif diff --git a/src/tightdb/objc/test/enumerator.m b/src/tightdb/objc/test/enumerator.m index 06a4e3d69c..4888538246 100644 --- a/src/tightdb/objc/test/enumerator.m +++ b/src/tightdb/objc/test/enumerator.m @@ -10,6 +10,8 @@ #import #import #import +#import "TestHelper.h" + TIGHTDB_TABLE_3(EnumPeopleTable, Name, String, @@ -20,53 +22,57 @@ Hired, Bool, Age, Int) + + @interface MACTestEnumerator: SenTestCase @end @implementation MACTestEnumerator -- (void)testTutorial +- (void)testEnumerator { - //------------------------------------------------------ - NSLog(@"--- Creating tables ---"); - //------------------------------------------------------ - TightdbGroup *group = [TightdbGroup group]; - // Create new table in group - EnumPeopleTable *people = [group getTable:@"employees" withClass:[EnumPeopleTable class]]; - - // Add some rows - [people addName:@"John" Age:20 Hired:YES]; - [people addName:@"Mary" Age:21 Hired:NO]; - [people addName:@"Lars" Age:21 Hired:YES]; - [people addName:@"Phil" Age:43 Hired:NO]; - [people addName:@"Anni" Age:54 Hired:YES]; - - //------------------------------------------------------ - NSLog(@"--- Iterators ---"); - //------------------------------------------------------ - - // 1: Iterate over table - for (EnumPeopleTable_Cursor *row in people) { - NSLog(@"(Enum)%@ is %lld years old.", row.Name, row.Age); + @autoreleasepool { + //------------------------------------------------------ + NSLog(@"--- Creating tables ---"); + //------------------------------------------------------ + TightdbGroup *group = [TightdbGroup group]; + // Create new table in group + EnumPeopleTable *people = [group getTable:@"employees" withClass:[EnumPeopleTable class]]; + + // Add some rows + [people addName:@"John" Age:20 Hired:YES]; + [people addName:@"Mary" Age:21 Hired:NO]; + [people addName:@"Lars" Age:21 Hired:YES]; + [people addName:@"Phil" Age:43 Hired:NO]; + [people addName:@"Anni" Age:54 Hired:YES]; + + //------------------------------------------------------ + NSLog(@"--- Iterators ---"); + //------------------------------------------------------ + + // 1: Iterate over table + for (EnumPeopleTable_Cursor *row in people) { + NSLog(@"(Enum)%@ is %lld years old.", row.Name, row.Age); + } + + // Do a query, and get all matches as TableView + EnumPeopleTable_View *res = [[[[people where].Hired equal:YES].Age between:20 to:30] findAll]; + NSLog(@"View count: %zu", [res count]); + // 2: Iterate over the resulting TableView + for (EnumPeopleTable_Cursor *row in res) { + NSLog(@"(Enum2) %@ is %lld years old.", row.Name, row.Age); + } + + // 3: Iterate over query (lazy) + + EnumPeopleTable_Query *q = [[people where].Age equal:21]; + NSLog(@"Query lazy count: %zu", [[q count] unsignedLongValue] ); + for (EnumPeopleTable_Cursor *row in q) { + NSLog(@"(Enum3) %@ is %lld years old.", row.Name, row.Age); + if (row.Name == nil) + break; + } } - - // Do a query, and get all matches as TableView - EnumPeopleTable_View *res = [[[[people where].Hired equal:YES].Age between:20 to:30] findAll]; - NSLog(@"View count: %zu", [res count]); - // 2: Iterate over the resulting TableView - for (EnumPeopleTable_Cursor *row in res) { - NSLog(@"(Enum2) %@ is %lld years old.", row.Name, row.Age); - } - - // 3: Iterate over query (lazy) - - EnumPeopleTable_Query *q = [[people where].Age equal:21]; - NSLog(@"Query lazy count: %zu", [[q count] unsignedLongValue] ); - for (EnumPeopleTable_Cursor *row in q) { - NSLog(@"(Enum3) %@ is %lld years old.", row.Name, row.Age); - if (row.Name == nil) - break; - } - + TEST_CHECK_ALLOC; } @end diff --git a/src/tightdb/objc/test/err_handling.mm b/src/tightdb/objc/test/err_handling.mm index c84b22deea..97f96f25a1 100644 --- a/src/tightdb/objc/test/err_handling.mm +++ b/src/tightdb/objc/test/err_handling.mm @@ -38,6 +38,13 @@ TableCol, TestQueryErrSub, MixedCol, Mixed) +#ifdef TIGHTDB_DEBUG +extern int TightdbViewAllocateCount; +extern int TightdbCursorAllocateCount; +extern int TightdbGroupAllocateCount; +extern int TightdbSpecAllocateCount; +extern int TightdbTableAllocateCount; +#endif @interface MACTestErrHandling: SenTestCase @end @@ -45,428 +52,455 @@ @implementation MACTestErrHandling - (void)testErrHandling { - NSError *error = nil; - - //------------------------------------------------------ - NSLog(@"--- Creating tables ---"); - //------------------------------------------------------ - - TightdbGroup *group = [TightdbGroup group]; - // Create new table in group - PeopleErrTable *people = [group getTable:@"employees" withClass:[PeopleErrTable class]]; - - // Add some rows - error = nil; - if (![people addName:@"John" Age:20 Hired:YES error:&error]) { - NSLog(@"%@", [error localizedDescription]); - STFail(@"This should have worked"); - } - error = nil; - if (![people addName:@"Mary" Age:21 Hired:NO error:&error]) { - NSLog(@"%@", [error localizedDescription]); - STFail(@"This should have worked"); - } - if (![people addName:@"Lars" Age:21 Hired:YES error:&error]) { - NSLog(@"%@", [error localizedDescription]); - STFail(@"This should have worked"); - } - error = nil; - if (![people addName:@"Phil" Age:43 Hired:NO error:&error]) { - NSLog(@"%@", [error localizedDescription]); - STFail(@"This should have worked"); - } - error = nil; - if (![people addName:@"Anni" Age:54 Hired:YES error:&error]) { - NSLog(@"%@", [error localizedDescription]); - STFail(@"This should have worked"); - } - - // Insert at specific position - [people insertAtIndex:2 Name:@"Frank" Age:34 Hired:YES]; - - // Getting the size of the table - NSLog(@"PeopleErrTable Size: %lu - is %@. [6 - not empty]", [people count], - [people isEmpty] ? @"empty" : @"not empty"); - - NSFileManager *fm = [NSFileManager defaultManager]; - - // Write the group to disk - [fm removeItemAtPath:@"peopleErr.tightdb" error:NULL]; - error = nil; - if (![group write:@"peopleErr.tightdb" error:&error]) { - NSLog(@"%@", [error localizedDescription]); - STFail(@"No error expected"); - } - - //------------------------------------------------------ - NSLog(@"--- Changing permissions ---"); - //------------------------------------------------------ - - NSMutableDictionary *attributes = [NSMutableDictionary dictionaryWithCapacity:1]; - [attributes setValue:[NSNumber numberWithShort:0444] forKey:NSFilePosixPermissions]; - - error = nil; - [fm setAttributes:attributes ofItemAtPath:@"peopleErr.tightdb" error:&error]; - if (error) { - STFail(@"Failed to set readonly attributes"); - } - - //------------------------------------------------------ - NSLog(@"--- Reopen and manipulate ---"); - //------------------------------------------------------ - - // Load a group from disk (and try to update, even though it is readonly) - error = nil; - TightdbGroup *fromDisk = [TightdbGroup groupWithFilename:@"peopleErr.tightdb" error:&error]; - if (error) { - NSLog(@"%@", [error localizedDescription]); - } else { - STFail(@"Since file cannot be opened, we should have gotten an error here."); - } - - //------------------------------------------------------ - NSLog(@"--- Make normal again ---"); - //------------------------------------------------------ - - [attributes setValue:[NSNumber numberWithShort:0644] forKey:NSFilePosixPermissions]; - - error = nil; - [fm setAttributes:attributes ofItemAtPath:@"peopleErr.tightdb" error:&error]; - if (error) { - STFail(@"Failed to set readonly attributes"); - } - - error = nil; - fromDisk = [TightdbGroup groupWithFilename:@"peopleErr.tightdb" error:&error]; - if (error) { - NSLog(@"%@", [error localizedDescription]); - STFail(@"File should have been possible to open"); - } - - PeopleErrTable *diskTable = [fromDisk getTable:@"employees" withClass:[PeopleErrTable class]]; - - // Fake readonly. - [((TightdbTable *)diskTable) setReadOnly:true]; - - NSLog(@"Disktable size: %zu", [diskTable count]); - - error = nil; - if (![diskTable addName:@"Anni" Age:54 Hired:YES error:&error]) { - NSLog(@"%@", [error localizedDescription]); - } else { - STFail(@"addName to readonly should have failed."); + @autoreleasepool { + NSError *error = nil; + + //------------------------------------------------------ + NSLog(@"--- Creating tables ---"); + //------------------------------------------------------ + + TightdbGroup *group = [TightdbGroup group]; + // Create new table in group + PeopleErrTable *people = [group getTable:@"employees" withClass:[PeopleErrTable class]]; + + // Add some rows + error = nil; + if (![people addName:@"John" Age:20 Hired:YES error:&error]) { + NSLog(@"%@", [error localizedDescription]); + STFail(@"This should have worked"); + } + error = nil; + if (![people addName:@"Mary" Age:21 Hired:NO error:&error]) { + NSLog(@"%@", [error localizedDescription]); + STFail(@"This should have worked"); + } + if (![people addName:@"Lars" Age:21 Hired:YES error:&error]) { + NSLog(@"%@", [error localizedDescription]); + STFail(@"This should have worked"); + } + error = nil; + if (![people addName:@"Phil" Age:43 Hired:NO error:&error]) { + NSLog(@"%@", [error localizedDescription]); + STFail(@"This should have worked"); + } + error = nil; + if (![people addName:@"Anni" Age:54 Hired:YES error:&error]) { + NSLog(@"%@", [error localizedDescription]); + STFail(@"This should have worked"); + } + + // Insert at specific position + [people insertAtIndex:2 Name:@"Frank" Age:34 Hired:YES]; + + // Getting the size of the table + NSLog(@"PeopleErrTable Size: %lu - is %@. [6 - not empty]", [people count], + [people isEmpty] ? @"empty" : @"not empty"); + + NSFileManager *fm = [NSFileManager defaultManager]; + + // Write the group to disk + [fm removeItemAtPath:@"peopleErr.tightdb" error:NULL]; + error = nil; + if (![group write:@"peopleErr.tightdb" error:&error]) { + NSLog(@"%@", [error localizedDescription]); + STFail(@"No error expected"); + } + + //------------------------------------------------------ + NSLog(@"--- Changing permissions ---"); + //------------------------------------------------------ + + NSMutableDictionary *attributes = [NSMutableDictionary dictionaryWithCapacity:1]; + [attributes setValue:[NSNumber numberWithShort:0444] forKey:NSFilePosixPermissions]; + + error = nil; + [fm setAttributes:attributes ofItemAtPath:@"peopleErr.tightdb" error:&error]; + if (error) { + STFail(@"Failed to set readonly attributes"); + } + + //------------------------------------------------------ + NSLog(@"--- Reopen and manipulate ---"); + //------------------------------------------------------ + + // Load a group from disk (and try to update, even though it is readonly) + error = nil; + TightdbGroup *fromDisk = [TightdbGroup groupWithFilename:@"peopleErr.tightdb" error:&error]; + if (error) { + NSLog(@"%@", [error localizedDescription]); + } else { + STFail(@"Since file cannot be opened, we should have gotten an error here."); + } + + //------------------------------------------------------ + NSLog(@"--- Make normal again ---"); + //------------------------------------------------------ + + [attributes setValue:[NSNumber numberWithShort:0644] forKey:NSFilePosixPermissions]; + + error = nil; + [fm setAttributes:attributes ofItemAtPath:@"peopleErr.tightdb" error:&error]; + if (error) { + STFail(@"Failed to set readonly attributes"); + } + + error = nil; + fromDisk = [TightdbGroup groupWithFilename:@"peopleErr.tightdb" error:&error]; + if (error) { + NSLog(@"%@", [error localizedDescription]); + STFail(@"File should have been possible to open"); + } + + PeopleErrTable *diskTable = [fromDisk getTable:@"employees" withClass:[PeopleErrTable class]]; + + // Fake readonly. + [((TightdbTable *)diskTable) setReadOnly:true]; + + NSLog(@"Disktable size: %zu", [diskTable count]); + + error = nil; + if (![diskTable addName:@"Anni" Age:54 Hired:YES error:&error]) { + NSLog(@"%@", [error localizedDescription]); + } else { + STFail(@"addName to readonly should have failed."); + } + + NSLog(@"Disktable size: %zu", [diskTable count]); } - - NSLog(@"Disktable size: %zu", [diskTable count]); +#ifdef TIGHTDB_DEBUG + STAssertEquals(0, TightdbViewAllocateCount, @"Zero TightdbView allocated"); + STAssertEquals(0, TightdbCursorAllocateCount, @"Zero TightdbCursor allocated"); + STAssertEquals(0, TightdbGroupAllocateCount, @"Zero TightdbGroup allocated"); + STAssertEquals(0, TightdbSpecAllocateCount, @"Zero TightdbSpec allocated"); + STAssertEquals(0, TightdbTableAllocateCount, @"Zero TightdbTable allocated"); +#endif } -(void)testErrorInsert { - NSError *error; - - // Create table with all column types - TightdbTable *table = [[TightdbTable alloc] init]; - TightdbSpec *s = [table getSpec]; - if (![s addColumn:tightdb_Int name:@"int" error:&error]) { - NSLog(@"%@", [error localizedDescription]); - STFail(@"addColumn failed."); - } - if (![s addColumn:tightdb_Bool name:@"bool" error:&error]) { - NSLog(@"%@", [error localizedDescription]); - STFail(@"addColumn failed."); - } - - if (![s addColumn:tightdb_Date name:@"date" error:&error]) { - NSLog(@"%@", [error localizedDescription]); - STFail(@"addColumn failed."); - } - if (![s addColumn:tightdb_String name:@"string" error:&error]) { - NSLog(@"%@", [error localizedDescription]); - STFail(@"addColumn failed."); - } - if (![s addColumn:tightdb_String name:@"string_long" error:&error]) { - NSLog(@"%@", [error localizedDescription]); - STFail(@"addColumn failed."); - } - if (![s addColumn:tightdb_String name:@"string_enum" error:&error]) { - NSLog(@"%@", [error localizedDescription]); - STFail(@"addColumn failed."); - } - if (![s addColumn:tightdb_Binary name:@"binary" error:&error]) { - NSLog(@"%@", [error localizedDescription]); - STFail(@"addColumn failed."); - } - if (![s addColumn:tightdb_Mixed name:@"mixed" error:&error]) { - NSLog(@"%@", [error localizedDescription]); - STFail(@"addColumn failed."); - } - TightdbSpec *sub; - if (!(sub = [s addColumnTable:@"tables" error:&error])) { - NSLog(@"%@", [error localizedDescription]); - STFail(@"addColumn failed."); - } - if (![sub addColumn:tightdb_Int name:@"sub_first" error:&error]) { - NSLog(@"%@", [error localizedDescription]); - STFail(@"addColumn failed."); - } - if (![sub addColumn:tightdb_String name:@"sub_second" error:&error]) { - NSLog(@"%@", [error localizedDescription]); - STFail(@"addColumn failed."); - } - if (![table updateFromSpecWithError:&error]) { - NSLog(@"%@", [error localizedDescription]); - STFail(@"UpdateFromSpec failed."); - } - - // Add some rows - for (size_t i = 0; i < 15; ++i) { - if (![table insertInt:0 ndx:i value:i error:&error]) { + @autoreleasepool { + NSError *error; + + // Create table with all column types + TightdbTable *table = [[TightdbTable alloc] init]; + TightdbSpec *s = [table getSpec]; + if (![s addColumn:tightdb_Int name:@"int" error:&error]) { NSLog(@"%@", [error localizedDescription]); - STFail(@"Insert failed."); + STFail(@"addColumn failed."); } - if (![table insertBool:1 ndx:i value:(i % 2 ? YES : NO) error:&error]) { + if (![s addColumn:tightdb_Bool name:@"bool" error:&error]) { NSLog(@"%@", [error localizedDescription]); - STFail(@"Insert failed."); + STFail(@"addColumn failed."); } - if (![table insertDate:2 ndx:i value:12345 error:&error]) { + + if (![s addColumn:tightdb_Date name:@"date" error:&error]) { NSLog(@"%@", [error localizedDescription]); - STFail(@"Insert failed."); + STFail(@"addColumn failed."); } - if (![table insertString:3 ndx:i value:[NSString stringWithFormat:@"string %zu", i] error:&error]) { + if (![s addColumn:tightdb_String name:@"string" error:&error]) { NSLog(@"%@", [error localizedDescription]); - STFail(@"Insert failed."); + STFail(@"addColumn failed."); } - if (![table insertString:4 ndx:i value:@" Very long string.............." error:&error]) { + if (![s addColumn:tightdb_String name:@"string_long" error:&error]) { NSLog(@"%@", [error localizedDescription]); - STFail(@"Insert failed."); + STFail(@"addColumn failed."); + } + if (![s addColumn:tightdb_String name:@"string_enum" error:&error]) { + NSLog(@"%@", [error localizedDescription]); + STFail(@"addColumn failed."); + } + if (![s addColumn:tightdb_Binary name:@"binary" error:&error]) { + NSLog(@"%@", [error localizedDescription]); + STFail(@"addColumn failed."); + } + if (![s addColumn:tightdb_Mixed name:@"mixed" error:&error]) { + NSLog(@"%@", [error localizedDescription]); + STFail(@"addColumn failed."); + } + TightdbSpec *sub; + if (!(sub = [s addColumnTable:@"tables" error:&error])) { + NSLog(@"%@", [error localizedDescription]); + STFail(@"addColumn failed."); + } + if (![sub addColumn:tightdb_Int name:@"sub_first" error:&error]) { + NSLog(@"%@", [error localizedDescription]); + STFail(@"addColumn failed."); + } + if (![sub addColumn:tightdb_String name:@"sub_second" error:&error]) { + NSLog(@"%@", [error localizedDescription]); + STFail(@"addColumn failed."); + } + if (![table updateFromSpecWithError:&error]) { + NSLog(@"%@", [error localizedDescription]); + STFail(@"UpdateFromSpec failed."); } - switch (i % 3) { - case 0: - if (![table insertString:5 ndx:i value:@"test1" error:&error]) { + // Add some rows + for (size_t i = 0; i < 15; ++i) { + if (![table insertInt:0 ndx:i value:i error:&error]) { + NSLog(@"%@", [error localizedDescription]); + STFail(@"Insert failed."); + } + if (![table insertBool:1 ndx:i value:(i % 2 ? YES : NO) error:&error]) { + NSLog(@"%@", [error localizedDescription]); + STFail(@"Insert failed."); + } + if (![table insertDate:2 ndx:i value:12345 error:&error]) { + NSLog(@"%@", [error localizedDescription]); + STFail(@"Insert failed."); + } + if (![table insertString:3 ndx:i value:[NSString stringWithFormat:@"string %zu", i] error:&error]) { + NSLog(@"%@", [error localizedDescription]); + STFail(@"Insert failed."); + } + if (![table insertString:4 ndx:i value:@" Very long string.............." error:&error]) { + NSLog(@"%@", [error localizedDescription]); + STFail(@"Insert failed."); + } + + switch (i % 3) { + case 0: + if (![table insertString:5 ndx:i value:@"test1" error:&error]) { + NSLog(@"%@", [error localizedDescription]); + STFail(@"Insert failed."); + } + break; + case 1: + if (![table insertString:5 ndx:i value:@"test2" error:&error]) { + NSLog(@"%@", [error localizedDescription]); + STFail(@"Insert failed."); + } + break; + case 2: + if (![table insertString:5 ndx:i value:@"test3" error:&error]) { + NSLog(@"%@", [error localizedDescription]); + STFail(@"Insert failed."); + } + break; + } + + if (![table insertBinary:6 ndx:i data:"binary" size:7 error:&error]) { + NSLog(@"%@", [error localizedDescription]); + STFail(@"Insert failed."); + } + switch (i % 3) { + case 0: + if (![table insertMixed:7 ndx:i value:[TightdbMixed mixedWithBool:NO] error:&error]) { + NSLog(@"%@", [error localizedDescription]); + STFail(@"Insert failed."); + } + break; + case 1: + if (![table insertMixed:7 ndx:i value:[TightdbMixed mixedWithInt64:i] error:&error]) { + NSLog(@"%@", [error localizedDescription]); + STFail(@"Insert failed."); + } + break; + case 2: + if (![table insertMixed:7 ndx:i value:[TightdbMixed mixedWithString:@"string"] error:&error]) { + NSLog(@"%@", [error localizedDescription]); + STFail(@"Insert failed."); + } + break; + } + if (![table insertSubtable:8 ndx:i error:&error]) { + NSLog(@"%@", [error localizedDescription]); + STFail(@"Insert failed."); + } + + if (![table insertDoneWithError:&error]) { + NSLog(@"%@", [error localizedDescription]); + STFail(@"InsertDone failed."); + } + + // Add sub-tables + if (i == 2) { + TightdbTable *subtable = [table getSubtable:8 ndx:i]; + if (![subtable insertInt:0 ndx:0 value:42 error:&error]) { NSLog(@"%@", [error localizedDescription]); STFail(@"Insert failed."); } - break; - case 1: - if (![table insertString:5 ndx:i value:@"test2" error:&error]) { + if (![subtable insertString:1 ndx:0 value:@"meaning" error:&error]) { NSLog(@"%@", [error localizedDescription]); STFail(@"Insert failed."); } - break; - case 2: - if (![table insertString:5 ndx:i value:@"test3" error:&error]) { + if (![subtable insertDoneWithError:&error]) { NSLog(@"%@", [error localizedDescription]); - STFail(@"Insert failed."); + STFail(@"InsertDone failed."); } - break; + } + } - if (![table insertBinary:6 ndx:i data:"binary" size:7 error:&error]) { + // We also want a ColumnStringEnum + if (![table optimize]) { NSLog(@"%@", [error localizedDescription]); STFail(@"Insert failed."); } - switch (i % 3) { - case 0: - if (![table insertMixed:7 ndx:i value:[TightdbMixed mixedWithBool:NO] error:&error]) { - NSLog(@"%@", [error localizedDescription]); - STFail(@"Insert failed."); - } - break; - case 1: - if (![table insertMixed:7 ndx:i value:[TightdbMixed mixedWithInt64:i] error:&error]) { - NSLog(@"%@", [error localizedDescription]); - STFail(@"Insert failed."); - } - break; - case 2: - if (![table insertMixed:7 ndx:i value:[TightdbMixed mixedWithString:@"string"] error:&error]) { - NSLog(@"%@", [error localizedDescription]); - STFail(@"Insert failed."); - } - break; + + // Test Deletes + if (![table remove:14 error:&error]) { + NSLog(@"%@", [error localizedDescription]); + STFail(@"Remove failed."); } - if (![table insertSubtable:8 ndx:i error:&error]) { + if (![table remove:0 error:&error]) { NSLog(@"%@", [error localizedDescription]); - STFail(@"Insert failed."); + STFail(@"Remove failed."); } - - if (![table insertDoneWithError:&error]) { + if (![table remove:5 error:&error]) { NSLog(@"%@", [error localizedDescription]); - STFail(@"InsertDone failed."); + STFail(@"Remove failed."); } - // Add sub-tables - if (i == 2) { - TightdbTable *subtable = [table getSubtable:8 ndx:i]; - if (![subtable insertInt:0 ndx:0 value:42 error:&error]) { - NSLog(@"%@", [error localizedDescription]); - STFail(@"Insert failed."); - } - if (![subtable insertString:1 ndx:0 value:@"meaning" error:&error]) { - NSLog(@"%@", [error localizedDescription]); - STFail(@"Insert failed."); - } - if (![subtable insertDoneWithError:&error]) { - NSLog(@"%@", [error localizedDescription]); - STFail(@"InsertDone failed."); - } + STAssertEquals([table count], (size_t)12, @"Size should have been 12"); +#ifdef TIGHTDB_DEBUG + [table verify]; +#endif + + // Test Clear + if (![table clearWithError:&error]) { + NSLog(@"%@", [error localizedDescription]); + STFail(@"Clear failed."); } + STAssertEquals([table count], (size_t)0, @"Size should have been zero"); - } - - // We also want a ColumnStringEnum - if (![table optimize]) { - NSLog(@"%@", [error localizedDescription]); - STFail(@"Insert failed."); - } - - // Test Deletes - if (![table remove:14 error:&error]) { - NSLog(@"%@", [error localizedDescription]); - STFail(@"Remove failed."); - } - if (![table remove:0 error:&error]) { - NSLog(@"%@", [error localizedDescription]); - STFail(@"Remove failed."); - } - if (![table remove:5 error:&error]) { - NSLog(@"%@", [error localizedDescription]); - STFail(@"Remove failed."); - } - - STAssertEquals([table count], (size_t)12, @"Size should have been 12"); #ifdef TIGHTDB_DEBUG - [table verify]; + [table verify]; #endif - - // Test Clear - if (![table clearWithError:&error]) { - NSLog(@"%@", [error localizedDescription]); - STFail(@"Clear failed."); } - STAssertEquals([table count], (size_t)0, @"Size should have been zero"); - #ifdef TIGHTDB_DEBUG - [table verify]; + STAssertEquals(0, TightdbViewAllocateCount, @"Zero TightdbView allocated"); + STAssertEquals(0, TightdbCursorAllocateCount, @"Zero TightdbCursor allocated"); + STAssertEquals(0, TightdbGroupAllocateCount, @"Zero TightdbGroup allocated"); + STAssertEquals(0, TightdbSpecAllocateCount, @"Zero TightdbSpec allocated"); + STAssertEquals(0, TightdbTableAllocateCount, @"Zero TightdbTable allocated"); #endif } - (void)testQueryErrHandling { - TestQueryErrAllTypes *table = [[TestQueryErrAllTypes alloc] init]; - NSLog(@"Table: %@", table); - STAssertNotNil(table, @"Table is nil"); - - const char bin[4] = { 0, 1, 2, 3 }; - TightdbBinary *bin1 = [[TightdbBinary alloc] initWithData:bin size:sizeof bin / 2]; - TightdbBinary *bin2 = [[TightdbBinary alloc] initWithData:bin size:sizeof bin]; - time_t timeNow = [[NSDate date] timeIntervalSince1970]; - // TestQueryErrSub *subtab1 = [[TestQueryErrSub alloc] init]; - TestQueryErrSub *subtab2 = [[TestQueryErrSub alloc] init]; - [subtab2 addAge:100]; - TightdbMixed *mixInt1 = [TightdbMixed mixedWithInt64:1]; - TightdbMixed *mixSubtab = [TightdbMixed mixedWithTable:subtab2]; - - [table addBoolCol:NO IntCol:54 FloatCol:0.7 DoubleCol:0.8 StringCol:@"foo" - BinaryCol:bin1 DateCol:0 TableCol:nil MixedCol:mixInt1]; - - [table addBoolCol:YES IntCol:506 FloatCol:7.7 DoubleCol:8.8 StringCol:@"banach" - BinaryCol:bin2 DateCol:timeNow TableCol:subtab2 MixedCol:mixSubtab]; - - STAssertEquals([[[[table where].BoolCol equal:NO] count] unsignedLongValue], (size_t)1, @"BoolCol equal"); - STAssertEquals([[[[table where].IntCol equal:54] count] unsignedLongValue], (size_t)1, @"IntCol equal"); - STAssertEquals([[[[table where].FloatCol equal:0.7f] count] unsignedLongValue], (size_t)1, @"FloatCol equal"); - STAssertEquals([[[[table where].DoubleCol equal:0.8] count] unsignedLongValue], (size_t)1, @"DoubleCol equal"); - STAssertEquals([[[[table where].StringCol equal:@"foo"] count] unsignedLongValue], (size_t)1, @"StringCol equal"); - STAssertEquals([[[[table where].BinaryCol equal:bin1] count] unsignedLongValue], (size_t)1, @"BinaryCol equal"); - STAssertEquals([[[[table where].DateCol equal:0] count] unsignedLongValue], (size_t)1, @"DateCol equal"); - // These are not yet implemented - // STAssertEquals([[[table where].TableCol equal:subtab1] count], (size_t)1, @"TableCol equal"); - // STAssertEquals([[[table where].MixedCol equal:mixInt1] count], (size_t)1, @"MixedCol equal"); - - TestQueryErrAllTypes_Query *query = [[table where].BoolCol equal:NO]; - - STAssertEquals([[query.IntCol min] longLongValue], (int64_t)54, @"IntCol min"); - STAssertEquals([[query.IntCol max] longLongValue], (int64_t)54, @"IntCol max"); - STAssertEquals([[query.IntCol sum] longLongValue], (int64_t)54, @"IntCol sum"); - STAssertEquals([[query.IntCol avg] doubleValue], 54.0, @"IntCol avg"); - - STAssertEquals([[query.FloatCol min] floatValue], 0.7f, @"FloatCol min"); - STAssertEquals([[query.FloatCol max] floatValue], 0.7f, @"FloatCol max"); - STAssertEquals([[query.FloatCol sum] floatValue], 0.7f, @"FloatCol sum"); - STAssertEquals([[query.FloatCol avg] doubleValue], (double)0.7f, @"FloatCol avg"); - - STAssertEquals([[query.DoubleCol min] doubleValue], 0.8, @"DoubleCol min"); - STAssertEquals([[query.DoubleCol max] doubleValue], 0.8, @"DoubleCol max"); - STAssertEquals([[query.DoubleCol sum] doubleValue], 0.8, @"DoubleCol sum"); - STAssertEquals([[query.DoubleCol avg] doubleValue], 0.8, @"DoubleCol avg"); - - // Check that all column conditions return query objects of the - // right type - [[[table where].BoolCol equal:NO].BoolCol equal:NO]; - - [[[table where].IntCol equal:0].BoolCol equal:NO]; - [[[table where].IntCol notEqual:0].BoolCol equal:NO]; - [[[table where].IntCol less:0].BoolCol equal:NO]; - [[[table where].IntCol lessEqual:0].BoolCol equal:NO]; - [[[table where].IntCol greater:0].BoolCol equal:NO]; - [[[table where].IntCol greaterEqual:0].BoolCol equal:NO]; - [[[table where].IntCol between:0 to:0].BoolCol equal:NO]; - - [[[table where].FloatCol equal:0].BoolCol equal:NO]; - [[[table where].FloatCol notEqual:0].BoolCol equal:NO]; - [[[table where].FloatCol less:0].BoolCol equal:NO]; - [[[table where].FloatCol lessEqual:0].BoolCol equal:NO]; - [[[table where].FloatCol greater:0].BoolCol equal:NO]; - [[[table where].FloatCol greaterEqual:0].BoolCol equal:NO]; - [[[table where].FloatCol between:0 to:0].BoolCol equal:NO]; - - [[[table where].DoubleCol equal:0].BoolCol equal:NO]; - [[[table where].DoubleCol notEqual:0].BoolCol equal:NO]; - [[[table where].DoubleCol less:0].BoolCol equal:NO]; - [[[table where].DoubleCol lessEqual:0].BoolCol equal:NO]; - [[[table where].DoubleCol greater:0].BoolCol equal:NO]; - [[[table where].DoubleCol greaterEqual:0].BoolCol equal:NO]; - [[[table where].DoubleCol between:0 to:0].BoolCol equal:NO]; - - [[[table where].StringCol equal:@""].BoolCol equal:NO]; - [[[table where].StringCol equal:@"" caseSensitive:NO].BoolCol equal:NO]; - [[[table where].StringCol notEqual:@""].BoolCol equal:NO]; - [[[table where].StringCol notEqual:@"" caseSensitive:NO].BoolCol equal:NO]; - [[[table where].StringCol beginsWith:@""].BoolCol equal:NO]; - [[[table where].StringCol beginsWith:@"" caseSensitive:NO].BoolCol equal:NO]; - [[[table where].StringCol endsWith:@""].BoolCol equal:NO]; - [[[table where].StringCol endsWith:@"" caseSensitive:NO].BoolCol equal:NO]; - [[[table where].StringCol contains:@""].BoolCol equal:NO]; - [[[table where].StringCol contains:@"" caseSensitive:NO].BoolCol equal:NO]; - - [[[table where].BinaryCol equal:bin1].BoolCol equal:NO]; - [[[table where].BinaryCol notEqual:bin1].BoolCol equal:NO]; - [[[table where].BinaryCol beginsWith:bin1].BoolCol equal:NO]; - [[[table where].BinaryCol endsWith:bin1].BoolCol equal:NO]; - [[[table where].BinaryCol contains:bin1].BoolCol equal:NO]; - - TestQueryErrAllTypes_View *view = [[[[table where].DateCol equal:0].BoolCol equal:NO] findAll]; - for (size_t i = 0; i < [view count]; i++) { - NSLog(@"%zu: %c", i, [[view objectAtIndex:i] BoolCol]); + @autoreleasepool { + TestQueryErrAllTypes *table = [[TestQueryErrAllTypes alloc] init]; + NSLog(@"Table: %@", table); + STAssertNotNil(table, @"Table is nil"); + + const char bin[4] = { 0, 1, 2, 3 }; + TightdbBinary *bin1 = [[TightdbBinary alloc] initWithData:bin size:sizeof bin / 2]; + TightdbBinary *bin2 = [[TightdbBinary alloc] initWithData:bin size:sizeof bin]; + time_t timeNow = [[NSDate date] timeIntervalSince1970]; + // TestQueryErrSub *subtab1 = [[TestQueryErrSub alloc] init]; + TestQueryErrSub *subtab2 = [[TestQueryErrSub alloc] init]; + [subtab2 addAge:100]; + TightdbMixed *mixInt1 = [TightdbMixed mixedWithInt64:1]; + TightdbMixed *mixSubtab = [TightdbMixed mixedWithTable:subtab2]; + + [table addBoolCol:NO IntCol:54 FloatCol:0.7 DoubleCol:0.8 StringCol:@"foo" + BinaryCol:bin1 DateCol:0 TableCol:nil MixedCol:mixInt1]; + + [table addBoolCol:YES IntCol:506 FloatCol:7.7 DoubleCol:8.8 StringCol:@"banach" + BinaryCol:bin2 DateCol:timeNow TableCol:subtab2 MixedCol:mixSubtab]; + + STAssertEquals([[[[table where].BoolCol equal:NO] count] unsignedLongValue], (size_t)1, @"BoolCol equal"); + STAssertEquals([[[[table where].IntCol equal:54] count] unsignedLongValue], (size_t)1, @"IntCol equal"); + STAssertEquals([[[[table where].FloatCol equal:0.7f] count] unsignedLongValue], (size_t)1, @"FloatCol equal"); + STAssertEquals([[[[table where].DoubleCol equal:0.8] count] unsignedLongValue], (size_t)1, @"DoubleCol equal"); + STAssertEquals([[[[table where].StringCol equal:@"foo"] count] unsignedLongValue], (size_t)1, @"StringCol equal"); + STAssertEquals([[[[table where].BinaryCol equal:bin1] count] unsignedLongValue], (size_t)1, @"BinaryCol equal"); + STAssertEquals([[[[table where].DateCol equal:0] count] unsignedLongValue], (size_t)1, @"DateCol equal"); + // These are not yet implemented + // STAssertEquals([[[table where].TableCol equal:subtab1] count], (size_t)1, @"TableCol equal"); + // STAssertEquals([[[table where].MixedCol equal:mixInt1] count], (size_t)1, @"MixedCol equal"); + + TestQueryErrAllTypes_Query *query = [[table where].BoolCol equal:NO]; + + STAssertEquals([[query.IntCol min] longLongValue], (int64_t)54, @"IntCol min"); + STAssertEquals([[query.IntCol max] longLongValue], (int64_t)54, @"IntCol max"); + STAssertEquals([[query.IntCol sum] longLongValue], (int64_t)54, @"IntCol sum"); + STAssertEquals([[query.IntCol avg] doubleValue], 54.0, @"IntCol avg"); + + STAssertEquals([[query.FloatCol min] floatValue], 0.7f, @"FloatCol min"); + STAssertEquals([[query.FloatCol max] floatValue], 0.7f, @"FloatCol max"); + STAssertEquals([[query.FloatCol sum] floatValue], 0.7f, @"FloatCol sum"); + STAssertEquals([[query.FloatCol avg] doubleValue], (double)0.7f, @"FloatCol avg"); + + STAssertEquals([[query.DoubleCol min] doubleValue], 0.8, @"DoubleCol min"); + STAssertEquals([[query.DoubleCol max] doubleValue], 0.8, @"DoubleCol max"); + STAssertEquals([[query.DoubleCol sum] doubleValue], 0.8, @"DoubleCol sum"); + STAssertEquals([[query.DoubleCol avg] doubleValue], 0.8, @"DoubleCol avg"); + + // Check that all column conditions return query objects of the + // right type + [[[table where].BoolCol equal:NO].BoolCol equal:NO]; + + [[[table where].IntCol equal:0].BoolCol equal:NO]; + [[[table where].IntCol notEqual:0].BoolCol equal:NO]; + [[[table where].IntCol less:0].BoolCol equal:NO]; + [[[table where].IntCol lessEqual:0].BoolCol equal:NO]; + [[[table where].IntCol greater:0].BoolCol equal:NO]; + [[[table where].IntCol greaterEqual:0].BoolCol equal:NO]; + [[[table where].IntCol between:0 to:0].BoolCol equal:NO]; + + [[[table where].FloatCol equal:0].BoolCol equal:NO]; + [[[table where].FloatCol notEqual:0].BoolCol equal:NO]; + [[[table where].FloatCol less:0].BoolCol equal:NO]; + [[[table where].FloatCol lessEqual:0].BoolCol equal:NO]; + [[[table where].FloatCol greater:0].BoolCol equal:NO]; + [[[table where].FloatCol greaterEqual:0].BoolCol equal:NO]; + [[[table where].FloatCol between:0 to:0].BoolCol equal:NO]; + + [[[table where].DoubleCol equal:0].BoolCol equal:NO]; + [[[table where].DoubleCol notEqual:0].BoolCol equal:NO]; + [[[table where].DoubleCol less:0].BoolCol equal:NO]; + [[[table where].DoubleCol lessEqual:0].BoolCol equal:NO]; + [[[table where].DoubleCol greater:0].BoolCol equal:NO]; + [[[table where].DoubleCol greaterEqual:0].BoolCol equal:NO]; + [[[table where].DoubleCol between:0 to:0].BoolCol equal:NO]; + + [[[table where].StringCol equal:@""].BoolCol equal:NO]; + [[[table where].StringCol equal:@"" caseSensitive:NO].BoolCol equal:NO]; + [[[table where].StringCol notEqual:@""].BoolCol equal:NO]; + [[[table where].StringCol notEqual:@"" caseSensitive:NO].BoolCol equal:NO]; + [[[table where].StringCol beginsWith:@""].BoolCol equal:NO]; + [[[table where].StringCol beginsWith:@"" caseSensitive:NO].BoolCol equal:NO]; + [[[table where].StringCol endsWith:@""].BoolCol equal:NO]; + [[[table where].StringCol endsWith:@"" caseSensitive:NO].BoolCol equal:NO]; + [[[table where].StringCol contains:@""].BoolCol equal:NO]; + [[[table where].StringCol contains:@"" caseSensitive:NO].BoolCol equal:NO]; + + [[[table where].BinaryCol equal:bin1].BoolCol equal:NO]; + [[[table where].BinaryCol notEqual:bin1].BoolCol equal:NO]; + [[[table where].BinaryCol beginsWith:bin1].BoolCol equal:NO]; + [[[table where].BinaryCol endsWith:bin1].BoolCol equal:NO]; + [[[table where].BinaryCol contains:bin1].BoolCol equal:NO]; + + TestQueryErrAllTypes_View *view = [[[[table where].DateCol equal:0].BoolCol equal:NO] findAll]; + for (size_t i = 0; i < [view count]; i++) { + NSLog(@"%zu: %c", i, [[view objectAtIndex:i] BoolCol]); + } + + + [[[table where].DateCol notEqual:0].BoolCol equal:NO]; + [[[table where].DateCol less:0].BoolCol equal:NO]; + [[[table where].DateCol lessEqual:0].BoolCol equal:NO]; + [[[table where].DateCol greater:0].BoolCol equal:NO]; + [[[table where].DateCol greaterEqual:0].BoolCol equal:NO]; + [[[table where].DateCol between:0 to:0].BoolCol equal:NO]; + + // These are not yet implemented + // [[[table where].TableCol equal:nil].BoolCol equal:NO]; + // [[[table where].TableCol notEqual:nil].BoolCol equal:NO]; + + // [[[table where].MixedCol equal:mixInt1].BoolCol equal:NO]; + // [[[table where].MixedCol notEqual:mixInt1].BoolCol equal:NO]; } - - - [[[table where].DateCol notEqual:0].BoolCol equal:NO]; - [[[table where].DateCol less:0].BoolCol equal:NO]; - [[[table where].DateCol lessEqual:0].BoolCol equal:NO]; - [[[table where].DateCol greater:0].BoolCol equal:NO]; - [[[table where].DateCol greaterEqual:0].BoolCol equal:NO]; - [[[table where].DateCol between:0 to:0].BoolCol equal:NO]; - - // These are not yet implemented - // [[[table where].TableCol equal:nil].BoolCol equal:NO]; - // [[[table where].TableCol notEqual:nil].BoolCol equal:NO]; - - // [[[table where].MixedCol equal:mixInt1].BoolCol equal:NO]; - // [[[table where].MixedCol notEqual:mixInt1].BoolCol equal:NO]; +#ifdef TIGHTDB_DEBUG + STAssertEquals(0, TightdbViewAllocateCount, @"Zero TightdbView allocated"); + STAssertEquals(0, TightdbCursorAllocateCount, @"Zero TightdbCursor allocated"); + STAssertEquals(0, TightdbGroupAllocateCount, @"Zero TightdbGroup allocated"); + STAssertEquals(0, TightdbSpecAllocateCount, @"Zero TightdbSpec allocated"); + STAssertEquals(0, TightdbTableAllocateCount, @"Zero TightdbTable allocated"); +#endif } diff --git a/src/tightdb/objc/test/tutorial.m b/src/tightdb/objc/test/tutorial.m index beea233dd6..c469d55184 100644 --- a/src/tightdb/objc/test/tutorial.m +++ b/src/tightdb/objc/test/tutorial.m @@ -28,152 +28,171 @@ Hired, Bool, Age, Int) + +#ifdef TIGHTDB_DEBUG +extern int TightdbViewAllocateCount; +extern int TightdbCursorAllocateCount; +extern int TightdbGroupAllocateCount; +extern int TightdbSpecAllocateCount; +extern int TightdbTableAllocateCount; +#endif + @interface MACTestTutorial: SenTestCase @end @implementation MACTestTutorial - (void)testTutorial { - //------------------------------------------------------ - NSLog(@"--- Creating tables ---"); - //------------------------------------------------------ - - TightdbGroup *group = [TightdbGroup group]; - // Create new table in group - PeopleTable *people = [group getTable:@"employees" withClass:[PeopleTable class]]; - - // Add some rows - [people addName:@"John" Age:20 Hired:YES]; - [people addName:@"Mary" Age:21 Hired:NO]; - [people addName:@"Lars" Age:21 Hired:YES]; - [people addName:@"Phil" Age:43 Hired:NO]; - [people addName:@"Anni" Age:54 Hired:YES]; - - // Insert at specific position - [people insertAtIndex:2 Name:@"Frank" Age:34 Hired:YES]; - - // Getting the size of the table - NSLog(@"PeopleTable Size: %lu - is %@. [6 - not empty]", [people count], - [people isEmpty] ? @"empty" : @"not empty"); - - //------------------------------------------------------ - NSLog(@"--- Working with individual rows ---"); - //------------------------------------------------------ - - // Getting values - NSString * name = [people objectAtIndex:5].Name; // => 'Anni' - // Using a cursor - PeopleTable_Cursor *myRow = [people objectAtIndex:5]; - int64_t age = myRow.Age; // => 54 - BOOL hired = myRow.Hired; // => true - NSLog(@"%@ is %lld years old.", name, age); - if (hired) NSLog(@"is hired."); - - // Setting values - NSError *error; - if (![[people objectAtIndex:5] setAge:43 error:&error]) { // Getting younger - NSLog(@"%@", [error localizedDescription]); - STFail(@"This action should not fail"); - } - // or with dot-syntax: - myRow.Age += 1; // Happy birthday! - NSLog(@"%@ age is now %lld. [44]", myRow.Name, myRow.Age); - - // Get last row - NSString *lastname = [people lastObject].Name; // => "Anni" - NSLog(@"Last name is %@. [Anni]", lastname); - - // Change a row - not implemented yet - // [people setAtIndex:4 Name:"Eric" Age:50 Hired:YES]; - - // Delete row - [people remove:2]; - NSLog(@"%lu rows after remove. [5]", [people count]); // 5 - STAssertEquals([people count], (size_t)5,@"rows should be 5"); - - // Iterating over rows: - for (size_t i = 0; i < [people count]; ++i) { - PeopleTable_Cursor *row = [people objectAtIndex:i]; - NSLog(@"(Rows) %@ is %lld years old.", row.Name, row.Age); - } - - //------------------------------------------------------ - NSLog(@"--- Simple Searching ---"); - //------------------------------------------------------ - - size_t row; - row = [people.Name find:@"Philip"]; // row = (size_t)-1 - NSLog(@"Philip: %zu [-1]", row); - STAssertEquals(row, (size_t)-1,@"Philip should not be there", nil); - - row = [people.Name find:@"Mary"]; - NSLog(@"Mary: %zu", row); - STAssertEquals(row, (size_t)1,@"Mary should have been there", nil); - - TightdbView *view = [people.Age findAll:21]; - size_t cnt = [view count]; // cnt = 2 - STAssertEquals(cnt, (size_t)2,@"Should be two rows in view", nil); - - //------------------------------------------------------ - NSLog(@"--- Queries ---"); - //------------------------------------------------------ - - // Create query (current employees between 20 and 30 years old) - PeopleTable_Query *q = [[[people where].Hired equal:YES] // Implicit AND - .Age between:20 to:30]; - - // Get number of matching entries - NSLog(@"Query count: %@", [q count]); - STAssertEquals([[q count] unsignedLongValue] , (size_t)2,@"Expected 2 rows in query", nil); - - // Get the average age - currently only a low-level interface! - double avg = [[q.Age avg] doubleValue]; - NSLog(@"Average: %f [20.5]", avg); - STAssertEquals(avg, 20.5,@"Expected 20.5 average", nil); - - // Execute the query and return a table (view) - TightdbView *res = [q findAll]; - for (size_t i = 0; i < [res count]; ++i) { - NSLog(@"%zu: %@ is %lld years old", i, - [people objectAtIndex:i].Name, - [people objectAtIndex:i].Age); - } - - //------------------------------------------------------ - NSLog(@"--- Serialization ---"); - //------------------------------------------------------ - - NSFileManager *fm = [NSFileManager defaultManager]; - - // Write the group to disk - [fm removeItemAtPath:@"employees.tightdb" error:NULL]; - [group write:@"employees.tightdb"]; - - // Load a group from disk (and print contents) - TightdbGroup *fromDisk = [TightdbGroup groupWithFilename:@"employees.tightdb"]; - PeopleTable *diskTable = [fromDisk getTable:@"employees" withClass:[PeopleTable class]]; - - [diskTable addName:@"Anni" Age:54 Hired:YES]; - - NSLog(@"Disktable size: %zu", [diskTable count]); - - for (size_t i = 0; i < [diskTable count]; i++) { - PeopleTable_Cursor *cursor = [diskTable objectAtIndex:i]; - NSLog(@"%zu: %@", i, [cursor Name]); - NSLog(@"%zu: %@", i, cursor.Name); - } - - // Write same group to memory buffer - size_t size; - const char* const data = [group writeToMem:&size]; - - // Load a group from memory (and print contents) - TightdbGroup *fromMem = [TightdbGroup groupWithBuffer:data size:size]; - PeopleTable *memTable = [fromMem getTable:@"employees" withClass:[PeopleTable class]]; - for (size_t i = 0; i < [memTable count]; i++) { - PeopleTable_Cursor *cursor = [memTable objectAtIndex:i]; - NSLog(@"%zu: %@", i, cursor.Name); + @autoreleasepool { + //------------------------------------------------------ + NSLog(@"--- Creating tables ---"); + //------------------------------------------------------ + + TightdbGroup *group = [TightdbGroup group]; + // Create new table in group + PeopleTable *people = [group getTable:@"employees" withClass:[PeopleTable class]]; + + // Add some rows + [people addName:@"John" Age:20 Hired:YES]; + [people addName:@"Mary" Age:21 Hired:NO]; + [people addName:@"Lars" Age:21 Hired:YES]; + [people addName:@"Phil" Age:43 Hired:NO]; + [people addName:@"Anni" Age:54 Hired:YES]; + + // Insert at specific position + [people insertAtIndex:2 Name:@"Frank" Age:34 Hired:YES]; + + // Getting the size of the table + NSLog(@"PeopleTable Size: %lu - is %@. [6 - not empty]", [people count], + [people isEmpty] ? @"empty" : @"not empty"); + + //------------------------------------------------------ + NSLog(@"--- Working with individual rows ---"); + //------------------------------------------------------ + + // Getting values + NSString * name = [people objectAtIndex:5].Name; // => 'Anni' + // Using a cursor + PeopleTable_Cursor *myRow = [people objectAtIndex:5]; + int64_t age = myRow.Age; // => 54 + BOOL hired = myRow.Hired; // => true + NSLog(@"%@ is %lld years old.", name, age); + if (hired) NSLog(@"is hired."); + + // Setting values + NSError *error; + if (![[people objectAtIndex:5] setAge:43 error:&error]) { // Getting younger + NSLog(@"%@", [error localizedDescription]); + STFail(@"This action should not fail"); + } + // or with dot-syntax: + myRow.Age += 1; // Happy birthday! + NSLog(@"%@ age is now %lld. [44]", myRow.Name, myRow.Age); + + // Get last row + NSString *lastname = [people lastObject].Name; // => "Anni" + NSLog(@"Last name is %@. [Anni]", lastname); + + // Change a row - not implemented yet + // [people setAtIndex:4 Name:"Eric" Age:50 Hired:YES]; + + // Delete row + [people remove:2]; + NSLog(@"%lu rows after remove. [5]", [people count]); // 5 + STAssertEquals([people count], (size_t)5,@"rows should be 5"); + + // Iterating over rows: + for (size_t i = 0; i < [people count]; ++i) { + PeopleTable_Cursor *row = [people objectAtIndex:i]; + NSLog(@"(Rows) %@ is %lld years old.", row.Name, row.Age); + } + + //------------------------------------------------------ + NSLog(@"--- Simple Searching ---"); + //------------------------------------------------------ + + size_t row; + row = [people.Name find:@"Philip"]; // row = (size_t)-1 + NSLog(@"Philip: %zu [-1]", row); + STAssertEquals(row, (size_t)-1,@"Philip should not be there", nil); + + row = [people.Name find:@"Mary"]; + NSLog(@"Mary: %zu", row); + STAssertEquals(row, (size_t)1,@"Mary should have been there", nil); + + TightdbView *view = [people.Age findAll:21]; + size_t cnt = [view count]; // cnt = 2 + STAssertEquals(cnt, (size_t)2,@"Should be two rows in view", nil); + + //------------------------------------------------------ + NSLog(@"--- Queries ---"); + //------------------------------------------------------ + + // Create query (current employees between 20 and 30 years old) + PeopleTable_Query *q = [[[people where].Hired equal:YES] // Implicit AND + .Age between:20 to:30]; + + // Get number of matching entries + NSLog(@"Query count: %@", [q count]); + STAssertEquals([[q count] unsignedLongValue] , (size_t)2,@"Expected 2 rows in query", nil); + + // Get the average age - currently only a low-level interface! + double avg = [[q.Age avg] doubleValue]; + NSLog(@"Average: %f [20.5]", avg); + STAssertEquals(avg, 20.5,@"Expected 20.5 average", nil); + + // Execute the query and return a table (view) + TightdbView *res = [q findAll]; + for (size_t i = 0; i < [res count]; ++i) { + NSLog(@"%zu: %@ is %lld years old", i, + [people objectAtIndex:i].Name, + [people objectAtIndex:i].Age); + } + + //------------------------------------------------------ + NSLog(@"--- Serialization ---"); + //------------------------------------------------------ + + NSFileManager *fm = [NSFileManager defaultManager]; + + // Write the group to disk + [fm removeItemAtPath:@"employees.tightdb" error:NULL]; + [group write:@"employees.tightdb"]; + + // Load a group from disk (and print contents) + TightdbGroup *fromDisk = [TightdbGroup groupWithFilename:@"employees.tightdb"]; + PeopleTable *diskTable = [fromDisk getTable:@"employees" withClass:[PeopleTable class]]; + + [diskTable addName:@"Anni" Age:54 Hired:YES]; + + NSLog(@"Disktable size: %zu", [diskTable count]); + + for (size_t i = 0; i < [diskTable count]; i++) { + PeopleTable_Cursor *cursor = [diskTable objectAtIndex:i]; + NSLog(@"%zu: %@", i, [cursor Name]); + NSLog(@"%zu: %@", i, cursor.Name); + } + + // Write same group to memory buffer + size_t size; + const char* const data = [group writeToMem:&size]; + + // Load a group from memory (and print contents) + TightdbGroup *fromMem = [TightdbGroup groupWithBuffer:data size:size]; + PeopleTable *memTable = [fromMem getTable:@"employees" withClass:[PeopleTable class]]; + for (size_t i = 0; i < [memTable count]; i++) { + PeopleTable_Cursor *cursor = [memTable objectAtIndex:i]; + NSLog(@"%zu: %@", i, cursor.Name); + } } +#ifdef TIGHTDB_DEBUG + STAssertEquals(0, TightdbViewAllocateCount, @"Zero TightdbView allocated"); + STAssertEquals(0, TightdbCursorAllocateCount, @"Zero TightdbCursor allocated"); + STAssertEquals(0, TightdbGroupAllocateCount, @"Zero TightdbGroup allocated"); + STAssertEquals(0, TightdbSpecAllocateCount, @"Zero TightdbSpec allocated"); + STAssertEquals(0, TightdbTableAllocateCount, @"Zero TightdbTable allocated"); +#endif + } @end From 0712977cc64a68a86d6a2ddb03bb1f1cd7a1149e Mon Sep 17 00:00:00 2001 From: Thomas Andersen Date: Tue, 2 Jul 2013 16:14:05 +0200 Subject: [PATCH 3/6] Finalize allocation checks. --- src/tightdb/objc/group_shared_objc.mm | 10 + src/tightdb/objc/table_objc.mm | 16 + src/tightdb/objc/test/TestHelper.h | 4 + src/tightdb/objc/test/data_type.mm | 23 +- src/tightdb/objc/test/err_handling.mm | 34 +- src/tightdb/objc/test/get_subtable.m | 60 ++-- src/tightdb/objc/test/group.m | 73 +++-- src/tightdb/objc/test/group_misc_2.m | 375 ++++++++++++----------- src/tightdb/objc/test/mixed.m | 314 ++++++++++--------- src/tightdb/objc/test/query.m | 10 +- src/tightdb/objc/test/shared_group.mm | 108 +++---- src/tightdb/objc/test/subtable.m | 39 ++- src/tightdb/objc/test/table.m | 194 ++++++------ src/tightdb/objc/test/table_delete_all.m | 156 +++++----- src/tightdb/objc/test/template.m | 6 + src/tightdb/objc/test/tutorial.m | 18 +- 16 files changed, 753 insertions(+), 687 deletions(-) diff --git a/src/tightdb/objc/group_shared_objc.mm b/src/tightdb/objc/group_shared_objc.mm index 922aef1abd..504dd9598c 100644 --- a/src/tightdb/objc/group_shared_objc.mm +++ b/src/tightdb/objc/group_shared_objc.mm @@ -7,6 +7,10 @@ using namespace std; +#ifdef TIGHTDB_DEBUG +int TightdbGroupSharedAllocateCount = 0; +#endif + @implementation TightdbSharedGroup { @@ -30,11 +34,17 @@ +(TightdbSharedGroup *)groupWithFilename:(NSString *)filename error:(NSError *__ if (shared_group2) { shared_group2->_sharedGroup = shared_group; } +#ifdef TIGHTDB_DEBUG + ++TightdbGroupSharedAllocateCount; +#endif return shared_group2; } -(void)dealloc { +#ifdef TIGHTDB_DEBUG + --TightdbGroupSharedAllocateCount; +#endif delete _sharedGroup; _sharedGroup = 0; } diff --git a/src/tightdb/objc/table_objc.mm b/src/tightdb/objc/table_objc.mm index deaf32d11c..993d557caf 100644 --- a/src/tightdb/objc/table_objc.mm +++ b/src/tightdb/objc/table_objc.mm @@ -1386,6 +1386,10 @@ -(void)verify @end +#ifdef TIGHTDB_DEBUG +int TightdbColumnProxyAllocateCount = 0; +#endif + @implementation TightdbColumnProxy @synthesize table = _table, column = _column; -(id)initWithTable:(TightdbTable *)table column:(size_t)column @@ -1394,6 +1398,9 @@ -(id)initWithTable:(TightdbTable *)table column:(size_t)column if (self) { _table = table; _column = column; +#ifdef TIGHTDB_DEBUG + ++TightdbColumnProxyAllocateCount; +#endif } return self; } @@ -1401,6 +1408,15 @@ -(void)clear { _table = nil; } + +-(void)dealloc +{ +#ifdef TIGHTDB_DEBUG + NSLog(@"TightdbColumnProxy dealloc"); + --TightdbColumnProxyAllocateCount; +#endif +} + @end @implementation TightdbColumnProxy_Bool diff --git a/src/tightdb/objc/test/TestHelper.h b/src/tightdb/objc/test/TestHelper.h index 7f48e0e229..734d84b83f 100644 --- a/src/tightdb/objc/test/TestHelper.h +++ b/src/tightdb/objc/test/TestHelper.h @@ -10,7 +10,9 @@ extern int TightdbQueryAllocateCount; extern int TightdbViewAllocateCount; extern int TightdbCursorAllocateCount; +extern int TightdbColumnProxyAllocateCount; extern int TightdbGroupAllocateCount; +extern int TightdbGroupSharedAllocateCount; extern int TightdbSpecAllocateCount; extern int TightdbTableAllocateCount; #endif @@ -20,7 +22,9 @@ extern int TightdbTableAllocateCount; #define TEST_CHECK_ALLOC STAssertEquals(0, TightdbQueryAllocateCount, @"Zero TightdbQuery allocated"); \ STAssertEquals(0, TightdbViewAllocateCount, @"Zero TightdbView allocated"); \ STAssertEquals(0, TightdbCursorAllocateCount, @"Zero TightdbCursor allocated"); \ +STAssertEquals(0, TightdbColumnProxyAllocateCount, @"Zero TightdbColumnProxy allocated"); \ STAssertEquals(0, TightdbGroupAllocateCount, @"Zero TightdbGroup allocated"); \ +STAssertEquals(0, TightdbGroupSharedAllocateCount, @"Zero TightdbGroupShared allocated"); \ STAssertEquals(0, TightdbSpecAllocateCount, @"Zero TightdbSpec allocated"); \ STAssertEquals(0, TightdbTableAllocateCount, @"Zero TightdbTable allocated"); #else diff --git a/src/tightdb/objc/test/data_type.mm b/src/tightdb/objc/test/data_type.mm index 07dce5d320..2cb2b4bf66 100644 --- a/src/tightdb/objc/test/data_type.mm +++ b/src/tightdb/objc/test/data_type.mm @@ -7,6 +7,8 @@ #import +#import "TestHelper.h" + #import #import @@ -16,15 +18,18 @@ @implementation TestDataType - (void)testDataType { - STAssertEquals((int)tightdb_Bool, (int)tightdb::type_Bool, @"Bool"); - STAssertEquals((int)tightdb_Int, (int)tightdb::type_Int, @"Int"); - STAssertEquals((int)tightdb_Float, (int)tightdb::type_Float, @"Float"); - STAssertEquals((int)tightdb_Double, (int)tightdb::type_Double, @"Double"); - STAssertEquals((int)tightdb_String, (int)tightdb::type_String, @"String"); - STAssertEquals((int)tightdb_Binary, (int)tightdb::type_Binary, @"Binary"); - STAssertEquals((int)tightdb_Date, (int)tightdb::type_Date, @"Date"); - STAssertEquals((int)tightdb_Table, (int)tightdb::type_Table, @"Table"); - STAssertEquals((int)tightdb_Mixed, (int)tightdb::type_Mixed, @"Mixed"); + @autoreleasepool { + STAssertEquals((int)tightdb_Bool, (int)tightdb::type_Bool, @"Bool"); + STAssertEquals((int)tightdb_Int, (int)tightdb::type_Int, @"Int"); + STAssertEquals((int)tightdb_Float, (int)tightdb::type_Float, @"Float"); + STAssertEquals((int)tightdb_Double, (int)tightdb::type_Double, @"Double"); + STAssertEquals((int)tightdb_String, (int)tightdb::type_String, @"String"); + STAssertEquals((int)tightdb_Binary, (int)tightdb::type_Binary, @"Binary"); + STAssertEquals((int)tightdb_Date, (int)tightdb::type_Date, @"Date"); + STAssertEquals((int)tightdb_Table, (int)tightdb::type_Table, @"Table"); + STAssertEquals((int)tightdb_Mixed, (int)tightdb::type_Mixed, @"Mixed"); + } + TEST_CHECK_ALLOC; } @end diff --git a/src/tightdb/objc/test/err_handling.mm b/src/tightdb/objc/test/err_handling.mm index 97f96f25a1..43dab78b11 100644 --- a/src/tightdb/objc/test/err_handling.mm +++ b/src/tightdb/objc/test/err_handling.mm @@ -7,6 +7,8 @@ #import +#import "TestHelper.h" + #import #import #import @@ -38,14 +40,6 @@ TableCol, TestQueryErrSub, MixedCol, Mixed) -#ifdef TIGHTDB_DEBUG -extern int TightdbViewAllocateCount; -extern int TightdbCursorAllocateCount; -extern int TightdbGroupAllocateCount; -extern int TightdbSpecAllocateCount; -extern int TightdbTableAllocateCount; -#endif - @interface MACTestErrHandling: SenTestCase @end @implementation MACTestErrHandling @@ -167,13 +161,7 @@ - (void)testErrHandling NSLog(@"Disktable size: %zu", [diskTable count]); } -#ifdef TIGHTDB_DEBUG - STAssertEquals(0, TightdbViewAllocateCount, @"Zero TightdbView allocated"); - STAssertEquals(0, TightdbCursorAllocateCount, @"Zero TightdbCursor allocated"); - STAssertEquals(0, TightdbGroupAllocateCount, @"Zero TightdbGroup allocated"); - STAssertEquals(0, TightdbSpecAllocateCount, @"Zero TightdbSpec allocated"); - STAssertEquals(0, TightdbTableAllocateCount, @"Zero TightdbTable allocated"); -#endif + TEST_CHECK_ALLOC; } -(void)testErrorInsert @@ -368,13 +356,7 @@ -(void)testErrorInsert [table verify]; #endif } -#ifdef TIGHTDB_DEBUG - STAssertEquals(0, TightdbViewAllocateCount, @"Zero TightdbView allocated"); - STAssertEquals(0, TightdbCursorAllocateCount, @"Zero TightdbCursor allocated"); - STAssertEquals(0, TightdbGroupAllocateCount, @"Zero TightdbGroup allocated"); - STAssertEquals(0, TightdbSpecAllocateCount, @"Zero TightdbSpec allocated"); - STAssertEquals(0, TightdbTableAllocateCount, @"Zero TightdbTable allocated"); -#endif + TEST_CHECK_ALLOC; } @@ -494,13 +476,7 @@ - (void)testQueryErrHandling // [[[table where].MixedCol equal:mixInt1].BoolCol equal:NO]; // [[[table where].MixedCol notEqual:mixInt1].BoolCol equal:NO]; } -#ifdef TIGHTDB_DEBUG - STAssertEquals(0, TightdbViewAllocateCount, @"Zero TightdbView allocated"); - STAssertEquals(0, TightdbCursorAllocateCount, @"Zero TightdbCursor allocated"); - STAssertEquals(0, TightdbGroupAllocateCount, @"Zero TightdbGroup allocated"); - STAssertEquals(0, TightdbSpecAllocateCount, @"Zero TightdbSpec allocated"); - STAssertEquals(0, TightdbTableAllocateCount, @"Zero TightdbTable allocated"); -#endif + TEST_CHECK_ALLOC; } diff --git a/src/tightdb/objc/test/get_subtable.m b/src/tightdb/objc/test/get_subtable.m index b33cf98817..99a65a49e6 100644 --- a/src/tightdb/objc/test/get_subtable.m +++ b/src/tightdb/objc/test/get_subtable.m @@ -7,6 +7,9 @@ #import +#import "TestHelper.h" + + #import #import #import @@ -31,33 +34,36 @@ @implementation MACTestGetSubtable - (void)testGetSubtable { - // Create table with all column types - TightdbTable *table = [[TightdbTable alloc] init]; - TightdbSpec *s = [table getSpec]; - [s addColumn:tightdb_Bool name:@"Outer"]; - [s addColumn:tightdb_Int name:@"Number"]; - TightdbSpec *sub = [s addColumnTable:@"GetSubtable"]; - [sub addColumn:tightdb_Bool name:@"Hired"]; - [sub addColumn:tightdb_Int name:@"Age"]; - [table updateFromSpec]; - - [table insertBool:0 ndx:0 value:NO]; - [table insertInt:1 ndx:0 value:10]; - [table insertSubtable:2 ndx:0]; - [table insertDone]; - - TightdbTable *subtable = [table getSubtable:2 ndx:0]; - [subtable insertBool:0 ndx:0 value:YES]; - [subtable insertInt:1 ndx:0 value:42]; - [subtable insertDone]; - - GetSubtable *testTable = [table getSubtable:2 ndx:0 withClass:[GetSubtable class]]; - GetSubtable_Cursor *cursor = [testTable objectAtIndex:0]; - NSLog(@"Age in subtable: %lld", cursor.Age); - STAssertEquals(cursor.Age, (int64_t)42, @"Sub table row should be 42"); - - STAssertNil([table getSubtable:2 ndx:0 withClass:[WrongNameTable class]], @"should return nil because wrong name"); - STAssertNil([table getSubtable:2 ndx:0 withClass:[WrongTypeTable class]], @"should return nil because wrong type"); + @autoreleasepool { + // Create table with all column types + TightdbTable *table = [[TightdbTable alloc] init]; + TightdbSpec *s = [table getSpec]; + [s addColumn:tightdb_Bool name:@"Outer"]; + [s addColumn:tightdb_Int name:@"Number"]; + TightdbSpec *sub = [s addColumnTable:@"GetSubtable"]; + [sub addColumn:tightdb_Bool name:@"Hired"]; + [sub addColumn:tightdb_Int name:@"Age"]; + [table updateFromSpec]; + + [table insertBool:0 ndx:0 value:NO]; + [table insertInt:1 ndx:0 value:10]; + [table insertSubtable:2 ndx:0]; + [table insertDone]; + + TightdbTable *subtable = [table getSubtable:2 ndx:0]; + [subtable insertBool:0 ndx:0 value:YES]; + [subtable insertInt:1 ndx:0 value:42]; + [subtable insertDone]; + + GetSubtable *testTable = [table getSubtable:2 ndx:0 withClass:[GetSubtable class]]; + GetSubtable_Cursor *cursor = [testTable objectAtIndex:0]; + NSLog(@"Age in subtable: %lld", cursor.Age); + STAssertEquals(cursor.Age, (int64_t)42, @"Sub table row should be 42"); + + STAssertNil([table getSubtable:2 ndx:0 withClass:[WrongNameTable class]], @"should return nil because wrong name"); + STAssertNil([table getSubtable:2 ndx:0 withClass:[WrongTypeTable class]], @"should return nil because wrong type"); + } + TEST_CHECK_ALLOC; } diff --git a/src/tightdb/objc/test/group.m b/src/tightdb/objc/test/group.m index 036097fe03..56dabe896f 100644 --- a/src/tightdb/objc/test/group.m +++ b/src/tightdb/objc/test/group.m @@ -7,6 +7,9 @@ #import +#import "TestHelper.h" + + #import #import @@ -24,7 +27,7 @@ @implementation MACTestGroup - (void)setUp { [super setUp]; - + // _group = [TightdbGroup group]; // NSLog(@"TightdbGroup: %@", _group); // STAssertNotNil(_group, @"Group is nil"); @@ -33,44 +36,48 @@ - (void)setUp - (void)tearDown { // Tear-down code here. - + // [super tearDown]; // _group = nil; } - (void)testGroup { - NSFileManager *fm = [NSFileManager defaultManager]; - - // Create empty group and serialize to disk - TightdbGroup *toDisk = [TightdbGroup group]; - [fm removeItemAtPath:@"table_test.tightdb" error:NULL]; - [toDisk write:@"table_test.tightdb"]; - - // Load the group - TightdbGroup *fromDisk = [TightdbGroup groupWithFilename:@"table_test.tightdb"]; - if (!fromDisk) - STFail(@"From disk not valid"); - - // Create new table in group - TestTableGroup *t = (TestTableGroup *)[fromDisk getTable:@"test" withClass:[TestTableGroup class]]; - - // Verify - NSLog(@"Columns: %zu", [t getColumnCount]); - if ([t getColumnCount] != 2) - STFail(@"Should have been 2 columns"); - if ([t count] != 0) - STFail(@"Should have been empty"); - - // Modify table - [t addFirst:@"Test" Second:YES]; - NSLog(@"Size: %lu", [t count]); - - // Verify - if ([t count] != 1) - STFail(@"Should have been one row"); - - t = nil; + @autoreleasepool { + NSFileManager *fm = [NSFileManager defaultManager]; + + // Create empty group and serialize to disk + TightdbGroup *toDisk = [TightdbGroup group]; + [fm removeItemAtPath:@"table_test.tightdb" error:NULL]; + [toDisk write:@"table_test.tightdb"]; + + // Load the group + TightdbGroup *fromDisk = [TightdbGroup groupWithFilename:@"table_test.tightdb"]; + if (!fromDisk) + STFail(@"From disk not valid"); + + // Create new table in group + TestTableGroup *t = (TestTableGroup *)[fromDisk getTable:@"test" withClass:[TestTableGroup class]]; + + // Verify + NSLog(@"Columns: %zu", [t getColumnCount]); + if ([t getColumnCount] != 2) + STFail(@"Should have been 2 columns"); + if ([t count] != 0) + STFail(@"Should have been empty"); + + // Modify table + [t addFirst:@"Test" Second:YES]; + NSLog(@"Size: %lu", [t count]); + + // Verify + if ([t count] != 1) + STFail(@"Should have been one row"); + + t = nil; + } + TEST_CHECK_ALLOC; + } @end diff --git a/src/tightdb/objc/test/group_misc_2.m b/src/tightdb/objc/test/group_misc_2.m index 5df0f6c4ca..163604bdcd 100644 --- a/src/tightdb/objc/test/group_misc_2.m +++ b/src/tightdb/objc/test/group_misc_2.m @@ -7,6 +7,8 @@ #import +#import "TestHelper.h" + #import #import @@ -40,152 +42,158 @@ @implementation MACTestGroupMisc2 - (void)testGroup_Misc2 { - size_t row; - TightdbGroup *group = [TightdbGroup group]; - NSLog(@"HasTable: %i", [group hasTable:@"employees" withClass:[MyTable class]] ); - // Create new table in group - MyTable *table = [group getTable:@"employees" withClass:[MyTable class]]; - NSLog(@"Table: %@", table); - NSLog(@"HasTable: %i", [group hasTable:@"employees" withClass:[MyTable class]] ); - - // Add some rows - [table addName:@"John" Age:20 Hired:YES Spare:0]; - [table addName:@"Mary" Age:21 Hired:NO Spare:0]; - [table addName:@"Lars" Age:21 Hired:YES Spare:0]; - [table addName:@"Phil" Age:43 Hired:NO Spare:0]; - [table addName:@"Anni" Age:54 Hired:YES Spare:0]; - - NSLog(@"MyTable Size: %lu", [table count]); - - //------------------------------------------------------ - - row = [table.Name find:@"Philip"]; // row = (size_t)-1 - NSLog(@"Philip: %zu", row); - STAssertEquals(row, (size_t)-1,@"Philip should not be there"); - row = [table.Name find:@"Mary"]; - NSLog(@"Mary: %zu", row); - STAssertEquals(row, (size_t)1,@"Mary should have been there"); - - TightdbView *view = [table.Age findAll:21]; - size_t cnt = [view count]; // cnt = 2 - STAssertEquals(cnt, (size_t)2,@"Should be two rows in view"); - - //------------------------------------------------------ - - MyTable2 *table2 = [[MyTable2 alloc] init]; - - // Add some rows - [table2 addHired:YES Age:20]; - [table2 addHired:NO Age:21]; - [table2 addHired:YES Age:22]; - [table2 addHired:NO Age:43]; - [table2 addHired:YES Age:54]; - - // Create query (current employees between 20 and 30 years old) - MyTable2_Query *q = [[[table2 where].Hired equal:YES].Age between:20 to:30]; - - // Get number of matching entries - NSLog(@"Query count: %zu", [[q count] unsignedLongValue]); - STAssertEquals([[q count] unsignedLongValue], (size_t)2,@"Expected 2 rows in query"); - - // Get the average age - currently only a low-level interface! - double avg = [[q.Age avg] doubleValue]; - NSLog(@"Average: %f", avg); - STAssertEquals(avg, 21.0,@"Expected 20.5 average"); - - // Execute the query and return a table (view) - TightdbView *res = [q findAll]; - for (size_t i = 0; i < [res count]; i++) { - // cursor missing. Only low-level interface! - NSLog(@"%zu: is %lld years old",i , [res get:1 ndx:i]); - } - - //------------------------------------------------------ - - NSFileManager *fm = [NSFileManager defaultManager]; - - // Write to disk - [fm removeItemAtPath:@"employees.tightdb" error:NULL]; - [group write:@"employees.tightdb"]; - - // Load a group from disk (and print contents) - TightdbGroup *fromDisk = [TightdbGroup groupWithFilename:@"employees.tightdb"]; - MyTable *diskTable = [fromDisk getTable:@"employees" withClass:[MyTable class]]; - - [diskTable addName:@"Anni" Age:54 Hired:YES Spare:0]; -// [diskTable insertAtIndex:2 Name:@"Thomas" Age:41 Hired:NO Spare:1]; - NSLog(@"Disktable size: %zu", [diskTable count]); - for (size_t i = 0; i < [diskTable count]; i++) { - MyTable_Cursor *cursor = [diskTable objectAtIndex:i]; - NSLog(@"%zu: %@", i, [cursor Name]); - NSLog(@"%zu: %@", i, cursor.Name); - NSLog(@"%zu: %@", i, [diskTable getString:0 ndx:i]); - } - - // Write same group to memory buffer - size_t size; - const char* data = [group writeToMem:&size]; - - // Load a group from memory (and print contents) - TightdbGroup *fromMem = [TightdbGroup groupWithBuffer:data size:size]; - MyTable *memTable = [fromMem getTable:@"employees" withClass:[MyTable class]]; - for (size_t i = 0; i < [memTable count]; i++) { - // ??? cursor - NSLog(@"%zu: %@", i, memTable.Name); + @autoreleasepool { + size_t row; + TightdbGroup *group = [TightdbGroup group]; + NSLog(@"HasTable: %i", [group hasTable:@"employees" withClass:[MyTable class]] ); + // Create new table in group + MyTable *table = [group getTable:@"employees" withClass:[MyTable class]]; + NSLog(@"Table: %@", table); + NSLog(@"HasTable: %i", [group hasTable:@"employees" withClass:[MyTable class]] ); + + // Add some rows + [table addName:@"John" Age:20 Hired:YES Spare:0]; + [table addName:@"Mary" Age:21 Hired:NO Spare:0]; + [table addName:@"Lars" Age:21 Hired:YES Spare:0]; + [table addName:@"Phil" Age:43 Hired:NO Spare:0]; + [table addName:@"Anni" Age:54 Hired:YES Spare:0]; + + NSLog(@"MyTable Size: %lu", [table count]); + + //------------------------------------------------------ + + row = [table.Name find:@"Philip"]; // row = (size_t)-1 + NSLog(@"Philip: %zu", row); + STAssertEquals(row, (size_t)-1,@"Philip should not be there"); + row = [table.Name find:@"Mary"]; + NSLog(@"Mary: %zu", row); + STAssertEquals(row, (size_t)1,@"Mary should have been there"); + + TightdbView *view = [table.Age findAll:21]; + size_t cnt = [view count]; // cnt = 2 + STAssertEquals(cnt, (size_t)2,@"Should be two rows in view"); + + //------------------------------------------------------ + + MyTable2 *table2 = [[MyTable2 alloc] init]; + + // Add some rows + [table2 addHired:YES Age:20]; + [table2 addHired:NO Age:21]; + [table2 addHired:YES Age:22]; + [table2 addHired:NO Age:43]; + [table2 addHired:YES Age:54]; + + // Create query (current employees between 20 and 30 years old) + MyTable2_Query *q = [[[table2 where].Hired equal:YES].Age between:20 to:30]; + + // Get number of matching entries + NSLog(@"Query count: %zu", [[q count] unsignedLongValue]); + STAssertEquals([[q count] unsignedLongValue], (size_t)2,@"Expected 2 rows in query"); + + // Get the average age - currently only a low-level interface! + double avg = [[q.Age avg] doubleValue]; + NSLog(@"Average: %f", avg); + STAssertEquals(avg, 21.0,@"Expected 20.5 average"); + + // Execute the query and return a table (view) + TightdbView *res = [q findAll]; + for (size_t i = 0; i < [res count]; i++) { + // cursor missing. Only low-level interface! + NSLog(@"%zu: is %lld years old",i , [res get:1 ndx:i]); + } + + //------------------------------------------------------ + + NSFileManager *fm = [NSFileManager defaultManager]; + + // Write to disk + [fm removeItemAtPath:@"employees.tightdb" error:NULL]; + [group write:@"employees.tightdb"]; + + // Load a group from disk (and print contents) + TightdbGroup *fromDisk = [TightdbGroup groupWithFilename:@"employees.tightdb"]; + MyTable *diskTable = [fromDisk getTable:@"employees" withClass:[MyTable class]]; + + [diskTable addName:@"Anni" Age:54 Hired:YES Spare:0]; + // [diskTable insertAtIndex:2 Name:@"Thomas" Age:41 Hired:NO Spare:1]; + NSLog(@"Disktable size: %zu", [diskTable count]); + for (size_t i = 0; i < [diskTable count]; i++) { + MyTable_Cursor *cursor = [diskTable objectAtIndex:i]; + NSLog(@"%zu: %@", i, [cursor Name]); + NSLog(@"%zu: %@", i, cursor.Name); + NSLog(@"%zu: %@", i, [diskTable getString:0 ndx:i]); + } + + // Write same group to memory buffer + size_t size; + const char* data = [group writeToMem:&size]; + + // Load a group from memory (and print contents) + TightdbGroup *fromMem = [TightdbGroup groupWithBuffer:data size:size]; + MyTable *memTable = [fromMem getTable:@"employees" withClass:[MyTable class]]; + for (size_t i = 0; i < [memTable count]; i++) { + // ??? cursor + NSLog(@"%zu: %@", i, memTable.Name); + } } + TEST_CHECK_ALLOC; } - (void)testQuery { - TightdbGroup *group = [TightdbGroup group]; - QueryTable *table = [group getTable:@"Query table" withClass:[QueryTable class]]; - - // Add some rows - [table addFirst:2 Second:@"a"]; - [table addFirst:4 Second:@"a"]; - [table addFirst:5 Second:@"b"]; - [table addFirst:8 Second:@"The quick brown fox"]; - - { - QueryTable_Query *q = [[table where].First between:3 to:7]; // Between - STAssertEquals((size_t)2, [[q count] unsignedLongValue], @"count != 2"); -// STAssertEquals(9, [q.First sum]); // Sum - STAssertEquals(4.5, [[q.First avg] doubleValue], @"Avg!=4.5"); // Average -// STAssertEquals(4, [q.First min]); // Minimum -// STAssertEquals(5, [q.First max]); // Maximum - } - { - QueryTable_Query *q = [[table where].Second contains:@"quick" caseSensitive:NO]; // String contains - STAssertEquals((size_t)1, [[q count] unsignedLongValue], @"count != 1"); - } - { - QueryTable_Query *q = [[table where].Second beginsWith:@"The" caseSensitive:NO]; // String prefix - STAssertEquals((size_t)1, [[q count] unsignedLongValue], @"count != 1"); - } - { - QueryTable_Query *q = [[table where].Second endsWith:@"The" caseSensitive:NO]; // String suffix - STAssertEquals((size_t)0, [[q count] unsignedLongValue], @"count != 1"); - } - { - QueryTable_Query *q = [[[table where].Second notEqual:@"a" caseSensitive:NO].Second notEqual:@"b" caseSensitive:NO]; // And - STAssertEquals((size_t)1, [[q count] unsignedLongValue], @"count != 1"); - } - { - QueryTable_Query *q = [[[[table where].Second notEqual:@"a" caseSensitive:NO] or].Second notEqual:@"b" caseSensitive:NO]; // Or - STAssertEquals((size_t)4, [[q count] unsignedLongValue], @"count != 1"); - } - { - QueryTable_Query *q = [[[[[[[table where].Second equal:@"a" caseSensitive:NO] group].First less:3] or].First greater:5] endgroup]; // Parentheses - STAssertEquals((size_t)1, [[q count] unsignedLongValue], @"count != 1"); - } - { - QueryTable_Query *q = [[[[[table where].Second equal:@"a" caseSensitive:NO].First less:3] or].First greater:5]; // No parenthesis - STAssertEquals((size_t)2, [[q count] unsignedLongValue], @"count != 2"); - TightdbView *tv = [q findAll]; - STAssertEquals((size_t)2, [tv count], @"count != 2"); - STAssertEquals((int64_t)8, [tv get:0 ndx:1], @"First != 8"); + @autoreleasepool { + TightdbGroup *group = [TightdbGroup group]; + QueryTable *table = [group getTable:@"Query table" withClass:[QueryTable class]]; + + // Add some rows + [table addFirst:2 Second:@"a"]; + [table addFirst:4 Second:@"a"]; + [table addFirst:5 Second:@"b"]; + [table addFirst:8 Second:@"The quick brown fox"]; + + { + QueryTable_Query *q = [[table where].First between:3 to:7]; // Between + STAssertEquals((size_t)2, [[q count] unsignedLongValue], @"count != 2"); + // STAssertEquals(9, [q.First sum]); // Sum + STAssertEquals(4.5, [[q.First avg] doubleValue], @"Avg!=4.5"); // Average + // STAssertEquals(4, [q.First min]); // Minimum + // STAssertEquals(5, [q.First max]); // Maximum + } + { + QueryTable_Query *q = [[table where].Second contains:@"quick" caseSensitive:NO]; // String contains + STAssertEquals((size_t)1, [[q count] unsignedLongValue], @"count != 1"); + } + { + QueryTable_Query *q = [[table where].Second beginsWith:@"The" caseSensitive:NO]; // String prefix + STAssertEquals((size_t)1, [[q count] unsignedLongValue], @"count != 1"); + } + { + QueryTable_Query *q = [[table where].Second endsWith:@"The" caseSensitive:NO]; // String suffix + STAssertEquals((size_t)0, [[q count] unsignedLongValue], @"count != 1"); + } + { + QueryTable_Query *q = [[[table where].Second notEqual:@"a" caseSensitive:NO].Second notEqual:@"b" caseSensitive:NO]; // And + STAssertEquals((size_t)1, [[q count] unsignedLongValue], @"count != 1"); + } + { + QueryTable_Query *q = [[[[table where].Second notEqual:@"a" caseSensitive:NO] or].Second notEqual:@"b" caseSensitive:NO]; // Or + STAssertEquals((size_t)4, [[q count] unsignedLongValue], @"count != 1"); + } + { + QueryTable_Query *q = [[[[[[[table where].Second equal:@"a" caseSensitive:NO] group].First less:3] or].First greater:5] endgroup]; // Parentheses + STAssertEquals((size_t)1, [[q count] unsignedLongValue], @"count != 1"); + } + { + QueryTable_Query *q = [[[[[table where].Second equal:@"a" caseSensitive:NO].First less:3] or].First greater:5]; // No parenthesis + STAssertEquals((size_t)2, [[q count] unsignedLongValue], @"count != 2"); + TightdbView *tv = [q findAll]; + STAssertEquals((size_t)2, [tv count], @"count != 2"); + STAssertEquals((int64_t)8, [tv get:0 ndx:1], @"First != 8"); + } } + TEST_CHECK_ALLOC; } /* @@ -195,52 +203,55 @@ - (void)testQuery */ - (void)testSubtables { - TightdbGroup *group = [TightdbGroup group]; - TightdbTable *table = [group getTable:@"table" withClass:[TightdbTable class]]; - - // Specify the table schema - { - TightdbSpec *s = [table getSpec]; - [s addColumn:tightdb_Int name:@"int"]; + @autoreleasepool { + TightdbGroup *group = [TightdbGroup group]; + TightdbTable *table = [group getTable:@"table" withClass:[TightdbTable class]]; + + // Specify the table schema { - TightdbSpec *sub = [s addColumnTable:@"tab"]; - [sub addColumn:tightdb_Int name:@"int"]; + TightdbSpec *s = [table getSpec]; + [s addColumn:tightdb_Int name:@"int"]; + { + TightdbSpec *sub = [s addColumnTable:@"tab"]; + [sub addColumn:tightdb_Int name:@"int"]; + } + [s addColumn:tightdb_Mixed name:@"mix"]; + [table updateFromSpec]; } - [s addColumn:tightdb_Mixed name:@"mix"]; - [table updateFromSpec]; - } - - int COL_TABLE_INT = 0; - int COL_TABLE_TAB = 1; - int COL_TABLE_MIX = 2; - int COL_SUBTABLE_INT = 0; - - // Add a row to the top level table - [table addRow]; - [table set:COL_TABLE_INT ndx:0 value:700]; - - // Add two rows to the subtable - TightdbTable *subtable = [table getSubtable:COL_TABLE_TAB ndx:0]; - [subtable addRow]; - [subtable set:COL_SUBTABLE_INT ndx:0 value:800]; - [subtable addRow]; - [subtable set:COL_SUBTABLE_INT ndx:1 value:801]; - - // Make the mixed values column contain another subtable - [table setMixed:COL_TABLE_MIX ndx:0 value: [TightdbMixed mixedWithTable:nil]]; - -/* Fails!!! - // Specify its schema - OCTopLevelTable *subtable2 = [table getTopLevelTable:COL_TABLE_MIX ndx:0]; - { - TightdbSpec *s = [subtable2 getSpec]; - [s addColumn:tightdb_Int name:@"int"]; - [subtable2 updateFromSpec:[s getRef]]; + + int COL_TABLE_INT = 0; + int COL_TABLE_TAB = 1; + int COL_TABLE_MIX = 2; + int COL_SUBTABLE_INT = 0; + + // Add a row to the top level table + [table addRow]; + [table set:COL_TABLE_INT ndx:0 value:700]; + + // Add two rows to the subtable + TightdbTable *subtable = [table getSubtable:COL_TABLE_TAB ndx:0]; + [subtable addRow]; + [subtable set:COL_SUBTABLE_INT ndx:0 value:800]; + [subtable addRow]; + [subtable set:COL_SUBTABLE_INT ndx:1 value:801]; + + // Make the mixed values column contain another subtable + [table setMixed:COL_TABLE_MIX ndx:0 value: [TightdbMixed mixedWithTable:nil]]; + + /* Fails!!! + // Specify its schema + OCTopLevelTable *subtable2 = [table getTopLevelTable:COL_TABLE_MIX ndx:0]; + { + TightdbSpec *s = [subtable2 getSpec]; + [s addColumn:tightdb_Int name:@"int"]; + [subtable2 updateFromSpec:[s getRef]]; + } + // Add a row to it + [subtable2 addRow]; + [subtable2 set:COL_SUBTABLE_INT ndx:0 value:900]; + */ } - // Add a row to it - [subtable2 addRow]; - [subtable2 set:COL_SUBTABLE_INT ndx:0 value:900]; -*/ + TEST_CHECK_ALLOC; } @end diff --git a/src/tightdb/objc/test/mixed.m b/src/tightdb/objc/test/mixed.m index c38d2c7bd6..481f4218ff 100644 --- a/src/tightdb/objc/test/mixed.m +++ b/src/tightdb/objc/test/mixed.m @@ -10,6 +10,8 @@ #import +#import "TestHelper.h" + #import #import #import @@ -30,166 +32,172 @@ @implementation MACTestMixed - (void)testMixedEqual { - time_t nowTime = [[NSDate date] timeIntervalSince1970]; - - TightdbMixed *mixedBool1 = [TightdbMixed mixedWithBool:YES]; - TightdbMixed *mixedBool2 = [TightdbMixed mixedWithBool:NO]; - TightdbMixed *mixedBool3 = [TightdbMixed mixedWithBool:NO]; - STAssertEquals([mixedBool1 isEqual:mixedBool1], YES, @"Same mixed should be equal (1)"); - STAssertEquals([mixedBool2 isEqual:mixedBool2], YES, @"Same mixed should be equal (2)"); - STAssertEquals([mixedBool2 isEqual:mixedBool3], YES, @"Mixed with same bools should be equal"); - STAssertEquals([mixedBool1 isEqual:mixedBool2], NO, @"Mixed with different bools should be different"); - - TightdbMixed *mixedInt1 = [TightdbMixed mixedWithInt64:10001]; - TightdbMixed *mixedInt2 = [TightdbMixed mixedWithInt64:20002]; - TightdbMixed *mixedInt3 = [TightdbMixed mixedWithInt64:20002]; - STAssertEquals([mixedInt1 isEqual:mixedInt1], YES, @"Same mixed should be equal (3)"); - STAssertEquals([mixedInt2 isEqual:mixedInt2], YES, @"Same mixed should be equal (4)"); - STAssertEquals([mixedInt2 isEqual:mixedInt3], YES, @"Mixed with same ints should be equal"); - STAssertEquals([mixedInt1 isEqual:mixedInt2], NO, @"Mixed with different ints should be different"); - - TightdbMixed *mixedString1 = [TightdbMixed mixedWithString:@"Hello"]; - TightdbMixed *mixedString2 = [TightdbMixed mixedWithString:@"Goodbye"]; - TightdbMixed *mixedString3 = [TightdbMixed mixedWithString:@"Goodbye"]; - STAssertEquals([mixedString1 isEqual:mixedString1], YES, @"Same mixed should be equal (5)"); - STAssertEquals([mixedString2 isEqual:mixedString2], YES, @"Same mixed should be equal (6)"); - STAssertEquals([mixedString2 isEqual:mixedString3], YES, @"Mixed with same strings should be equal"); - STAssertEquals([mixedString1 isEqual:mixedString2], NO, @"Mixed with different strings should be different"); - - const char* str1 = "Hello"; - const char* str2 = "Goodbye"; - TightdbMixed *mixedBinary1 = [TightdbMixed mixedWithBinary:str1 size:strlen(str1)]; - TightdbMixed *mixedBinary2 = [TightdbMixed mixedWithBinary:str2 size:strlen(str2)]; - TightdbMixed *mixedBinary3 = [TightdbMixed mixedWithBinary:str2 size:strlen(str2)]; - STAssertEquals([mixedBinary1 isEqual:mixedBinary1], YES, @"Same mixed should be equal (7)"); - STAssertEquals([mixedBinary2 isEqual:mixedBinary2], YES, @"Same mixed should be equal (8)"); - STAssertEquals([mixedBinary2 isEqual:mixedBinary3], YES, @"Mixed with same binary data should be equal"); - STAssertEquals([mixedBinary1 isEqual:mixedBinary2], NO, @"Mixed with different binary data should be different"); - - TightdbMixed *mixedDate1 = [TightdbMixed mixedWithDate:nowTime]; - TightdbMixed *mixedDate2 = [TightdbMixed mixedWithDate:nowTime+1]; - TightdbMixed *mixedDate3 = [TightdbMixed mixedWithDate:nowTime+1]; - STAssertEquals([mixedDate1 isEqual:mixedDate1], YES, @"Same mixed should be equal (9)"); - STAssertEquals([mixedDate2 isEqual:mixedDate2], YES, @"Same mixed should be equal (10)"); - STAssertEquals([mixedDate2 isEqual:mixedDate3], YES, @"Mixed with same timestamps should be equal"); - STAssertEquals([mixedDate1 isEqual:mixedDate2], NO, @"Mixed with different timestamps should be different"); - - MixedTable *table1 = [[MixedTable alloc] init]; - SubMixedTable *table2 = [[SubMixedTable alloc] init]; - SubMixedTable *table3 = [[SubMixedTable alloc] init]; - [table1 addHired:YES Other:mixedBool1 Age:54]; - [table2 addHired:YES Age:54]; - [table3 addHired:YES Age:54]; - TightdbMixed *mixedTable1 = [TightdbMixed mixedWithTable:table1]; - TightdbMixed *mixedTable2 = [TightdbMixed mixedWithTable:table2]; - TightdbMixed *mixedTable3 = [TightdbMixed mixedWithTable:table3]; - STAssertEquals([mixedTable1 isEqual:mixedTable1], YES, @"Same mixed should be equal (11)"); - STAssertEquals([mixedTable2 isEqual:mixedTable2], YES, @"Same mixed should be equal (12)"); - STAssertEquals([mixedTable2 isEqual:mixedTable3], YES, @"Mixed with same tables should be equal"); - STAssertEquals([mixedTable1 isEqual:mixedTable2], NO, @"Mixed with different tables should be different"); - - - STAssertEquals([mixedBool1 isEqual:mixedInt1], NO, @"Mixed with different types should be different (1)"); - STAssertEquals([mixedBool1 isEqual:mixedString1], NO, @"Mixed with different types should be different (2)"); - STAssertEquals([mixedBool1 isEqual:mixedBinary1], NO, @"Mixed with different types should be different (3)"); - STAssertEquals([mixedBool1 isEqual:mixedDate1], NO, @"Mixed with different types should be different (4)"); - STAssertEquals([mixedBool1 isEqual:mixedTable1], NO, @"Mixed with different types should be different (5)"); - - STAssertEquals([mixedInt1 isEqual:mixedBool1], NO, @"Mixed with different types should be different (6)"); - STAssertEquals([mixedInt1 isEqual:mixedString1], NO, @"Mixed with different types should be different (7)"); - STAssertEquals([mixedInt1 isEqual:mixedBinary1], NO, @"Mixed with different types should be different (8)"); - STAssertEquals([mixedInt1 isEqual:mixedDate1], NO, @"Mixed with different types should be different (9)"); - STAssertEquals([mixedInt1 isEqual:mixedTable1], NO, @"Mixed with different types should be different (10)"); - - STAssertEquals([mixedString1 isEqual:mixedBool1], NO, @"Mixed with different types should be different (11)"); - STAssertEquals([mixedString1 isEqual:mixedInt1], NO, @"Mixed with different types should be different (12)"); - STAssertEquals([mixedString1 isEqual:mixedBinary1], NO, @"Mixed with different types should be different (13)"); - STAssertEquals([mixedString1 isEqual:mixedDate1], NO, @"Mixed with different types should be different (14)"); - STAssertEquals([mixedString1 isEqual:mixedTable1], NO, @"Mixed with different types should be different (15)"); - - STAssertEquals([mixedBinary1 isEqual:mixedBool1], NO, @"Mixed with different types should be different (16)"); - STAssertEquals([mixedBinary1 isEqual:mixedInt1], NO, @"Mixed with different types should be different (17)"); - STAssertEquals([mixedBinary1 isEqual:mixedString1], NO, @"Mixed with different types should be different (18)"); - STAssertEquals([mixedBinary1 isEqual:mixedDate1], NO, @"Mixed with different types should be different (19)"); - STAssertEquals([mixedBinary1 isEqual:mixedTable1], NO, @"Mixed with different types should be different (20)"); - - STAssertEquals([mixedDate1 isEqual:mixedBool1], NO, @"Mixed with different types should be different (21)"); - STAssertEquals([mixedDate1 isEqual:mixedInt1], NO, @"Mixed with different types should be different (22)"); - STAssertEquals([mixedDate1 isEqual:mixedString1], NO, @"Mixed with different types should be different (23)"); - STAssertEquals([mixedDate1 isEqual:mixedBinary1], NO, @"Mixed with different types should be different (24)"); - STAssertEquals([mixedDate1 isEqual:mixedTable1], NO, @"Mixed with different types should be different (25)"); - - STAssertEquals([mixedTable1 isEqual:mixedBool1], NO, @"Mixed with different types should be different (26)"); - STAssertEquals([mixedTable1 isEqual:mixedInt1], NO, @"Mixed with different types should be different (27)"); - STAssertEquals([mixedTable1 isEqual:mixedString1], NO, @"Mixed with different types should be different (28)"); - STAssertEquals([mixedTable1 isEqual:mixedBinary1], NO, @"Mixed with different types should be different (29)"); - STAssertEquals([mixedTable1 isEqual:mixedDate1], NO, @"Mixed with different types should be different (30)"); + @autoreleasepool { + time_t nowTime = [[NSDate date] timeIntervalSince1970]; + + TightdbMixed *mixedBool1 = [TightdbMixed mixedWithBool:YES]; + TightdbMixed *mixedBool2 = [TightdbMixed mixedWithBool:NO]; + TightdbMixed *mixedBool3 = [TightdbMixed mixedWithBool:NO]; + STAssertEquals([mixedBool1 isEqual:mixedBool1], YES, @"Same mixed should be equal (1)"); + STAssertEquals([mixedBool2 isEqual:mixedBool2], YES, @"Same mixed should be equal (2)"); + STAssertEquals([mixedBool2 isEqual:mixedBool3], YES, @"Mixed with same bools should be equal"); + STAssertEquals([mixedBool1 isEqual:mixedBool2], NO, @"Mixed with different bools should be different"); + + TightdbMixed *mixedInt1 = [TightdbMixed mixedWithInt64:10001]; + TightdbMixed *mixedInt2 = [TightdbMixed mixedWithInt64:20002]; + TightdbMixed *mixedInt3 = [TightdbMixed mixedWithInt64:20002]; + STAssertEquals([mixedInt1 isEqual:mixedInt1], YES, @"Same mixed should be equal (3)"); + STAssertEquals([mixedInt2 isEqual:mixedInt2], YES, @"Same mixed should be equal (4)"); + STAssertEquals([mixedInt2 isEqual:mixedInt3], YES, @"Mixed with same ints should be equal"); + STAssertEquals([mixedInt1 isEqual:mixedInt2], NO, @"Mixed with different ints should be different"); + + TightdbMixed *mixedString1 = [TightdbMixed mixedWithString:@"Hello"]; + TightdbMixed *mixedString2 = [TightdbMixed mixedWithString:@"Goodbye"]; + TightdbMixed *mixedString3 = [TightdbMixed mixedWithString:@"Goodbye"]; + STAssertEquals([mixedString1 isEqual:mixedString1], YES, @"Same mixed should be equal (5)"); + STAssertEquals([mixedString2 isEqual:mixedString2], YES, @"Same mixed should be equal (6)"); + STAssertEquals([mixedString2 isEqual:mixedString3], YES, @"Mixed with same strings should be equal"); + STAssertEquals([mixedString1 isEqual:mixedString2], NO, @"Mixed with different strings should be different"); + + const char* str1 = "Hello"; + const char* str2 = "Goodbye"; + TightdbMixed *mixedBinary1 = [TightdbMixed mixedWithBinary:str1 size:strlen(str1)]; + TightdbMixed *mixedBinary2 = [TightdbMixed mixedWithBinary:str2 size:strlen(str2)]; + TightdbMixed *mixedBinary3 = [TightdbMixed mixedWithBinary:str2 size:strlen(str2)]; + STAssertEquals([mixedBinary1 isEqual:mixedBinary1], YES, @"Same mixed should be equal (7)"); + STAssertEquals([mixedBinary2 isEqual:mixedBinary2], YES, @"Same mixed should be equal (8)"); + STAssertEquals([mixedBinary2 isEqual:mixedBinary3], YES, @"Mixed with same binary data should be equal"); + STAssertEquals([mixedBinary1 isEqual:mixedBinary2], NO, @"Mixed with different binary data should be different"); + + TightdbMixed *mixedDate1 = [TightdbMixed mixedWithDate:nowTime]; + TightdbMixed *mixedDate2 = [TightdbMixed mixedWithDate:nowTime+1]; + TightdbMixed *mixedDate3 = [TightdbMixed mixedWithDate:nowTime+1]; + STAssertEquals([mixedDate1 isEqual:mixedDate1], YES, @"Same mixed should be equal (9)"); + STAssertEquals([mixedDate2 isEqual:mixedDate2], YES, @"Same mixed should be equal (10)"); + STAssertEquals([mixedDate2 isEqual:mixedDate3], YES, @"Mixed with same timestamps should be equal"); + STAssertEquals([mixedDate1 isEqual:mixedDate2], NO, @"Mixed with different timestamps should be different"); + + MixedTable *table1 = [[MixedTable alloc] init]; + SubMixedTable *table2 = [[SubMixedTable alloc] init]; + SubMixedTable *table3 = [[SubMixedTable alloc] init]; + [table1 addHired:YES Other:mixedBool1 Age:54]; + [table2 addHired:YES Age:54]; + [table3 addHired:YES Age:54]; + TightdbMixed *mixedTable1 = [TightdbMixed mixedWithTable:table1]; + TightdbMixed *mixedTable2 = [TightdbMixed mixedWithTable:table2]; + TightdbMixed *mixedTable3 = [TightdbMixed mixedWithTable:table3]; + STAssertEquals([mixedTable1 isEqual:mixedTable1], YES, @"Same mixed should be equal (11)"); + STAssertEquals([mixedTable2 isEqual:mixedTable2], YES, @"Same mixed should be equal (12)"); + STAssertEquals([mixedTable2 isEqual:mixedTable3], YES, @"Mixed with same tables should be equal"); + STAssertEquals([mixedTable1 isEqual:mixedTable2], NO, @"Mixed with different tables should be different"); + + + STAssertEquals([mixedBool1 isEqual:mixedInt1], NO, @"Mixed with different types should be different (1)"); + STAssertEquals([mixedBool1 isEqual:mixedString1], NO, @"Mixed with different types should be different (2)"); + STAssertEquals([mixedBool1 isEqual:mixedBinary1], NO, @"Mixed with different types should be different (3)"); + STAssertEquals([mixedBool1 isEqual:mixedDate1], NO, @"Mixed with different types should be different (4)"); + STAssertEquals([mixedBool1 isEqual:mixedTable1], NO, @"Mixed with different types should be different (5)"); + + STAssertEquals([mixedInt1 isEqual:mixedBool1], NO, @"Mixed with different types should be different (6)"); + STAssertEquals([mixedInt1 isEqual:mixedString1], NO, @"Mixed with different types should be different (7)"); + STAssertEquals([mixedInt1 isEqual:mixedBinary1], NO, @"Mixed with different types should be different (8)"); + STAssertEquals([mixedInt1 isEqual:mixedDate1], NO, @"Mixed with different types should be different (9)"); + STAssertEquals([mixedInt1 isEqual:mixedTable1], NO, @"Mixed with different types should be different (10)"); + + STAssertEquals([mixedString1 isEqual:mixedBool1], NO, @"Mixed with different types should be different (11)"); + STAssertEquals([mixedString1 isEqual:mixedInt1], NO, @"Mixed with different types should be different (12)"); + STAssertEquals([mixedString1 isEqual:mixedBinary1], NO, @"Mixed with different types should be different (13)"); + STAssertEquals([mixedString1 isEqual:mixedDate1], NO, @"Mixed with different types should be different (14)"); + STAssertEquals([mixedString1 isEqual:mixedTable1], NO, @"Mixed with different types should be different (15)"); + + STAssertEquals([mixedBinary1 isEqual:mixedBool1], NO, @"Mixed with different types should be different (16)"); + STAssertEquals([mixedBinary1 isEqual:mixedInt1], NO, @"Mixed with different types should be different (17)"); + STAssertEquals([mixedBinary1 isEqual:mixedString1], NO, @"Mixed with different types should be different (18)"); + STAssertEquals([mixedBinary1 isEqual:mixedDate1], NO, @"Mixed with different types should be different (19)"); + STAssertEquals([mixedBinary1 isEqual:mixedTable1], NO, @"Mixed with different types should be different (20)"); + + STAssertEquals([mixedDate1 isEqual:mixedBool1], NO, @"Mixed with different types should be different (21)"); + STAssertEquals([mixedDate1 isEqual:mixedInt1], NO, @"Mixed with different types should be different (22)"); + STAssertEquals([mixedDate1 isEqual:mixedString1], NO, @"Mixed with different types should be different (23)"); + STAssertEquals([mixedDate1 isEqual:mixedBinary1], NO, @"Mixed with different types should be different (24)"); + STAssertEquals([mixedDate1 isEqual:mixedTable1], NO, @"Mixed with different types should be different (25)"); + + STAssertEquals([mixedTable1 isEqual:mixedBool1], NO, @"Mixed with different types should be different (26)"); + STAssertEquals([mixedTable1 isEqual:mixedInt1], NO, @"Mixed with different types should be different (27)"); + STAssertEquals([mixedTable1 isEqual:mixedString1], NO, @"Mixed with different types should be different (28)"); + STAssertEquals([mixedTable1 isEqual:mixedBinary1], NO, @"Mixed with different types should be different (29)"); + STAssertEquals([mixedTable1 isEqual:mixedDate1], NO, @"Mixed with different types should be different (30)"); + } + TEST_CHECK_ALLOC; } - (void)testMixed { - time_t nowTime = [[NSDate date] timeIntervalSince1970]; - - SubMixedTable *tableSub = [[SubMixedTable alloc] init]; - - // Add some rows - [tableSub addHired:YES Age:20]; - [tableSub addHired:NO Age:21]; - [tableSub addHired:YES Age:22]; - [tableSub addHired:NO Age:43]; - [tableSub addHired:YES Age:54]; - - TightdbGroup *group = [TightdbGroup group]; - // Create new table in group - MixedTable *table = [group getTable:@"MixedValues" withClass:[MixedTable class]]; - NSLog(@"Table: %@", table); - // Add some rows - TightdbMixed *mixedTable = [TightdbMixed mixedWithTable:tableSub]; - [table addHired:YES Other:[TightdbMixed mixedWithString:@"Jens"] Age:50]; - [table addHired:YES Other:[TightdbMixed mixedWithString:@"Aage"] Age:52]; - [table addHired:YES Other:[TightdbMixed mixedWithString:@"Joergen"] Age:53]; - [table addHired:YES Other:[TightdbMixed mixedWithString:@"Dave"] Age:54]; - [table addHired:YES Other:mixedTable Age:54]; - TightdbMixed *mixedDate = [TightdbMixed mixedWithDate:nowTime]; - [table addHired:YES Other:mixedDate Age:54]; - - // Test isequal - TightdbMixed *mixedDate2 = [TightdbMixed mixedWithDate:nowTime]; - TightdbMixed *mixedDate3 = [TightdbMixed mixedWithDate:nowTime+1]; - STAssertEquals([mixedDate isEqual:mixedDate2], YES,@"Mixed dates should be equal"); - STAssertEquals([mixedDate isEqual:mixedDate3], NO,@"Mixed dates should not be equal"); - - // Test cast and isClass - TightdbTable *unknownTable = [mixedTable getTable]; - NSLog(@"Is SubMixedTable type: %i", [unknownTable isClass:[SubMixedTable class]]); - STAssertEquals([unknownTable isClass:[SubMixedTable class]], YES,@"Unknown table should be of type SubMixedTable"); - tableSub = [unknownTable castClass:[SubMixedTable class]]; - NSLog(@"TableSub Size: %lu", [tableSub count]); - STAssertEquals([tableSub count], (size_t)5,@"Subtable should have 5 rows"); - NSLog(@"Count int: %lu", [table countInt:2 target:50]); - NSLog(@"Max: %lld", [table maxInt:2]); - NSLog(@"Avg: %.2f", [table avgInt:2]); - - NSLog(@"MyTable Size: %lu", [table count]); - int sumType = 0; - for (size_t i = 0; i < [table count]; i++) { - MixedTable_Cursor *cursor = [table objectAtIndex:i]; - NSLog(@"%zu: %@", i, cursor.Other); - NSLog(@"Type: %i", [cursor.Other getType] ); - sumType += [cursor.Other getType]; - if ([cursor.Other getType] == tightdb_String) - NSLog(@"StringMixed: %@", [cursor.Other getString]); - else if ([cursor.Other getType] == tightdb_Date) { - NSLog(@"DateMixed: %ld", [cursor.Other getDate]); - STAssertEquals(nowTime, [cursor.Other getDate],@"Date should match what went in"); - } - else if ([cursor.Other getType] == tightdb_Table) { - NSLog(@"TableMixed: %@", [cursor.Other getTable]); + @autoreleasepool { + time_t nowTime = [[NSDate date] timeIntervalSince1970]; + + SubMixedTable *tableSub = [[SubMixedTable alloc] init]; + + // Add some rows + [tableSub addHired:YES Age:20]; + [tableSub addHired:NO Age:21]; + [tableSub addHired:YES Age:22]; + [tableSub addHired:NO Age:43]; + [tableSub addHired:YES Age:54]; + + TightdbGroup *group = [TightdbGroup group]; + // Create new table in group + MixedTable *table = [group getTable:@"MixedValues" withClass:[MixedTable class]]; + NSLog(@"Table: %@", table); + // Add some rows + TightdbMixed *mixedTable = [TightdbMixed mixedWithTable:tableSub]; + [table addHired:YES Other:[TightdbMixed mixedWithString:@"Jens"] Age:50]; + [table addHired:YES Other:[TightdbMixed mixedWithString:@"Aage"] Age:52]; + [table addHired:YES Other:[TightdbMixed mixedWithString:@"Joergen"] Age:53]; + [table addHired:YES Other:[TightdbMixed mixedWithString:@"Dave"] Age:54]; + [table addHired:YES Other:mixedTable Age:54]; + TightdbMixed *mixedDate = [TightdbMixed mixedWithDate:nowTime]; + [table addHired:YES Other:mixedDate Age:54]; + + // Test isequal + TightdbMixed *mixedDate2 = [TightdbMixed mixedWithDate:nowTime]; + TightdbMixed *mixedDate3 = [TightdbMixed mixedWithDate:nowTime+1]; + STAssertEquals([mixedDate isEqual:mixedDate2], YES,@"Mixed dates should be equal"); + STAssertEquals([mixedDate isEqual:mixedDate3], NO,@"Mixed dates should not be equal"); + + // Test cast and isClass + TightdbTable *unknownTable = [mixedTable getTable]; + NSLog(@"Is SubMixedTable type: %i", [unknownTable isClass:[SubMixedTable class]]); + STAssertEquals([unknownTable isClass:[SubMixedTable class]], YES,@"Unknown table should be of type SubMixedTable"); + tableSub = [unknownTable castClass:[SubMixedTable class]]; + NSLog(@"TableSub Size: %lu", [tableSub count]); + STAssertEquals([tableSub count], (size_t)5,@"Subtable should have 5 rows"); + NSLog(@"Count int: %lu", [table countInt:2 target:50]); + NSLog(@"Max: %lld", [table maxInt:2]); + NSLog(@"Avg: %.2f", [table avgInt:2]); + + NSLog(@"MyTable Size: %lu", [table count]); + int sumType = 0; + for (size_t i = 0; i < [table count]; i++) { + MixedTable_Cursor *cursor = [table objectAtIndex:i]; + NSLog(@"%zu: %@", i, cursor.Other); + NSLog(@"Type: %i", [cursor.Other getType] ); + sumType += [cursor.Other getType]; + if ([cursor.Other getType] == tightdb_String) + NSLog(@"StringMixed: %@", [cursor.Other getString]); + else if ([cursor.Other getType] == tightdb_Date) { + NSLog(@"DateMixed: %ld", [cursor.Other getDate]); + STAssertEquals(nowTime, [cursor.Other getDate],@"Date should match what went in"); + } + else if ([cursor.Other getType] == tightdb_Table) { + NSLog(@"TableMixed: %@", [cursor.Other getTable]); + } } + // 7 + 2 + 2 + 2 + 2 + STAssertEquals(sumType, 20,@"Sum of mixed types should be 20"); } - // 7 + 2 + 2 + 2 + 2 - STAssertEquals(sumType, 20,@"Sum of mixed types should be 20"); + TEST_CHECK_ALLOC; } diff --git a/src/tightdb/objc/test/query.m b/src/tightdb/objc/test/query.m index 444663a3a6..8eb45d97a9 100644 --- a/src/tightdb/objc/test/query.m +++ b/src/tightdb/objc/test/query.m @@ -5,6 +5,8 @@ #import +#import "TestHelper.h" + #import TIGHTDB_TABLE_1(TestQuerySub, @@ -27,6 +29,7 @@ @implementation MACtestQuery - (void)testQuery { + @autoreleasepool { TestQueryAllTypes *table = [[TestQueryAllTypes alloc] init]; NSLog(@"Table: %@", table); STAssertNotNil(table, @"Table is nil"); @@ -134,6 +137,8 @@ - (void)testQuery // [[[table where].MixedCol equal:mixInt1].BoolCol equal:NO]; // [[[table where].MixedCol notEqual:mixInt1].BoolCol equal:NO]; + } + TEST_CHECK_ALLOC; } #define BOOL_COL 0 @@ -147,7 +152,7 @@ - (void)testQuery - (void) testDynamic { - + @autoreleasepool { TightdbTable *table = [[TightdbTable alloc]init]; [table addColumn:tightdb_Bool name:@"BoolCol"]; @@ -229,7 +234,8 @@ - (void) testDynamic STAssertEquals([[[table where] greaterEqualDate:timeNow colNdx:DATE_COL] count], [NSNumber numberWithLongLong:1], @"notEqualDate"); STAssertEquals([[[table where] sumInt:INT_COL] longLongValue], (int64_t)860, @"IntCol max"); - + } + TEST_CHECK_ALLOC; } @end diff --git a/src/tightdb/objc/test/shared_group.mm b/src/tightdb/objc/test/shared_group.mm index 412b04037f..0edfdfcaaf 100644 --- a/src/tightdb/objc/test/shared_group.mm +++ b/src/tightdb/objc/test/shared_group.mm @@ -7,6 +7,8 @@ #import +#import "TestHelper.h" + #import #import #import @@ -28,27 +30,28 @@ @implementation MACTestSharedGroup - (void)testSharedGroup { - TightdbGroup *group = [TightdbGroup group]; - // Create new table in group - SharedTable2 *table = [group getTable:@"employees" withClass:[SharedTable2 class]]; - NSLog(@"Table: %@", table); - // Add some rows - [table addHired:YES Age:50]; - [table addHired:YES Age:52]; - [table addHired:YES Age:53]; - [table addHired:YES Age:54]; - - NSLog(@"MyTable Size: %lu", [table count]); - - - NSFileManager *fm = [NSFileManager defaultManager]; - - // Write to disk - [fm removeItemAtPath:@"employees.tightdb" error:NULL]; - [group write:@"employees.tightdb"]; - - // Read only shared group - TightdbSharedGroup *fromDisk = [TightdbSharedGroup groupWithFilename:@"employees.tightdb"]; + @autoreleasepool { + TightdbGroup *group = [TightdbGroup group]; + // Create new table in group + SharedTable2 *table = [group getTable:@"employees" withClass:[SharedTable2 class]]; + NSLog(@"Table: %@", table); + // Add some rows + [table addHired:YES Age:50]; + [table addHired:YES Age:52]; + [table addHired:YES Age:53]; + [table addHired:YES Age:54]; + + NSLog(@"MyTable Size: %lu", [table count]); + + + NSFileManager *fm = [NSFileManager defaultManager]; + + // Write to disk + [fm removeItemAtPath:@"employees.tightdb" error:NULL]; + [group write:@"employees.tightdb"]; + + // Read only shared group + TightdbSharedGroup *fromDisk = [TightdbSharedGroup groupWithFilename:@"employees.tightdb"]; [fromDisk readTransaction:^(TightdbGroup *group) { SharedTable2 *diskTable = [group getTable:@"employees" withClass:[SharedTable2 class]]; STAssertEquals(size_t(4), [diskTable count], @"There should be 4 rows"); @@ -60,30 +63,30 @@ - (void)testSharedGroup } [diskTable addHired:YES Age:54]; }]; - - // Write shared group and commit -// TightdbSharedGroup *fromDisk = [TightdbSharedGroup groupWithFilename:@"employees.tightdb"]; - [fromDisk writeTransaction:^(TightdbGroup *group) { - SharedTable2 *diskTable = [group getTable:@"employees" withClass:[SharedTable2 class]]; - STAssertEquals(size_t(4), [diskTable count], @"There should be 4 rows"); - for (size_t i = 0; i < 50; i++) { - [diskTable addHired:YES Age:i]; - } - return YES; // Commit - } error:nil]; - // Write shared group and rollback -// TightdbSharedGroup *fromDisk = [TightdbSharedGroup groupWithFilename:@"employees.tightdb"]; - [fromDisk writeTransaction:^(TightdbGroup *group) { - SharedTable2 *diskTable = [group getTable:@"employees" withClass:[SharedTable2 class]]; - STAssertEquals(size_t(54), [diskTable count], @"There should be 54 rows"); - for (size_t i = 0; i < 50; i++) { - [diskTable addHired:YES Age:i]; - } - return NO; // rollback - }]; - // Write and fail with exception in block (Should rollback) - Note: Cannot simulate exception, so doing readonly instead -// TightdbSharedGroup *fromDisk = [TightdbSharedGroup groupWithFilename:@"employees.tightdb"]; - __block int addCount = 0; + + // Write shared group and commit + // TightdbSharedGroup *fromDisk = [TightdbSharedGroup groupWithFilename:@"employees.tightdb"]; + [fromDisk writeTransaction:^(TightdbGroup *group) { + SharedTable2 *diskTable = [group getTable:@"employees" withClass:[SharedTable2 class]]; + STAssertEquals(size_t(4), [diskTable count], @"There should be 4 rows"); + for (size_t i = 0; i < 50; i++) { + [diskTable addHired:YES Age:i]; + } + return YES; // Commit + } error:nil]; + // Write shared group and rollback + // TightdbSharedGroup *fromDisk = [TightdbSharedGroup groupWithFilename:@"employees.tightdb"]; + [fromDisk writeTransaction:^(TightdbGroup *group) { + SharedTable2 *diskTable = [group getTable:@"employees" withClass:[SharedTable2 class]]; + STAssertEquals(size_t(54), [diskTable count], @"There should be 54 rows"); + for (size_t i = 0; i < 50; i++) { + [diskTable addHired:YES Age:i]; + } + return NO; // rollback + }]; + // Write and fail with exception in block (Should rollback) - Note: Cannot simulate exception, so doing readonly instead + // TightdbSharedGroup *fromDisk = [TightdbSharedGroup groupWithFilename:@"employees.tightdb"]; + __block int addCount = 0; [fromDisk writeTransaction:^(TightdbGroup *group) { SharedTable2 *diskTable = [group getTable:@"employees" withClass:[SharedTable2 class]]; // Fake readonly. @@ -96,13 +99,14 @@ - (void)testSharedGroup } return YES; // commit }]; - STAssertEquals(0, addCount, @"No rows should be added"); - - [fromDisk readTransaction:^(TightdbGroup *group) { - SharedTable2 *diskTable = [group getTable:@"employees" withClass:[SharedTable2 class]]; - STAssertEquals(size_t(54), [diskTable count], @"There should be 54 rows"); - }]; - + STAssertEquals(0, addCount, @"No rows should be added"); + + [fromDisk readTransaction:^(TightdbGroup *group) { + SharedTable2 *diskTable = [group getTable:@"employees" withClass:[SharedTable2 class]]; + STAssertEquals(size_t(54), [diskTable count], @"There should be 54 rows"); + }]; + } + TEST_CHECK_ALLOC; } diff --git a/src/tightdb/objc/test/subtable.m b/src/tightdb/objc/test/subtable.m index b7149ef205..a4494a722f 100644 --- a/src/tightdb/objc/test/subtable.m +++ b/src/tightdb/objc/test/subtable.m @@ -7,6 +7,8 @@ #import +#import "TestHelper.h" + #import #import @@ -26,7 +28,7 @@ @implementation MACTestSubtable - (void)setUp { [super setUp]; - + // _group = [Group group]; // NSLog(@"Group: %@", _group); // STAssertNotNil(_group, @"Group is nil"); @@ -35,28 +37,31 @@ - (void)setUp - (void)tearDown { // Tear-down code here. - + // [super tearDown]; // _group = nil; } - (void)testSubtable { - TightdbGroup *group = [TightdbGroup group]; - - /* Create new table in group */ - TestSubtableMain *people = [group getTable:@"employees" withClass:[TestSubtableMain class]]; - - /* FIXME: Add support for specifying a subtable to the 'add' - method. The subtable must then be copied into the parent - table. */ - [people addFirst:@"first" Sub:nil Second:8]; - - TestSubtableMain_Cursor *cursor = [people objectAtIndex:0]; - TestSubtableSub *subtable = cursor.Sub; - [subtable addName:@"name" Age:999]; - - STAssertEquals([subtable objectAtIndex:0].Age, (int64_t)999, @"Age should be 999"); + @autoreleasepool { + TightdbGroup *group = [TightdbGroup group]; + + /* Create new table in group */ + TestSubtableMain *people = [group getTable:@"employees" withClass:[TestSubtableMain class]]; + + /* FIXME: Add support for specifying a subtable to the 'add' + method. The subtable must then be copied into the parent + table. */ + [people addFirst:@"first" Sub:nil Second:8]; + + TestSubtableMain_Cursor *cursor = [people objectAtIndex:0]; + TestSubtableSub *subtable = cursor.Sub; + [subtable addName:@"name" Age:999]; + + STAssertEquals([subtable objectAtIndex:0].Age, (int64_t)999, @"Age should be 999"); + } + TEST_CHECK_ALLOC; } @end diff --git a/src/tightdb/objc/test/table.m b/src/tightdb/objc/test/table.m index c2e73a8819..84e49e9bd9 100644 --- a/src/tightdb/objc/test/table.m +++ b/src/tightdb/objc/test/table.m @@ -5,6 +5,8 @@ #import +#import "TestHelper.h" + #import TIGHTDB_TABLE_1(TestTableSub, @@ -27,103 +29,109 @@ @implementation MACtestTable - (void)testTable { - TightdbTable *_table = [[TightdbTable alloc] init]; - NSLog(@"Table: %@", _table); - STAssertNotNil(_table, @"Table is nil"); - - // 1. Add two columns - [_table addColumn:tightdb_Int name:@"first"]; - [_table addColumn:tightdb_Int name:@"second"]; - - // Verify - STAssertEquals(tightdb_Int, [_table getColumnType:0], @"First column not int"); - STAssertEquals(tightdb_Int, [_table getColumnType:1], @"Second column not int"); - if (![[_table getColumnName:0] isEqualToString:@"first"]) - STFail(@"First not equal to first"); - if (![[_table getColumnName:1] isEqualToString:@"second"]) - STFail(@"Second not equal to second"); - - // 2. Add a row with data - const size_t ndx = [_table addRow]; - [_table set:0 ndx:ndx value:0]; - [_table set:1 ndx:ndx value:10]; - - // Verify - if ([_table get:0 ndx:ndx] != 0) - STFail(@"First not zero"); - if ([_table get:1 ndx:ndx] != 10) - STFail(@"Second not 10"); + @autoreleasepool { + TightdbTable *_table = [[TightdbTable alloc] init]; + NSLog(@"Table: %@", _table); + STAssertNotNil(_table, @"Table is nil"); + + // 1. Add two columns + [_table addColumn:tightdb_Int name:@"first"]; + [_table addColumn:tightdb_Int name:@"second"]; + + // Verify + STAssertEquals(tightdb_Int, [_table getColumnType:0], @"First column not int"); + STAssertEquals(tightdb_Int, [_table getColumnType:1], @"Second column not int"); + if (![[_table getColumnName:0] isEqualToString:@"first"]) + STFail(@"First not equal to first"); + if (![[_table getColumnName:1] isEqualToString:@"second"]) + STFail(@"Second not equal to second"); + + // 2. Add a row with data + const size_t ndx = [_table addRow]; + [_table set:0 ndx:ndx value:0]; + [_table set:1 ndx:ndx value:10]; + + // Verify + if ([_table get:0 ndx:ndx] != 0) + STFail(@"First not zero"); + if ([_table get:1 ndx:ndx] != 10) + STFail(@"Second not 10"); + } + TEST_CHECK_ALLOC; } - (void)testDataTypes { - TestTableAllTypes *table = [[TestTableAllTypes alloc] init]; - NSLog(@"Table: %@", table); - STAssertNotNil(table, @"Table is nil"); - - // Verify column types - STAssertEquals(tightdb_Bool, [table getColumnType:0], @"First column not bool"); - STAssertEquals(tightdb_Int, [table getColumnType:1], @"Second column not int"); - STAssertEquals(tightdb_Float, [table getColumnType:2], @"Third column not float"); - STAssertEquals(tightdb_Double, [table getColumnType:3], @"Fourth column not double"); - STAssertEquals(tightdb_String, [table getColumnType:4], @"Fifth column not string"); - STAssertEquals(tightdb_Binary, [table getColumnType:5], @"Sixth column not binary"); - STAssertEquals(tightdb_Date, [table getColumnType:6], @"Seventh column not date"); - STAssertEquals(tightdb_Table, [table getColumnType:7], @"Eighth column not table"); - STAssertEquals(tightdb_Mixed, [table getColumnType:8], @"Ninth column not mixed"); - - const char bin[4] = { 0, 1, 2, 3 }; - TightdbBinary *bin1 = [[TightdbBinary alloc] initWithData:bin size:sizeof bin / 2]; - TightdbBinary *bin2 = [[TightdbBinary alloc] initWithData:bin size:sizeof bin]; - time_t timeNow = [[NSDate date] timeIntervalSince1970]; - TestTableSub *subtab1 = [[TestTableSub alloc] init]; - TestTableSub *subtab2 = [[TestTableSub alloc] init]; - [subtab2 addAge:100]; - TightdbMixed *mixInt1 = [TightdbMixed mixedWithInt64:1]; - TightdbMixed *mixSubtab = [TightdbMixed mixedWithTable:subtab2]; - - [table addBoolCol:NO IntCol:54 FloatCol:0.7 DoubleCol:0.8 StringCol:@"foo" - BinaryCol:bin1 DateCol:0 TableCol:nil MixedCol:mixInt1]; - - [table addBoolCol:YES IntCol:506 FloatCol:7.7 DoubleCol:8.8 StringCol:@"banach" - BinaryCol:bin2 DateCol:timeNow TableCol:subtab2 MixedCol:mixSubtab]; - - TestTableAllTypes_Cursor *row1 = [table objectAtIndex:0]; - TestTableAllTypes_Cursor *row2 = [table objectAtIndex:1]; - - STAssertEquals(row1.BoolCol, NO, @"row1.BoolCol"); - STAssertEquals(row2.BoolCol, YES, @"row2.BoolCol"); - STAssertEquals(row1.IntCol, (int64_t)54, @"row1.IntCol"); - STAssertEquals(row2.IntCol, (int64_t)506, @"row2.IntCol"); - STAssertEquals(row1.FloatCol, 0.7f, @"row1.FloatCol"); - STAssertEquals(row2.FloatCol, 7.7f, @"row2.FloatCol"); - STAssertEquals(row1.DoubleCol, 0.8, @"row1.DoubleCol"); - STAssertEquals(row2.DoubleCol, 8.8, @"row2.DoubleCol"); - STAssertTrue([row1.StringCol isEqual:@"foo"], @"row1.StringCol"); - STAssertTrue([row2.StringCol isEqual:@"banach"], @"row2.StringCol"); - STAssertTrue([row1.BinaryCol isEqual:bin1], @"row1.BinaryCol"); - STAssertTrue([row2.BinaryCol isEqual:bin2], @"row2.BinaryCol"); - STAssertEquals(row1.DateCol, (time_t)0, @"row1.DateCol"); - STAssertEquals(row2.DateCol, timeNow, @"row2.DateCol"); - STAssertTrue([row1.TableCol isEqual:subtab1], @"row1.TableCol"); - STAssertTrue([row2.TableCol isEqual:subtab2], @"row2.TableCol"); - STAssertTrue([row1.MixedCol isEqual:mixInt1], @"row1.MixedCol"); - STAssertTrue([row2.MixedCol isEqual:mixSubtab], @"row2.MixedCol"); - - STAssertEquals([table.IntCol min], (int64_t)54, @"IntCol min"); - STAssertEquals([table.IntCol max], (int64_t)506, @"IntCol max"); - STAssertEquals([table.IntCol sum], (int64_t)560, @"IntCol sum"); - STAssertEquals([table.IntCol avg], 280.0, @"IntCol avg"); - - STAssertEquals([table.FloatCol min], 0.7f, @"FloatCol min"); - STAssertEquals([table.FloatCol max], 7.7f, @"FloatCol max"); - STAssertEquals([table.FloatCol sum], (double)0.7f + 7.7f, @"FloatCol sum"); - STAssertEquals([table.FloatCol avg], ((double)0.7f + 7.7f) / 2, @"FloatCol avg"); - - STAssertEquals([table.DoubleCol min], 0.8, @"DoubleCol min"); - STAssertEquals([table.DoubleCol max], 8.8, @"DoubleCol max"); - STAssertEquals([table.DoubleCol sum], 0.8 + 8.8, @"DoubleCol sum"); - STAssertEquals([table.DoubleCol avg], (0.8 + 8.8) / 2, @"DoubleCol avg"); + @autoreleasepool { + TestTableAllTypes *table = [[TestTableAllTypes alloc] init]; + NSLog(@"Table: %@", table); + STAssertNotNil(table, @"Table is nil"); + + // Verify column types + STAssertEquals(tightdb_Bool, [table getColumnType:0], @"First column not bool"); + STAssertEquals(tightdb_Int, [table getColumnType:1], @"Second column not int"); + STAssertEquals(tightdb_Float, [table getColumnType:2], @"Third column not float"); + STAssertEquals(tightdb_Double, [table getColumnType:3], @"Fourth column not double"); + STAssertEquals(tightdb_String, [table getColumnType:4], @"Fifth column not string"); + STAssertEquals(tightdb_Binary, [table getColumnType:5], @"Sixth column not binary"); + STAssertEquals(tightdb_Date, [table getColumnType:6], @"Seventh column not date"); + STAssertEquals(tightdb_Table, [table getColumnType:7], @"Eighth column not table"); + STAssertEquals(tightdb_Mixed, [table getColumnType:8], @"Ninth column not mixed"); + + const char bin[4] = { 0, 1, 2, 3 }; + TightdbBinary *bin1 = [[TightdbBinary alloc] initWithData:bin size:sizeof bin / 2]; + TightdbBinary *bin2 = [[TightdbBinary alloc] initWithData:bin size:sizeof bin]; + time_t timeNow = [[NSDate date] timeIntervalSince1970]; + TestTableSub *subtab1 = [[TestTableSub alloc] init]; + TestTableSub *subtab2 = [[TestTableSub alloc] init]; + [subtab2 addAge:100]; + TightdbMixed *mixInt1 = [TightdbMixed mixedWithInt64:1]; + TightdbMixed *mixSubtab = [TightdbMixed mixedWithTable:subtab2]; + + [table addBoolCol:NO IntCol:54 FloatCol:0.7 DoubleCol:0.8 StringCol:@"foo" + BinaryCol:bin1 DateCol:0 TableCol:nil MixedCol:mixInt1]; + + [table addBoolCol:YES IntCol:506 FloatCol:7.7 DoubleCol:8.8 StringCol:@"banach" + BinaryCol:bin2 DateCol:timeNow TableCol:subtab2 MixedCol:mixSubtab]; + + TestTableAllTypes_Cursor *row1 = [table objectAtIndex:0]; + TestTableAllTypes_Cursor *row2 = [table objectAtIndex:1]; + + STAssertEquals(row1.BoolCol, NO, @"row1.BoolCol"); + STAssertEquals(row2.BoolCol, YES, @"row2.BoolCol"); + STAssertEquals(row1.IntCol, (int64_t)54, @"row1.IntCol"); + STAssertEquals(row2.IntCol, (int64_t)506, @"row2.IntCol"); + STAssertEquals(row1.FloatCol, 0.7f, @"row1.FloatCol"); + STAssertEquals(row2.FloatCol, 7.7f, @"row2.FloatCol"); + STAssertEquals(row1.DoubleCol, 0.8, @"row1.DoubleCol"); + STAssertEquals(row2.DoubleCol, 8.8, @"row2.DoubleCol"); + STAssertTrue([row1.StringCol isEqual:@"foo"], @"row1.StringCol"); + STAssertTrue([row2.StringCol isEqual:@"banach"], @"row2.StringCol"); + STAssertTrue([row1.BinaryCol isEqual:bin1], @"row1.BinaryCol"); + STAssertTrue([row2.BinaryCol isEqual:bin2], @"row2.BinaryCol"); + STAssertEquals(row1.DateCol, (time_t)0, @"row1.DateCol"); + STAssertEquals(row2.DateCol, timeNow, @"row2.DateCol"); + STAssertTrue([row1.TableCol isEqual:subtab1], @"row1.TableCol"); + STAssertTrue([row2.TableCol isEqual:subtab2], @"row2.TableCol"); + STAssertTrue([row1.MixedCol isEqual:mixInt1], @"row1.MixedCol"); + STAssertTrue([row2.MixedCol isEqual:mixSubtab], @"row2.MixedCol"); + + STAssertEquals([table.IntCol min], (int64_t)54, @"IntCol min"); + STAssertEquals([table.IntCol max], (int64_t)506, @"IntCol max"); + STAssertEquals([table.IntCol sum], (int64_t)560, @"IntCol sum"); + STAssertEquals([table.IntCol avg], 280.0, @"IntCol avg"); + + STAssertEquals([table.FloatCol min], 0.7f, @"FloatCol min"); + STAssertEquals([table.FloatCol max], 7.7f, @"FloatCol max"); + STAssertEquals([table.FloatCol sum], (double)0.7f + 7.7f, @"FloatCol sum"); + STAssertEquals([table.FloatCol avg], ((double)0.7f + 7.7f) / 2, @"FloatCol avg"); + + STAssertEquals([table.DoubleCol min], 0.8, @"DoubleCol min"); + STAssertEquals([table.DoubleCol max], 8.8, @"DoubleCol max"); + STAssertEquals([table.DoubleCol sum], 0.8 + 8.8, @"DoubleCol sum"); + STAssertEquals([table.DoubleCol avg], (0.8 + 8.8) / 2, @"DoubleCol avg"); + } + TEST_CHECK_ALLOC; } @end diff --git a/src/tightdb/objc/test/table_delete_all.m b/src/tightdb/objc/test/table_delete_all.m index 2d83596bbc..444ec3ab91 100644 --- a/src/tightdb/objc/test/table_delete_all.m +++ b/src/tightdb/objc/test/table_delete_all.m @@ -5,6 +5,8 @@ #import +#import "TestHelper.h" + #import @interface MACTestTableDeleteAll: SenTestCase @@ -13,86 +15,90 @@ @implementation MACTestTableDeleteAll -(void)testTableDeleteAll { - // Create table with all column types - TightdbTable *table = [[TightdbTable alloc] init]; - TightdbSpec *s = [table getSpec]; - [s addColumn:tightdb_Int name:@"int"]; - [s addColumn:tightdb_Bool name:@"bool"]; - [s addColumn:tightdb_Date name:@"date"]; - [s addColumn:tightdb_String name:@"string"]; - [s addColumn:tightdb_String name:@"string_long"]; - [s addColumn:tightdb_String name:@"string_enum"]; - [s addColumn:tightdb_Binary name:@"binary"]; - [s addColumn:tightdb_Mixed name:@"mixed"]; - TightdbSpec *sub = [s addColumnTable:@"tables"]; - [sub addColumn:tightdb_Int name:@"sub_first"]; - [sub addColumn:tightdb_String name:@"sub_second"]; - [table updateFromSpec]; - - // Add some rows - for (size_t i = 0; i < 15; ++i) { - [table insertInt:0 ndx:i value:i]; - [table insertBool:1 ndx:i value:(i % 2 ? YES : NO)]; - [table insertDate:2 ndx:i value:12345]; - [table insertString:3 ndx:i value:[NSString stringWithFormat:@"string %zu", i]]; - [table insertString:4 ndx:i value:@" Very long string.............."]; - - switch (i % 3) { - case 0: - [table insertString:5 ndx:i value:@"test1"]; - break; - case 1: - [table insertString:5 ndx:i value:@"test2"]; - break; - case 2: - [table insertString:5 ndx:i value:@"test3"]; - break; - } - - [table insertBinary:6 ndx:i data:"binary" size:7]; - switch (i % 3) { - case 0: - [table insertMixed:7 ndx:i value:[TightdbMixed mixedWithBool:NO]]; - break; - case 1: - [table insertMixed:7 ndx:i value:[TightdbMixed mixedWithInt64:i]]; - break; - case 2: - [table insertMixed:7 ndx:i value:[TightdbMixed mixedWithString:@"string"]]; - break; - } - [table insertSubtable:8 ndx:i]; - [table insertDone]; - - // Add sub-tables - if (i == 2) { - TightdbTable *subtable = [table getSubtable:8 ndx:i]; - [subtable insertInt:0 ndx:0 value:42]; - [subtable insertString:1 ndx:0 value:@"meaning"]; - [subtable insertDone]; + @autoreleasepool { + // Create table with all column types + TightdbTable *table = [[TightdbTable alloc] init]; + TightdbSpec *s = [table getSpec]; + [s addColumn:tightdb_Int name:@"int"]; + [s addColumn:tightdb_Bool name:@"bool"]; + [s addColumn:tightdb_Date name:@"date"]; + [s addColumn:tightdb_String name:@"string"]; + [s addColumn:tightdb_String name:@"string_long"]; + [s addColumn:tightdb_String name:@"string_enum"]; + [s addColumn:tightdb_Binary name:@"binary"]; + [s addColumn:tightdb_Mixed name:@"mixed"]; + TightdbSpec *sub = [s addColumnTable:@"tables"]; + [sub addColumn:tightdb_Int name:@"sub_first"]; + [sub addColumn:tightdb_String name:@"sub_second"]; + [table updateFromSpec]; + + // Add some rows + for (size_t i = 0; i < 15; ++i) { + [table insertInt:0 ndx:i value:i]; + [table insertBool:1 ndx:i value:(i % 2 ? YES : NO)]; + [table insertDate:2 ndx:i value:12345]; + [table insertString:3 ndx:i value:[NSString stringWithFormat:@"string %zu", i]]; + [table insertString:4 ndx:i value:@" Very long string.............."]; + + switch (i % 3) { + case 0: + [table insertString:5 ndx:i value:@"test1"]; + break; + case 1: + [table insertString:5 ndx:i value:@"test2"]; + break; + case 2: + [table insertString:5 ndx:i value:@"test3"]; + break; + } + + [table insertBinary:6 ndx:i data:"binary" size:7]; + switch (i % 3) { + case 0: + [table insertMixed:7 ndx:i value:[TightdbMixed mixedWithBool:NO]]; + break; + case 1: + [table insertMixed:7 ndx:i value:[TightdbMixed mixedWithInt64:i]]; + break; + case 2: + [table insertMixed:7 ndx:i value:[TightdbMixed mixedWithString:@"string"]]; + break; + } + [table insertSubtable:8 ndx:i]; + [table insertDone]; + + // Add sub-tables + if (i == 2) { + TightdbTable *subtable = [table getSubtable:8 ndx:i]; + [subtable insertInt:0 ndx:0 value:42]; + [subtable insertString:1 ndx:0 value:@"meaning"]; + [subtable insertDone]; + } + } - - } - - // We also want a ColumnStringEnum - [table optimize]; - - // Test Deletes - [table remove:14]; - [table remove:0]; - [table remove:5]; - STAssertEquals([table count], (size_t)12, @"Size should have been 12"); + + // We also want a ColumnStringEnum + [table optimize]; + + // Test Deletes + [table remove:14]; + [table remove:0]; + [table remove:5]; + STAssertEquals([table count], (size_t)12, @"Size should have been 12"); #ifdef TIGHTDB_DEBUG - [table verify]; + [table verify]; #endif - - // Test Clear - [table clear]; - STAssertEquals([table count], (size_t)0, @"Size should have been zero"); - + + // Test Clear + [table clear]; + STAssertEquals([table count], (size_t)0, @"Size should have been zero"); + #ifdef TIGHTDB_DEBUG - [table verify]; + [table verify]; #endif + } + TEST_CHECK_ALLOC; + } @end diff --git a/src/tightdb/objc/test/template.m b/src/tightdb/objc/test/template.m index 0505e5cb3b..6421b0b865 100644 --- a/src/tightdb/objc/test/template.m +++ b/src/tightdb/objc/test/template.m @@ -4,6 +4,8 @@ // #import +#import "TestHelper.h" + #import @@ -27,6 +29,10 @@ - (void)tearDown - (void)testExample { + @autoreleasepool { + + } + TEST_CHECK_ALLOC; } @end diff --git a/src/tightdb/objc/test/tutorial.m b/src/tightdb/objc/test/tutorial.m index c469d55184..0de478e46d 100644 --- a/src/tightdb/objc/test/tutorial.m +++ b/src/tightdb/objc/test/tutorial.m @@ -7,6 +7,8 @@ #import +#import "TestHelper.h" + #import #import @@ -29,14 +31,6 @@ Age, Int) -#ifdef TIGHTDB_DEBUG -extern int TightdbViewAllocateCount; -extern int TightdbCursorAllocateCount; -extern int TightdbGroupAllocateCount; -extern int TightdbSpecAllocateCount; -extern int TightdbTableAllocateCount; -#endif - @interface MACTestTutorial: SenTestCase @end @implementation MACTestTutorial @@ -185,13 +179,7 @@ - (void)testTutorial NSLog(@"%zu: %@", i, cursor.Name); } } -#ifdef TIGHTDB_DEBUG - STAssertEquals(0, TightdbViewAllocateCount, @"Zero TightdbView allocated"); - STAssertEquals(0, TightdbCursorAllocateCount, @"Zero TightdbCursor allocated"); - STAssertEquals(0, TightdbGroupAllocateCount, @"Zero TightdbGroup allocated"); - STAssertEquals(0, TightdbSpecAllocateCount, @"Zero TightdbSpec allocated"); - STAssertEquals(0, TightdbTableAllocateCount, @"Zero TightdbTable allocated"); -#endif + TEST_CHECK_ALLOC; } From 5939771fbf1cfe29976084eb6675520268e8282c Mon Sep 17 00:00:00 2001 From: Thomas Andersen Date: Tue, 2 Jul 2013 17:22:37 +0200 Subject: [PATCH 4/6] Made allocation counter atomic so they can survie multi threaded access. Problem observed running multithread test case multiple times. --- .../TightDbObjcDyn.xcodeproj/project.pbxproj | 8 +- src/tightdb/objc/cursor_objc.mm | 2 +- src/tightdb/objc/group_objc.mm | 2 +- src/tightdb/objc/group_shared_objc.mm | 2 +- src/tightdb/objc/query_objc.mm | 2 +- src/tightdb/objc/table_objc.mm | 46 +++- src/tightdb/objc/test/Makefile | 2 +- src/tightdb/objc/test/TestHelper.h | 20 +- src/tightdb/objc/test/threads.m | 231 ++++++++++++++++++ 9 files changed, 296 insertions(+), 19 deletions(-) create mode 100644 src/tightdb/objc/test/threads.m diff --git a/TightDbObjcDyn/TightDbObjcDyn.xcodeproj/project.pbxproj b/TightDbObjcDyn/TightDbObjcDyn.xcodeproj/project.pbxproj index b9caf0c047..a70646a540 100644 --- a/TightDbObjcDyn/TightDbObjcDyn.xcodeproj/project.pbxproj +++ b/TightDbObjcDyn/TightDbObjcDyn.xcodeproj/project.pbxproj @@ -43,6 +43,7 @@ E9189100177B71E400653D7A /* table.m in Sources */ = {isa = PBXBuildFile; fileRef = E91890F2177B71E400653D7A /* table.m */; }; E9189101177B71E400653D7A /* template.m in Sources */ = {isa = PBXBuildFile; fileRef = E91890F3177B71E400653D7A /* template.m */; }; E9189102177B71E400653D7A /* tutorial.m in Sources */ = {isa = PBXBuildFile; fileRef = E91890F4177B71E400653D7A /* tutorial.m */; }; + E94EA3E117831986001AE3DA /* threads.m in Sources */ = {isa = PBXBuildFile; fileRef = E94EA3E017831986001AE3DA /* threads.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -97,6 +98,7 @@ E91890F2177B71E400653D7A /* table.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = table.m; path = ../../src/tightdb/objc/test/table.m; sourceTree = ""; }; E91890F3177B71E400653D7A /* template.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = template.m; path = ../../src/tightdb/objc/test/template.m; sourceTree = ""; }; E91890F4177B71E400653D7A /* tutorial.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = tutorial.m; path = ../../src/tightdb/objc/test/tutorial.m; sourceTree = ""; }; + E94EA3E017831986001AE3DA /* threads.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = threads.m; path = ../../src/tightdb/objc/test/threads.m; sourceTree = ""; }; E9F2A7B11781FAB600292661 /* TestHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TestHelper.h; path = ../../src/tightdb/objc/test/TestHelper.h; sourceTree = ""; }; /* End PBXFileReference section */ @@ -197,7 +199,6 @@ E91890B4177B677900653D7A /* TightDbObjcDynTests */ = { isa = PBXGroup; children = ( - E9F2A7B11781FAB600292661 /* TestHelper.h */, E91890E7177B71E400653D7A /* data_type.mm */, E91890E8177B71E400653D7A /* enumerator.m */, E91890E9177B71E400653D7A /* err_handling.mm */, @@ -210,8 +211,10 @@ E91890F0177B71E400653D7A /* subtable.m */, E91890F1177B71E400653D7A /* table_delete_all.m */, E91890F2177B71E400653D7A /* table.m */, - E91890F3177B71E400653D7A /* template.m */, E91890F4177B71E400653D7A /* tutorial.m */, + E9F2A7B11781FAB600292661 /* TestHelper.h */, + E91890F3177B71E400653D7A /* template.m */, + E94EA3E017831986001AE3DA /* threads.m */, E91890B5177B677900653D7A /* Supporting Files */, ); path = TightDbObjcDynTests; @@ -372,6 +375,7 @@ E9189100177B71E400653D7A /* table.m in Sources */, E9189101177B71E400653D7A /* template.m in Sources */, E9189102177B71E400653D7A /* tutorial.m in Sources */, + E94EA3E117831986001AE3DA /* threads.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/src/tightdb/objc/cursor_objc.mm b/src/tightdb/objc/cursor_objc.mm index 794232eee1..26d219cb7e 100644 --- a/src/tightdb/objc/cursor_objc.mm +++ b/src/tightdb/objc/cursor_objc.mm @@ -13,7 +13,7 @@ using namespace std; #ifdef TIGHTDB_DEBUG -int TightdbCursorAllocateCount = 0; +_Atomic(int) TightdbCursorAllocateCount = 0; #endif @interface TightdbCursor() diff --git a/src/tightdb/objc/group_objc.mm b/src/tightdb/objc/group_objc.mm index d2cb71852e..c995ebb9cb 100644 --- a/src/tightdb/objc/group_objc.mm +++ b/src/tightdb/objc/group_objc.mm @@ -15,7 +15,7 @@ using namespace std; #ifdef TIGHTDB_DEBUG -int TightdbGroupAllocateCount = 0; +_Atomic(int) TightdbGroupAllocateCount = 0; #endif @interface TightdbGroup() diff --git a/src/tightdb/objc/group_shared_objc.mm b/src/tightdb/objc/group_shared_objc.mm index 504dd9598c..b29960451c 100644 --- a/src/tightdb/objc/group_shared_objc.mm +++ b/src/tightdb/objc/group_shared_objc.mm @@ -8,7 +8,7 @@ using namespace std; #ifdef TIGHTDB_DEBUG -int TightdbGroupSharedAllocateCount = 0; +_Atomic(int) TightdbGroupSharedAllocateCount = 0; #endif diff --git a/src/tightdb/objc/query_objc.mm b/src/tightdb/objc/query_objc.mm index 76d6a8fe86..bff6a12b63 100644 --- a/src/tightdb/objc/query_objc.mm +++ b/src/tightdb/objc/query_objc.mm @@ -18,7 +18,7 @@ using namespace std; #ifdef TIGHTDB_DEBUG -int TightdbQueryAllocateCount = 0; +_Atomic(int) TightdbQueryAllocateCount = 0; #endif diff --git a/src/tightdb/objc/table_objc.mm b/src/tightdb/objc/table_objc.mm index 993d557caf..0ca634d10e 100644 --- a/src/tightdb/objc/table_objc.mm +++ b/src/tightdb/objc/table_objc.mm @@ -17,6 +17,11 @@ using namespace std; + +#ifdef TIGHTDB_DEBUG +_Atomic(int) TightdbBinaryAllocateCount = 0; +#endif + @implementation TightdbBinary { tightdb::BinaryData _data; @@ -26,6 +31,9 @@ -(id)initWithData:(const char *)data size:(size_t)size self = [super init]; if (self) { _data = tightdb::BinaryData(data, size); +#ifdef TIGHTDB_DEBUG + ++TightdbBinaryAllocateCount; +#endif } return self; } @@ -34,6 +42,9 @@ -(id)initWithBinary:(tightdb::BinaryData)data self = [super init]; if (self) { _data = data; +#ifdef TIGHTDB_DEBUG + ++TightdbBinaryAllocateCount; +#endif } return self; } @@ -53,8 +64,17 @@ -(BOOL)isEqual:(TightdbBinary *)bin { return _data; } +-(void)dealloc +{ +#ifdef TIGHTDB_DEBUG + --TightdbBinaryAllocateCount; +#endif +} @end +#ifdef TIGHTDB_DEBUG +_Atomic(int) TightdbMixedAllocateCount = 0; +#endif @interface TightdbMixed() @property (nonatomic) tightdb::Mixed mixed; @@ -65,6 +85,23 @@ @implementation TightdbMixed @synthesize mixed = _mixed; @synthesize table = _table; +-(id)init +{ + self = [super init]; + if (self) { +#ifdef TIGHTDB_DEBUG + ++TightdbMixedAllocateCount; +#endif + } + return self; +} +-(void)dealloc +{ +#ifdef TIGHTDB_DEBUG + --TightdbMixedAllocateCount; +#endif +} + +(TightdbMixed *)mixedWithBool:(BOOL)value { TightdbMixed *mixed = [[TightdbMixed alloc] init]; @@ -211,7 +248,7 @@ -(TightdbTable *)getTable @end #ifdef TIGHTDB_DEBUG -int TightdbSpecAllocateCount = 0; +_Atomic(int) TightdbSpecAllocateCount = 0; #endif @interface TightdbSpec() @@ -329,7 +366,7 @@ -(void)dealloc #ifdef TIGHTDB_DEBUG -int TightdbViewAllocateCount = 0; +_Atomic(int) TightdbViewAllocateCount = 0; #endif @interface TightdbView() @@ -461,7 +498,7 @@ - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state object #ifdef TIGHTDB_DEBUG -int TightdbTableAllocateCount = 0; +_Atomic(int) TightdbTableAllocateCount = 0; #endif @implementation TightdbTable @@ -486,6 +523,7 @@ -(id)initWithError:(NSError *__autoreleasing *)error , @"com.tightdb.table", return nil); #ifdef TIGHTDB_DEBUG ++TightdbTableAllocateCount; + NSLog(@"TightdbTable init"); #endif } return self; @@ -1387,7 +1425,7 @@ -(void)verify #ifdef TIGHTDB_DEBUG -int TightdbColumnProxyAllocateCount = 0; +_Atomic(int) TightdbColumnProxyAllocateCount = 0; #endif @implementation TightdbColumnProxy diff --git a/src/tightdb/objc/test/Makefile b/src/tightdb/objc/test/Makefile index 3770cd490b..b9659cb923 100644 --- a/src/tightdb/objc/test/Makefile +++ b/src/tightdb/objc/test/Makefile @@ -4,7 +4,7 @@ XCODE_HOME = $(shell xcode-select --print-path) unit_tests_SOURCES = \ data_type.mm table.m group.m group_misc_2.m table_delete_all.m tutorial.m enumerator.m \ -get_subtable.m subtable.m mixed.m query.m shared_group.m err_handling.mm +get_subtable.m subtable.m mixed.m query.m shared_group.m err_handling.mm threads.m unit_tests_CFLAGS = -Wno-comment -fobjc-arc -fobjc-abi-version=2 -F$(XCODE_HOME)/Library/Frameworks unit_tests_LDFLAGS = -bundle -fobjc-link-runtime -F$(XCODE_HOME)/Library/Frameworks -framework Cocoa -framework SenTestingKit diff --git a/src/tightdb/objc/test/TestHelper.h b/src/tightdb/objc/test/TestHelper.h index 734d84b83f..47555b42f6 100644 --- a/src/tightdb/objc/test/TestHelper.h +++ b/src/tightdb/objc/test/TestHelper.h @@ -15,18 +15,22 @@ extern int TightdbGroupAllocateCount; extern int TightdbGroupSharedAllocateCount; extern int TightdbSpecAllocateCount; extern int TightdbTableAllocateCount; +extern int TightdbBinaryAllocateCount; +extern int TightdbMixedAllocateCount; #endif #ifdef TIGHTDB_DEBUG -#define TEST_CHECK_ALLOC STAssertEquals(0, TightdbQueryAllocateCount, @"Zero TightdbQuery allocated"); \ -STAssertEquals(0, TightdbViewAllocateCount, @"Zero TightdbView allocated"); \ -STAssertEquals(0, TightdbCursorAllocateCount, @"Zero TightdbCursor allocated"); \ -STAssertEquals(0, TightdbColumnProxyAllocateCount, @"Zero TightdbColumnProxy allocated"); \ -STAssertEquals(0, TightdbGroupAllocateCount, @"Zero TightdbGroup allocated"); \ -STAssertEquals(0, TightdbGroupSharedAllocateCount, @"Zero TightdbGroupShared allocated"); \ -STAssertEquals(0, TightdbSpecAllocateCount, @"Zero TightdbSpec allocated"); \ -STAssertEquals(0, TightdbTableAllocateCount, @"Zero TightdbTable allocated"); +#define TEST_CHECK_ALLOC STAssertEquals(TightdbQueryAllocateCount, 0, @"Zero TightdbQuery allocated"); \ +STAssertEquals(TightdbViewAllocateCount, 0, @"Zero TightdbView allocated"); \ +STAssertEquals(TightdbCursorAllocateCount, 0, @"Zero TightdbCursor allocated"); \ +STAssertEquals(TightdbColumnProxyAllocateCount, 0, @"Zero TightdbColumnProxy allocated"); \ +STAssertEquals(TightdbGroupAllocateCount, 0, @"Zero TightdbGroup allocated"); \ +STAssertEquals(TightdbGroupSharedAllocateCount, 0, @"Zero TightdbGroupShared allocated"); \ +STAssertEquals(TightdbSpecAllocateCount, 0, @"Zero TightdbSpec allocated"); \ +STAssertEquals(TightdbBinaryAllocateCount, 0, @"Zero TightdbBinary allocated"); \ +STAssertEquals(TightdbMixedAllocateCount, 0, @"Zero TightdbMixed allocated"); \ +STAssertEquals(TightdbTableAllocateCount, 0, @"Zero TightdbTable allocated"); #else #define TEST_CHECK_ALLOC #endif diff --git a/src/tightdb/objc/test/threads.m b/src/tightdb/objc/test/threads.m new file mode 100644 index 0000000000..df97ca8e7a --- /dev/null +++ b/src/tightdb/objc/test/threads.m @@ -0,0 +1,231 @@ +// +// threads.m +// TightDb +// + +#import +#import "TestHelper.h" + +#import +#import + + +TIGHTDB_TABLE_2(TestThreadTableGroup, + First, String, + Second, Int) + +TIGHTDB_TABLE_3(EnumPeopleThreadTable, + Name, String, + Age, Int, + Hired, Bool) + +TIGHTDB_TABLE_2(EnumPeopleThreadTable2, + Hired, Bool, + Age, Int) + +TIGHTDB_TABLE_DEF_3(PeopleTable, + Name, String, + Age, Int, + Hired, Bool) + +@interface MacTightDbTestsThreads: SenTestCase +@end +@implementation MacTightDbTestsThreads + +- (void)setUp +{ + [super setUp]; + + // Set-up code here. +} + +- (void)tearDown +{ + // Tear-down code here. + + [super tearDown]; + + // Workaround for problem when executing test in xcode. Remove if do not care. :) + sleep(1); // Workaround for bug in xcode - sometimes it says test did not finish even though it did. This should be a possible workaround. Unfortunately it slows the execution down. +} + +- (void)testThreads +{ + int runCount = 10; + while(--runCount>0) { + dispatch_semaphore_t sema = dispatch_semaphore_create(0); + __block int doneCount = 0; + int actualThreads = 0; + + ++actualThreads; + dispatch_async(dispatch_get_global_queue(0, 0), ^{ + @autoreleasepool { + TightdbGroup *fromDisk = [TightdbGroup groupWithFilename:@"employees.tightdb"]; + PeopleTable *diskTable = [fromDisk getTable:@"employees" withClass:[PeopleTable class]]; + + [diskTable addName:@"Thread1" Age:1 Hired:YES]; + + NSLog(@"Disktable size: %zu", [diskTable count]); + + for (size_t i = 0; i < [diskTable count]; i++) { + PeopleTable_Cursor *cursor = [diskTable objectAtIndex:i]; + NSLog(@"%zu: %@", i, [cursor Name]); + } + } + ++doneCount; + dispatch_semaphore_signal(sema); + }); + ++actualThreads; + dispatch_async(dispatch_get_global_queue(0, 0), ^{ + @autoreleasepool { + TightdbGroup *fromDisk = [TightdbGroup groupWithFilename:@"employees.tightdb"]; + PeopleTable *diskTable = [fromDisk getTable:@"employees" withClass:[PeopleTable class]]; + + [diskTable addName:@"Thread2" Age:2 Hired:YES]; + + NSLog(@"Disktable size: %zu", [diskTable count]); + + for (size_t i = 0; i < [diskTable count]; i++) { + PeopleTable_Cursor *cursor = [diskTable objectAtIndex:i]; + NSLog(@"%zu: %@", i, [cursor Name]); + } + } + ++doneCount; + dispatch_semaphore_signal(sema); + }); + ++actualThreads; + dispatch_async(dispatch_get_global_queue(0, 0), ^{ + @autoreleasepool { + NSFileManager *fm = [NSFileManager defaultManager]; + + // Create empty group and serialize to disk + TightdbGroup *toDisk = [TightdbGroup group]; + [fm removeItemAtPath:@"table_test.tightdb" error:NULL]; + [toDisk write:@"table_test.tightdb"]; + + // Load the group + TightdbGroup *fromDisk = [TightdbGroup groupWithFilename:@"table_test.tightdb"]; + if (!fromDisk) + STFail(@"From disk not valid"); + + // Create new table in group + TestThreadTableGroup *t = (TestThreadTableGroup *)[fromDisk getTable:@"test" withClass:[TestThreadTableGroup class]]; + + // Verify + NSLog(@"Columns: %zu", [t getColumnCount]); + if ([t getColumnCount] != 2) + STFail(@"Should have been 2 columns"); + if ([t count] != 0) + STFail(@"Should have been empty"); + + // Modify table + [t addFirst:@"Test" Second:YES]; + NSLog(@"Size: %lu", [t count]); + + // Verify + if ([t count] != 1) + STFail(@"Should have been one row"); + + t = nil; + } + ++doneCount; + dispatch_semaphore_signal(sema); + }); + ++actualThreads; + dispatch_async(dispatch_get_global_queue(0, 0), ^{ + @autoreleasepool { + TightdbGroup *group = [TightdbGroup group]; + TightdbTable *table = [group getTable:@"table" withClass:[TightdbTable class]]; + + // Specify the table schema + { + TightdbSpec *s = [table getSpec]; + [s addColumn:tightdb_Int name:@"int"]; + { + TightdbSpec *sub = [s addColumnTable:@"tab"]; + [sub addColumn:tightdb_Int name:@"int"]; + } + [s addColumn:tightdb_Mixed name:@"mix"]; + [table updateFromSpec]; + } + + int COL_TABLE_INT = 0; + int COL_TABLE_TAB = 1; + int COL_TABLE_MIX = 2; + int COL_SUBTABLE_INT = 0; + + // Add a row to the top level table + [table addRow]; + [table set:COL_TABLE_INT ndx:0 value:700]; + + // Add two rows to the subtable + TightdbTable *subtable = [table getSubtable:COL_TABLE_TAB ndx:0]; + [subtable addRow]; + [subtable set:COL_SUBTABLE_INT ndx:0 value:800]; + [subtable addRow]; + [subtable set:COL_SUBTABLE_INT ndx:1 value:801]; + + // Make the mixed values column contain another subtable + [table setMixed:COL_TABLE_MIX ndx:0 value: [TightdbMixed mixedWithTable:nil]]; + } + ++doneCount; + dispatch_semaphore_signal(sema); + }); + ++actualThreads; + dispatch_async(dispatch_get_global_queue(0, 0), ^{ + @autoreleasepool { + //------------------------------------------------------ + NSLog(@"--- Creating tables ---"); + //------------------------------------------------------ + TightdbGroup *group = [TightdbGroup group]; + // Create new table in group + EnumPeopleThreadTable *people = [group getTable:@"employees" withClass:[EnumPeopleThreadTable class]]; + + // Add some rows + [people addName:@"John" Age:20 Hired:YES]; + [people addName:@"Mary" Age:21 Hired:NO]; + [people addName:@"Lars" Age:21 Hired:YES]; + [people addName:@"Phil" Age:43 Hired:NO]; + [people addName:@"Anni" Age:54 Hired:YES]; + + //------------------------------------------------------ + NSLog(@"--- Iterators ---"); + //------------------------------------------------------ + + // 1: Iterate over table + for (EnumPeopleThreadTable_Cursor *row in people) { + NSLog(@"(Enum)%@ is %lld years old.", row.Name, row.Age); + } + + // Do a query, and get all matches as TableView + EnumPeopleThreadTable_View *res = [[[[people where].Hired equal:YES].Age between:20 to:30] findAll]; + NSLog(@"View count: %zu", [res count]); + // 2: Iterate over the resulting TableView + for (EnumPeopleThreadTable_Cursor *row in res) { + NSLog(@"(Enum2) %@ is %lld years old.", row.Name, row.Age); + } + + // 3: Iterate over query (lazy) + + EnumPeopleThreadTable_Query *q = [[people where].Age equal:21]; + NSLog(@"Query lazy count: %zu", [[q count] unsignedLongValue] ); + for (EnumPeopleThreadTable_Cursor *row in q) { + NSLog(@"(Enum3) %@ is %lld years old.", row.Name, row.Age); + if (row.Name == nil) + break; + } + } + ++doneCount; + dispatch_semaphore_signal(sema); + }); + NSLog(@"Wait for background tasks..."); + while(doneCount Date: Thu, 4 Jul 2013 19:07:44 +0200 Subject: [PATCH 5/6] Re-evaluated property limitation after suggestion from Jesper. It was a success, and it should now be allowed to have any case in column names. API should probably be redone to reflect this --- .../TightDbObjcDyn.xcodeproj/project.pbxproj | 54 +- src/tightdb/objc/helper_macros.h | 22 +- src/tightdb/objc/test/query.m | 294 +++++------ src/tightdb/objc/tightdb.h | 480 +++++++++--------- src/tightdb/objc/tightdb.h.py | 4 +- 5 files changed, 429 insertions(+), 425 deletions(-) diff --git a/TightDbObjcDyn/TightDbObjcDyn.xcodeproj/project.pbxproj b/TightDbObjcDyn/TightDbObjcDyn.xcodeproj/project.pbxproj index a70646a540..292c2e6cad 100644 --- a/TightDbObjcDyn/TightDbObjcDyn.xcodeproj/project.pbxproj +++ b/TightDbObjcDyn/TightDbObjcDyn.xcodeproj/project.pbxproj @@ -7,6 +7,19 @@ objects = { /* Begin PBXBuildFile section */ + E9106BC61785E31400113590 /* data_type.mm in Sources */ = {isa = PBXBuildFile; fileRef = E91890E7177B71E400653D7A /* data_type.mm */; }; + E9106BC71785E31400113590 /* enumerator.m in Sources */ = {isa = PBXBuildFile; fileRef = E91890E8177B71E400653D7A /* enumerator.m */; }; + E9106BC81785E31400113590 /* err_handling.mm in Sources */ = {isa = PBXBuildFile; fileRef = E91890E9177B71E400653D7A /* err_handling.mm */; }; + E9106BC91785E31400113590 /* get_subtable.m in Sources */ = {isa = PBXBuildFile; fileRef = E91890EA177B71E400653D7A /* get_subtable.m */; }; + E9106BCA1785E31400113590 /* group_misc_2.m in Sources */ = {isa = PBXBuildFile; fileRef = E91890EB177B71E400653D7A /* group_misc_2.m */; }; + E9106BCB1785E31400113590 /* group.m in Sources */ = {isa = PBXBuildFile; fileRef = E91890EC177B71E400653D7A /* group.m */; }; + E9106BCC1785E31400113590 /* mixed.m in Sources */ = {isa = PBXBuildFile; fileRef = E91890ED177B71E400653D7A /* mixed.m */; }; + E9106BCD1785E31400113590 /* shared_group.mm in Sources */ = {isa = PBXBuildFile; fileRef = E91890EF177B71E400653D7A /* shared_group.mm */; }; + E9106BCE1785E31400113590 /* subtable.m in Sources */ = {isa = PBXBuildFile; fileRef = E91890F0177B71E400653D7A /* subtable.m */; }; + E9106BCF1785E31400113590 /* table_delete_all.m in Sources */ = {isa = PBXBuildFile; fileRef = E91890F1177B71E400653D7A /* table_delete_all.m */; }; + E9106BD01785E31400113590 /* table.m in Sources */ = {isa = PBXBuildFile; fileRef = E91890F2177B71E400653D7A /* table.m */; }; + E9106BD11785E31400113590 /* tutorial.m in Sources */ = {isa = PBXBuildFile; fileRef = E91890F4177B71E400653D7A /* tutorial.m */; }; + E9106BD21785E31400113590 /* threads.m in Sources */ = {isa = PBXBuildFile; fileRef = E94EA3E017831986001AE3DA /* threads.m */; }; E918909D177B677900653D7A /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E918909C177B677900653D7A /* Cocoa.framework */; }; E91890AF177B677900653D7A /* SenTestingKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E91890AE177B677900653D7A /* SenTestingKit.framework */; }; E91890B0177B677900653D7A /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E918909C177B677900653D7A /* Cocoa.framework */; }; @@ -29,21 +42,7 @@ E91890E4177B67AB00653D7A /* tightdb.h in Headers */ = {isa = PBXBuildFile; fileRef = E91890D3177B67AB00653D7A /* tightdb.h */; }; E91890E5177B67AB00653D7A /* type.h in Headers */ = {isa = PBXBuildFile; fileRef = E91890D4177B67AB00653D7A /* type.h */; }; E91890E6177B67AB00653D7A /* util.hpp in Headers */ = {isa = PBXBuildFile; fileRef = E91890D5177B67AB00653D7A /* util.hpp */; }; - E91890F5177B71E400653D7A /* data_type.mm in Sources */ = {isa = PBXBuildFile; fileRef = E91890E7177B71E400653D7A /* data_type.mm */; }; - E91890F6177B71E400653D7A /* enumerator.m in Sources */ = {isa = PBXBuildFile; fileRef = E91890E8177B71E400653D7A /* enumerator.m */; }; - E91890F7177B71E400653D7A /* err_handling.mm in Sources */ = {isa = PBXBuildFile; fileRef = E91890E9177B71E400653D7A /* err_handling.mm */; }; - E91890F8177B71E400653D7A /* get_subtable.m in Sources */ = {isa = PBXBuildFile; fileRef = E91890EA177B71E400653D7A /* get_subtable.m */; }; - E91890F9177B71E400653D7A /* group_misc_2.m in Sources */ = {isa = PBXBuildFile; fileRef = E91890EB177B71E400653D7A /* group_misc_2.m */; }; - E91890FA177B71E400653D7A /* group.m in Sources */ = {isa = PBXBuildFile; fileRef = E91890EC177B71E400653D7A /* group.m */; }; - E91890FB177B71E400653D7A /* mixed.m in Sources */ = {isa = PBXBuildFile; fileRef = E91890ED177B71E400653D7A /* mixed.m */; }; E91890FC177B71E400653D7A /* query.m in Sources */ = {isa = PBXBuildFile; fileRef = E91890EE177B71E400653D7A /* query.m */; }; - E91890FD177B71E400653D7A /* shared_group.mm in Sources */ = {isa = PBXBuildFile; fileRef = E91890EF177B71E400653D7A /* shared_group.mm */; }; - E91890FE177B71E400653D7A /* subtable.m in Sources */ = {isa = PBXBuildFile; fileRef = E91890F0177B71E400653D7A /* subtable.m */; }; - E91890FF177B71E400653D7A /* table_delete_all.m in Sources */ = {isa = PBXBuildFile; fileRef = E91890F1177B71E400653D7A /* table_delete_all.m */; }; - E9189100177B71E400653D7A /* table.m in Sources */ = {isa = PBXBuildFile; fileRef = E91890F2177B71E400653D7A /* table.m */; }; - E9189101177B71E400653D7A /* template.m in Sources */ = {isa = PBXBuildFile; fileRef = E91890F3177B71E400653D7A /* template.m */; }; - E9189102177B71E400653D7A /* tutorial.m in Sources */ = {isa = PBXBuildFile; fileRef = E91890F4177B71E400653D7A /* tutorial.m */; }; - E94EA3E117831986001AE3DA /* threads.m in Sources */ = {isa = PBXBuildFile; fileRef = E94EA3E017831986001AE3DA /* threads.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -361,21 +360,20 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - E91890F5177B71E400653D7A /* data_type.mm in Sources */, - E91890F6177B71E400653D7A /* enumerator.m in Sources */, - E91890F7177B71E400653D7A /* err_handling.mm in Sources */, - E91890F8177B71E400653D7A /* get_subtable.m in Sources */, - E91890F9177B71E400653D7A /* group_misc_2.m in Sources */, - E91890FA177B71E400653D7A /* group.m in Sources */, - E91890FB177B71E400653D7A /* mixed.m in Sources */, E91890FC177B71E400653D7A /* query.m in Sources */, - E91890FD177B71E400653D7A /* shared_group.mm in Sources */, - E91890FE177B71E400653D7A /* subtable.m in Sources */, - E91890FF177B71E400653D7A /* table_delete_all.m in Sources */, - E9189100177B71E400653D7A /* table.m in Sources */, - E9189101177B71E400653D7A /* template.m in Sources */, - E9189102177B71E400653D7A /* tutorial.m in Sources */, - E94EA3E117831986001AE3DA /* threads.m in Sources */, + E9106BC61785E31400113590 /* data_type.mm in Sources */, + E9106BC71785E31400113590 /* enumerator.m in Sources */, + E9106BC81785E31400113590 /* err_handling.mm in Sources */, + E9106BC91785E31400113590 /* get_subtable.m in Sources */, + E9106BCA1785E31400113590 /* group_misc_2.m in Sources */, + E9106BCB1785E31400113590 /* group.m in Sources */, + E9106BCC1785E31400113590 /* mixed.m in Sources */, + E9106BCD1785E31400113590 /* shared_group.mm in Sources */, + E9106BCE1785E31400113590 /* subtable.m in Sources */, + E9106BCF1785E31400113590 /* table_delete_all.m in Sources */, + E9106BD01785E31400113590 /* table.m in Sources */, + E9106BD11785E31400113590 /* tutorial.m in Sources */, + E9106BD21785E31400113590 /* threads.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/src/tightdb/objc/helper_macros.h b/src/tightdb/objc/helper_macros.h index c1362115a0..cc7de7f0f1 100644 --- a/src/tightdb/objc/helper_macros.h +++ b/src/tightdb/objc/helper_macros.h @@ -74,7 +74,14 @@ #define TIGHTDB_COLUMN_PROXY_DEF_4_Y(name, type) @property(nonatomic, strong) TightdbColumnProxy_Subtable *name; #define TIGHTDB_COLUMN_PROXY_DEF_4_N(name, type) @property(nonatomic, strong) TightdbColumnProxy_##type *name; -#define TIGHTDB_COLUMN_PROXY_IMPL(name, type) @synthesize name = _##name; +//#define TIGHTDB_COLUMN_PROXY_IMPL(name, type) @synthesize name = _##name; + +#define TIGHTDB_COLUMN_PROXY_IMPL(name, type) TIGHTDB_COLUMN_PROXY_IMPL_2(TIGHTDB_IS_SUBTABLE(type), name, type) +#define TIGHTDB_COLUMN_PROXY_IMPL_2(is_subtable, name, type) TIGHTDB_COLUMN_PROXY_IMPL_3(is_subtable, name, type) +#define TIGHTDB_COLUMN_PROXY_IMPL_3(is_subtable, name, type) TIGHTDB_COLUMN_PROXY_IMPL_4_##is_subtable(name, type) +#define TIGHTDB_COLUMN_PROXY_IMPL_4_Y(name, type) -(TightdbColumnProxy_Subtable *)name { return _##name; } +#define TIGHTDB_COLUMN_PROXY_IMPL_4_N(name, type) -(TightdbColumnProxy_##type *)name { return _##name; } + #define TIGHTDB_COLUMN_PROXY_INIT(table, col, name, type) TIGHTDB_COLUMN_PROXY_INIT_2(TIGHTDB_IS_SUBTABLE(type), table, col, name, type) #define TIGHTDB_COLUMN_PROXY_INIT_2(is_subtable, table, col, name, type) TIGHTDB_COLUMN_PROXY_INIT_3(is_subtable, table, col, name, type) @@ -161,7 +168,7 @@ #define TIGHTDB_CURSOR_PROPERTY_DEF_SIMPLE(name, type) \ -@property TIGHTDB_TYPE_##type name; \ +@property (nonatomic) TIGHTDB_TYPE_##type name; \ -(TIGHTDB_TYPE_##type)name; \ -(void)set##name:(TIGHTDB_TYPE_##type)value; \ -(BOOL)set##name:(TIGHTDB_TYPE_##type)value error:(NSError *__autoreleasing *)error; @@ -169,26 +176,25 @@ #define TIGHTDB_CURSOR_PROPERTY_IMPL_SIMPLE(name, type) \ -(TIGHTDB_TYPE_##type)name \ { \ - return [_##name get##type]; \ + return [_acc_##name get##type]; \ } \ -(void)set##name:(TIGHTDB_TYPE_##type)value \ { \ - [_##name set##type:value]; \ + [_acc_##name set##type:value]; \ } \ -(BOOL)set##name:(TIGHTDB_TYPE_##type)value error:(NSError *__autoreleasing *)error \ { \ - return [_##name set##type:value error:error]; \ + return [_acc_##name set##type:value error:error]; \ } #define TIGHTDB_CURSOR_PROPERTY_DEF_SUBTABLE(name, type) \ -@property (readonly) type *name; \ --(type *)name; \ +@property (nonatomic, readonly) type *name; \ #define TIGHTDB_CURSOR_PROPERTY_IMPL_SUBTABLE(name, type) \ -(type *)name \ { \ - return [_##name getSubtable:[type class]]; \ + return [_acc_##name getSubtable:[type class]]; \ } \ diff --git a/src/tightdb/objc/test/query.m b/src/tightdb/objc/test/query.m index 8eb45d97a9..81ef464fee 100644 --- a/src/tightdb/objc/test/query.m +++ b/src/tightdb/objc/test/query.m @@ -10,18 +10,18 @@ #import TIGHTDB_TABLE_1(TestQuerySub, - Age, Int) + age, Int) TIGHTDB_TABLE_9(TestQueryAllTypes, - BoolCol, Bool, - IntCol, Int, - FloatCol, Float, - DoubleCol, Double, - StringCol, String, - BinaryCol, Binary, - DateCol, Date, - TableCol, TestQuerySub, - MixedCol, Mixed) + boolCol, Bool, + intCol, Int, + floatCol, Float, + doubleCol, Double, + stringCol, String, + binaryCol, Binary, + dateCol, Date, + tableCol, TestQuerySub, + mixedCol, Mixed) @interface MACtestQuery: SenTestCase @end @@ -30,113 +30,113 @@ @implementation MACtestQuery - (void)testQuery { @autoreleasepool { - TestQueryAllTypes *table = [[TestQueryAllTypes alloc] init]; - NSLog(@"Table: %@", table); - STAssertNotNil(table, @"Table is nil"); - - const char bin[4] = { 0, 1, 2, 3 }; - TightdbBinary *bin1 = [[TightdbBinary alloc] initWithData:bin size:sizeof bin / 2]; - TightdbBinary *bin2 = [[TightdbBinary alloc] initWithData:bin size:sizeof bin]; - time_t timeNow = [[NSDate date] timeIntervalSince1970]; -// TestQuerySub *subtab1 = [[TestQuerySub alloc] init]; - TestQuerySub *subtab2 = [[TestQuerySub alloc] init]; - [subtab2 addAge:100]; - TightdbMixed *mixInt1 = [TightdbMixed mixedWithInt64:1]; - TightdbMixed *mixSubtab = [TightdbMixed mixedWithTable:subtab2]; - - [table addBoolCol:NO IntCol:54 FloatCol:0.7 DoubleCol:0.8 StringCol:@"foo" - BinaryCol:bin1 DateCol:0 TableCol:nil MixedCol:mixInt1]; - - [table addBoolCol:YES IntCol:506 FloatCol:7.7 DoubleCol:8.8 StringCol:@"banach" - BinaryCol:bin2 DateCol:timeNow TableCol:subtab2 MixedCol:mixSubtab]; - - STAssertEquals([[[[table where].BoolCol equal:NO] count] unsignedLongValue], (size_t)1, @"BoolCol equal"); - STAssertEquals([[[[table where].IntCol equal:54] count] unsignedLongValue], (size_t)1, @"IntCol equal"); - STAssertEquals([[[[table where].FloatCol equal:0.7f] count] unsignedLongValue], (size_t)1, @"FloatCol equal"); - STAssertEquals([[[[table where].DoubleCol equal:0.8] count] unsignedLongValue], (size_t)1, @"DoubleCol equal"); - STAssertEquals([[[[table where].StringCol equal:@"foo"] count] unsignedLongValue], (size_t)1, @"StringCol equal"); - STAssertEquals([[[[table where].BinaryCol equal:bin1] count] unsignedLongValue], (size_t)1, @"BinaryCol equal"); - STAssertEquals([[[[table where].DateCol equal:0] count] unsignedLongValue], (size_t)1, @"DateCol equal"); -// These are not yet implemented -// STAssertEquals([[[table where].TableCol equal:subtab1] count], (size_t)1, @"TableCol equal"); -// STAssertEquals([[[table where].MixedCol equal:mixInt1] count], (size_t)1, @"MixedCol equal"); - - TestQueryAllTypes_Query *query = [[table where].BoolCol equal:NO]; - - STAssertEquals([[query.IntCol min] longLongValue], (int64_t)54, @"IntCol min"); - STAssertEquals([[query.IntCol max] longLongValue], (int64_t)54, @"IntCol max"); - STAssertEquals([[query.IntCol sum] longLongValue], (int64_t)54, @"IntCol sum"); - STAssertEquals([[query.IntCol avg] doubleValue], 54.0, @"IntCol avg"); - - STAssertEquals([[query.FloatCol min] floatValue], 0.7f, @"FloatCol min"); - STAssertEquals([[query.FloatCol max] floatValue], 0.7f, @"FloatCol max"); - STAssertEquals([[query.FloatCol sum] floatValue], 0.7f, @"FloatCol sum"); - STAssertEquals([[query.FloatCol avg] doubleValue], (double)0.7f, @"FloatCol avg"); - - STAssertEquals([[query.DoubleCol min] doubleValue], 0.8, @"DoubleCol min"); - STAssertEquals([[query.DoubleCol max] doubleValue], 0.8, @"DoubleCol max"); - STAssertEquals([[query.DoubleCol sum] doubleValue], 0.8, @"DoubleCol sum"); - STAssertEquals([[query.DoubleCol avg] doubleValue], 0.8, @"DoubleCol avg"); - - // Check that all column conditions return query objects of the - // right type - [[[table where].BoolCol equal:NO].BoolCol equal:NO]; - - [[[table where].IntCol equal:0].BoolCol equal:NO]; - [[[table where].IntCol notEqual:0].BoolCol equal:NO]; - [[[table where].IntCol less:0].BoolCol equal:NO]; - [[[table where].IntCol lessEqual:0].BoolCol equal:NO]; - [[[table where].IntCol greater:0].BoolCol equal:NO]; - [[[table where].IntCol greaterEqual:0].BoolCol equal:NO]; - [[[table where].IntCol between:0 to:0].BoolCol equal:NO]; - - [[[table where].FloatCol equal:0].BoolCol equal:NO]; - [[[table where].FloatCol notEqual:0].BoolCol equal:NO]; - [[[table where].FloatCol less:0].BoolCol equal:NO]; - [[[table where].FloatCol lessEqual:0].BoolCol equal:NO]; - [[[table where].FloatCol greater:0].BoolCol equal:NO]; - [[[table where].FloatCol greaterEqual:0].BoolCol equal:NO]; - [[[table where].FloatCol between:0 to:0].BoolCol equal:NO]; - - [[[table where].DoubleCol equal:0].BoolCol equal:NO]; - [[[table where].DoubleCol notEqual:0].BoolCol equal:NO]; - [[[table where].DoubleCol less:0].BoolCol equal:NO]; - [[[table where].DoubleCol lessEqual:0].BoolCol equal:NO]; - [[[table where].DoubleCol greater:0].BoolCol equal:NO]; - [[[table where].DoubleCol greaterEqual:0].BoolCol equal:NO]; - [[[table where].DoubleCol between:0 to:0].BoolCol equal:NO]; - - [[[table where].StringCol equal:@""].BoolCol equal:NO]; - [[[table where].StringCol equal:@"" caseSensitive:NO].BoolCol equal:NO]; - [[[table where].StringCol notEqual:@""].BoolCol equal:NO]; - [[[table where].StringCol notEqual:@"" caseSensitive:NO].BoolCol equal:NO]; - [[[table where].StringCol beginsWith:@""].BoolCol equal:NO]; - [[[table where].StringCol beginsWith:@"" caseSensitive:NO].BoolCol equal:NO]; - [[[table where].StringCol endsWith:@""].BoolCol equal:NO]; - [[[table where].StringCol endsWith:@"" caseSensitive:NO].BoolCol equal:NO]; - [[[table where].StringCol contains:@""].BoolCol equal:NO]; - [[[table where].StringCol contains:@"" caseSensitive:NO].BoolCol equal:NO]; - - [[[table where].BinaryCol equal:bin1].BoolCol equal:NO]; - [[[table where].BinaryCol notEqual:bin1].BoolCol equal:NO]; - [[[table where].BinaryCol beginsWith:bin1].BoolCol equal:NO]; - [[[table where].BinaryCol endsWith:bin1].BoolCol equal:NO]; - [[[table where].BinaryCol contains:bin1].BoolCol equal:NO]; - - [[[table where].DateCol equal:0].BoolCol equal:NO]; - [[[table where].DateCol notEqual:0].BoolCol equal:NO]; - [[[table where].DateCol less:0].BoolCol equal:NO]; - [[[table where].DateCol lessEqual:0].BoolCol equal:NO]; - [[[table where].DateCol greater:0].BoolCol equal:NO]; - [[[table where].DateCol greaterEqual:0].BoolCol equal:NO]; - [[[table where].DateCol between:0 to:0].BoolCol equal:NO]; - -// These are not yet implemented -// [[[table where].TableCol equal:nil].BoolCol equal:NO]; -// [[[table where].TableCol notEqual:nil].BoolCol equal:NO]; - -// [[[table where].MixedCol equal:mixInt1].BoolCol equal:NO]; -// [[[table where].MixedCol notEqual:mixInt1].BoolCol equal:NO]; + TestQueryAllTypes *table = [[TestQueryAllTypes alloc] init]; + NSLog(@"Table: %@", table); + STAssertNotNil(table, @"Table is nil"); + + const char bin[4] = { 0, 1, 2, 3 }; + TightdbBinary *bin1 = [[TightdbBinary alloc] initWithData:bin size:sizeof bin / 2]; + TightdbBinary *bin2 = [[TightdbBinary alloc] initWithData:bin size:sizeof bin]; + time_t timeNow = [[NSDate date] timeIntervalSince1970]; + // TestQuerySub *subtab1 = [[TestQuerySub alloc] init]; + TestQuerySub *subtab2 = [[TestQuerySub alloc] init]; + [subtab2 addage:100]; + TightdbMixed *mixInt1 = [TightdbMixed mixedWithInt64:1]; + TightdbMixed *mixSubtab = [TightdbMixed mixedWithTable:subtab2]; + + [table addboolCol:NO intCol:54 floatCol:0.7 doubleCol:0.8 stringCol:@"foo" + binaryCol:bin1 dateCol:0 tableCol:nil mixedCol:mixInt1]; + + [table addboolCol:YES intCol:506 floatCol:7.7 doubleCol:8.8 stringCol:@"banach" + binaryCol:bin2 dateCol:timeNow tableCol:subtab2 mixedCol:mixSubtab]; + + STAssertEquals([[[[table where].boolCol equal:NO] count] unsignedLongValue], (size_t)1, @"boolCol equal"); + STAssertEquals([[[[table where].intCol equal:54] count] unsignedLongValue], (size_t)1, @"intCol equal"); + STAssertEquals([[[[table where].floatCol equal:0.7f] count] unsignedLongValue], (size_t)1, @"floatCol equal"); + STAssertEquals([[[[table where].doubleCol equal:0.8] count] unsignedLongValue], (size_t)1, @"doubleCol equal"); + STAssertEquals([[[[table where].stringCol equal:@"foo"] count] unsignedLongValue], (size_t)1, @"stringCol equal"); + STAssertEquals([[[[table where].binaryCol equal:bin1] count] unsignedLongValue], (size_t)1, @"binaryCol equal"); + STAssertEquals([[[[table where].dateCol equal:0] count] unsignedLongValue], (size_t)1, @"dateCol equal"); + // These are not yet implemented + // STAssertEquals([[[table where].tableCol equal:subtab1] count], (size_t)1, @"tableCol equal"); + // STAssertEquals([[[table where].mixedCol equal:mixInt1] count], (size_t)1, @"mixedCol equal"); + + TestQueryAllTypes_Query *query = [[table where].boolCol equal:NO]; + + STAssertEquals([[query.intCol min] longLongValue], (int64_t)54, @"intCol min"); + STAssertEquals([[query.intCol max] longLongValue], (int64_t)54, @"intCol max"); + STAssertEquals([[query.intCol sum] longLongValue], (int64_t)54, @"intCol sum"); + STAssertEquals([[query.intCol avg] doubleValue], 54.0, @"intCol avg"); + + STAssertEquals([[query.floatCol min] floatValue], 0.7f, @"floatCol min"); + STAssertEquals([[query.floatCol max] floatValue], 0.7f, @"floatCol max"); + STAssertEquals([[query.floatCol sum] floatValue], 0.7f, @"floatCol sum"); + STAssertEquals([[query.floatCol avg] doubleValue], (double)0.7f, @"floatCol avg"); + + STAssertEquals([[query.doubleCol min] doubleValue], 0.8, @"doubleCol min"); + STAssertEquals([[query.doubleCol max] doubleValue], 0.8, @"doubleCol max"); + STAssertEquals([[query.doubleCol sum] doubleValue], 0.8, @"doubleCol sum"); + STAssertEquals([[query.doubleCol avg] doubleValue], 0.8, @"doubleCol avg"); + + // Check that all column conditions return query objects of the + // right type + [[[table where].boolCol equal:NO].boolCol equal:NO]; + + [[[table where].intCol equal:0].boolCol equal:NO]; + [[[table where].intCol notEqual:0].boolCol equal:NO]; + [[[table where].intCol less:0].boolCol equal:NO]; + [[[table where].intCol lessEqual:0].boolCol equal:NO]; + [[[table where].intCol greater:0].boolCol equal:NO]; + [[[table where].intCol greaterEqual:0].boolCol equal:NO]; + [[[table where].intCol between:0 to:0].boolCol equal:NO]; + + [[[table where].floatCol equal:0].boolCol equal:NO]; + [[[table where].floatCol notEqual:0].boolCol equal:NO]; + [[[table where].floatCol less:0].boolCol equal:NO]; + [[[table where].floatCol lessEqual:0].boolCol equal:NO]; + [[[table where].floatCol greater:0].boolCol equal:NO]; + [[[table where].floatCol greaterEqual:0].boolCol equal:NO]; + [[[table where].floatCol between:0 to:0].boolCol equal:NO]; + + [[[table where].doubleCol equal:0].boolCol equal:NO]; + [[[table where].doubleCol notEqual:0].boolCol equal:NO]; + [[[table where].doubleCol less:0].boolCol equal:NO]; + [[[table where].doubleCol lessEqual:0].boolCol equal:NO]; + [[[table where].doubleCol greater:0].boolCol equal:NO]; + [[[table where].doubleCol greaterEqual:0].boolCol equal:NO]; + [[[table where].doubleCol between:0 to:0].boolCol equal:NO]; + + [[[table where].stringCol equal:@""].boolCol equal:NO]; + [[[table where].stringCol equal:@"" caseSensitive:NO].boolCol equal:NO]; + [[[table where].stringCol notEqual:@""].boolCol equal:NO]; + [[[table where].stringCol notEqual:@"" caseSensitive:NO].boolCol equal:NO]; + [[[table where].stringCol beginsWith:@""].boolCol equal:NO]; + [[[table where].stringCol beginsWith:@"" caseSensitive:NO].boolCol equal:NO]; + [[[table where].stringCol endsWith:@""].boolCol equal:NO]; + [[[table where].stringCol endsWith:@"" caseSensitive:NO].boolCol equal:NO]; + [[[table where].stringCol contains:@""].boolCol equal:NO]; + [[[table where].stringCol contains:@"" caseSensitive:NO].boolCol equal:NO]; + + [[[table where].binaryCol equal:bin1].boolCol equal:NO]; + [[[table where].binaryCol notEqual:bin1].boolCol equal:NO]; + [[[table where].binaryCol beginsWith:bin1].boolCol equal:NO]; + [[[table where].binaryCol endsWith:bin1].boolCol equal:NO]; + [[[table where].binaryCol contains:bin1].boolCol equal:NO]; + + [[[table where].dateCol equal:0].boolCol equal:NO]; + [[[table where].dateCol notEqual:0].boolCol equal:NO]; + [[[table where].dateCol less:0].boolCol equal:NO]; + [[[table where].dateCol lessEqual:0].boolCol equal:NO]; + [[[table where].dateCol greater:0].boolCol equal:NO]; + [[[table where].dateCol greaterEqual:0].boolCol equal:NO]; + [[[table where].dateCol between:0 to:0].boolCol equal:NO]; + + // These are not yet implemented + // [[[table where].tableCol equal:nil].boolCol equal:NO]; + // [[[table where].tableCol notEqual:nil].boolCol equal:NO]; + + // [[[table where].mixedCol equal:mixInt1].boolCol equal:NO]; + // [[[table where].mixedCol notEqual:mixInt1].boolCol equal:NO]; } TEST_CHECK_ALLOC; } @@ -150,21 +150,21 @@ - (void)testQuery #define DATE_COL 6 #define MIXED_COL 7 -- (void) testDynamic +- (void) testDynamic { @autoreleasepool { TightdbTable *table = [[TightdbTable alloc]init]; - - [table addColumn:tightdb_Bool name:@"BoolCol"]; - [table addColumn:tightdb_Int name:@"IntCol"]; - [table addColumn:tightdb_Float name:@"FloatCol"]; - [table addColumn:tightdb_Double name:@"DoubleCol"]; - [table addColumn:tightdb_String name:@"StringCol"]; - [table addColumn:tightdb_Binary name:@"BinaryCol"]; - [table addColumn:tightdb_Date name:@"DateCol"]; - [table addColumn:tightdb_Mixed name:@"MixedCol"]; - // TODO: add Enum and Subtable when possible. - + + [table addColumn:tightdb_Bool name:@"boolCol"]; + [table addColumn:tightdb_Int name:@"intCol"]; + [table addColumn:tightdb_Float name:@"floatCol"]; + [table addColumn:tightdb_Double name:@"doubleCol"]; + [table addColumn:tightdb_String name:@"stringCol"]; + [table addColumn:tightdb_Binary name:@"binaryCol"]; + [table addColumn:tightdb_Date name:@"dateCol"]; + [table addColumn:tightdb_Mixed name:@"mixedCol"]; + // TODO: add Enum and Subtable when possible. + const char bin[4] = { 0, 1, 2, 3 }; time_t timeNow = [[NSDate date] timeIntervalSince1970]; TightdbMixed *mixInt1 = [TightdbMixed mixedWithInt64:1]; @@ -173,67 +173,67 @@ - (void) testDynamic TightdbBinary *bin2 = [[TightdbBinary alloc] initWithData:bin size:sizeof bin]; [table addRows:2]; - + [table setBool:BOOL_COL ndx:0 value:YES]; [table setBool:BOOL_COL ndx:1 value:NO]; - + [table set:INT_COL ndx:0 value:0]; [table set:INT_COL ndx:1 value:860]; - + [table setFloat:FLOAT_COL ndx:0 value:0]; [table setFloat:FLOAT_COL ndx:1 value:5.6]; - + [table setDouble:DOUBLE_COL ndx:0 value:0]; [table setDouble:DOUBLE_COL ndx:1 value:5.6]; - + [table setString:STRING_COL ndx:0 value:@""]; [table setString:STRING_COL ndx:1 value:@"foo"]; - + [table setBinary:BINARY_COL ndx:0 value:bin1]; [table setBinary:BINARY_COL ndx:1 value:bin2]; - + [table setDate:DATE_COL ndx:0 value:0]; [table setDate:DATE_COL ndx:1 value:timeNow]; - + [table setMixed:MIXED_COL ndx:0 value:mixInt1]; [table setMixed:MIXED_COL ndx:1 value:mixString]; - + // Conditions (note that count is invoked to get the number of matches) - + STAssertEquals([[[table where] betweenInt:859 to:861 colNdx:INT_COL] count], [NSNumber numberWithLongLong:1], @"betweenInt"); STAssertEquals([[[table where] betweenFloat:5.5 to:5.7 colNdx:FLOAT_COL] count], [NSNumber numberWithLongLong:1], @"betweenFloat"); STAssertEquals([[[table where] betweenDouble:5.5 to:5.7 colNdx:DOUBLE_COL] count], [NSNumber numberWithLongLong:1], @"betweenDouble"); - + STAssertEquals([[[table where] equalBool:YES colNdx:BOOL_COL] count], [NSNumber numberWithLongLong:1], @"equalBool"); STAssertEquals([[[table where] equalInt:860 colNdx:INT_COL] count], [NSNumber numberWithLongLong:1], @"equalInt"); STAssertEquals([[[table where] equalFloat:5.6 colNdx:FLOAT_COL] count], [NSNumber numberWithLongLong:1], @"equalFloat"); STAssertEquals([[[table where] equalDouble:5.6 colNdx:DOUBLE_COL] count], [NSNumber numberWithLongLong:1], @"equalDouble"); - STAssertEquals([[[table where] equalString:@"foo" colNdx:STRING_COL] count], [NSNumber numberWithLongLong:1], @"equalString"); + STAssertEquals([[[table where] equalString:@"foo" colNdx:STRING_COL] count], [NSNumber numberWithLongLong:1], @"equalString"); STAssertEquals([[[table where] equalString:@"Foo" colNdx:STRING_COL caseSensitive:NO] count], [NSNumber numberWithLongLong:1], @"equalStringCaseNo"); STAssertEquals([[[table where] equalString:@"Foo" colNdx:STRING_COL caseSensitive:YES] count], [NSNumber numberWithLongLong:0], @"equalStringCaseYes"); STAssertEquals([[[table where] equalDate:timeNow colNdx:DATE_COL] count], [NSNumber numberWithLongLong:1], @"equalDate"); STAssertEquals([[[table where] equalBinary:bin1 colNdx:BINARY_COL] count], [NSNumber numberWithLongLong:1], @"equalBinary"); - + STAssertEquals([[[table where] notEqualInt:860 colNdx:INT_COL] count], [NSNumber numberWithLongLong:1], @"notEqualInt"); STAssertEquals([[[table where] notEqualFloat:5.6 colNdx:FLOAT_COL] count], [NSNumber numberWithLongLong:1], @"notEqualFloat"); STAssertEquals([[[table where] notEqualDouble:5.6 colNdx:DOUBLE_COL] count], [NSNumber numberWithLongLong:1], @"notEqualDouble"); - STAssertEquals([[[table where] notEqualString:@"foo" colNdx:STRING_COL] count], [NSNumber numberWithLongLong:1], @"notEqualString"); + STAssertEquals([[[table where] notEqualString:@"foo" colNdx:STRING_COL] count], [NSNumber numberWithLongLong:1], @"notEqualString"); STAssertEquals([[[table where] notEqualString:@"Foo" colNdx:STRING_COL caseSensitive:NO] count], [NSNumber numberWithLongLong:1], @"notEqualStringCaseNo"); STAssertEquals([[[table where] notEqualString:@"Foo" colNdx:STRING_COL caseSensitive:YES] count], [NSNumber numberWithLongLong:2], @"notEqualStringCaseYes"); STAssertEquals([[[table where] notEqualDate:timeNow colNdx:DATE_COL] count], [NSNumber numberWithLongLong:1], @"notEqualDate"); STAssertEquals([[[table where] notEqualBinary:bin1 colNdx:BINARY_COL] count], [NSNumber numberWithLongLong:1], @"notEqualBinary"); - + STAssertEquals([[[table where] greaterInt:859 colNdx:INT_COL] count], [NSNumber numberWithLongLong:1], @"greaterInt"); STAssertEquals([[[table where] greaterFloat:5.5 colNdx:FLOAT_COL] count], [NSNumber numberWithLongLong:1], @"greaterFloat"); STAssertEquals([[[table where] greaterDouble:5.5 colNdx:DOUBLE_COL] count], [NSNumber numberWithLongLong:1], @"greaterDouble"); STAssertEquals([[[table where] greaterDate:0 colNdx:DATE_COL] count], [NSNumber numberWithLongLong:1], @"greaterDate"); - + STAssertEquals([[[table where] greaterEqualInt:860 colNdx:INT_COL] count], [NSNumber numberWithLongLong:1], @"notEqualInt"); STAssertEquals([[[table where] greaterEqualFloat:5.6 colNdx:FLOAT_COL] count], [NSNumber numberWithLongLong:1], @"notEqualFloat"); STAssertEquals([[[table where] greaterEqualDouble:5.6 colNdx:DOUBLE_COL] count], [NSNumber numberWithLongLong:1], @"notEqualDouble"); STAssertEquals([[[table where] greaterEqualDate:timeNow colNdx:DATE_COL] count], [NSNumber numberWithLongLong:1], @"notEqualDate"); - - STAssertEquals([[[table where] sumInt:INT_COL] longLongValue], (int64_t)860, @"IntCol max"); + + STAssertEquals([[[table where] sumInt:INT_COL] longLongValue], (int64_t)860, @"intCol max"); } TEST_CHECK_ALLOC; } diff --git a/src/tightdb/objc/tightdb.h b/src/tightdb/objc/tightdb.h index 4b367ff238..936a3c8158 100644 --- a/src/tightdb/objc/tightdb.h +++ b/src/tightdb/objc/tightdb.h @@ -57,13 +57,13 @@ TIGHTDB_COLUMN_PROXY_DEF(CName1, CType1) \ #define TIGHTDB_TABLE_IMPL_1(TableName, CName1, CType1) \ @implementation TableName##_Cursor \ { \ - TightdbAccessor *_##CName1; \ + TightdbAccessor *_acc_##CName1; \ } \ -(id)initWithTable:(TightdbTable *)table ndx:(size_t)ndx \ { \ self = [super initWithTable:table ndx:ndx]; \ if (self) { \ - _##CName1 = [[TightdbAccessor alloc] initWithCursor:self columnId:0]; \ + _acc_##CName1 = [[TightdbAccessor alloc] initWithCursor:self columnId:0]; \ } \ return self; \ } \ @@ -264,15 +264,15 @@ TIGHTDB_COLUMN_PROXY_DEF(CName2, CType2) \ #define TIGHTDB_TABLE_IMPL_2(TableName, CName1, CType1, CName2, CType2) \ @implementation TableName##_Cursor \ { \ - TightdbAccessor *_##CName1; \ - TightdbAccessor *_##CName2; \ + TightdbAccessor *_acc_##CName1; \ + TightdbAccessor *_acc_##CName2; \ } \ -(id)initWithTable:(TightdbTable *)table ndx:(size_t)ndx \ { \ self = [super initWithTable:table ndx:ndx]; \ if (self) { \ - _##CName1 = [[TightdbAccessor alloc] initWithCursor:self columnId:0]; \ - _##CName2 = [[TightdbAccessor alloc] initWithCursor:self columnId:1]; \ + _acc_##CName1 = [[TightdbAccessor alloc] initWithCursor:self columnId:0]; \ + _acc_##CName2 = [[TightdbAccessor alloc] initWithCursor:self columnId:1]; \ } \ return self; \ } \ @@ -488,17 +488,17 @@ TIGHTDB_COLUMN_PROXY_DEF(CName3, CType3) \ #define TIGHTDB_TABLE_IMPL_3(TableName, CName1, CType1, CName2, CType2, CName3, CType3) \ @implementation TableName##_Cursor \ { \ - TightdbAccessor *_##CName1; \ - TightdbAccessor *_##CName2; \ - TightdbAccessor *_##CName3; \ + TightdbAccessor *_acc_##CName1; \ + TightdbAccessor *_acc_##CName2; \ + TightdbAccessor *_acc_##CName3; \ } \ -(id)initWithTable:(TightdbTable *)table ndx:(size_t)ndx \ { \ self = [super initWithTable:table ndx:ndx]; \ if (self) { \ - _##CName1 = [[TightdbAccessor alloc] initWithCursor:self columnId:0]; \ - _##CName2 = [[TightdbAccessor alloc] initWithCursor:self columnId:1]; \ - _##CName3 = [[TightdbAccessor alloc] initWithCursor:self columnId:2]; \ + _acc_##CName1 = [[TightdbAccessor alloc] initWithCursor:self columnId:0]; \ + _acc_##CName2 = [[TightdbAccessor alloc] initWithCursor:self columnId:1]; \ + _acc_##CName3 = [[TightdbAccessor alloc] initWithCursor:self columnId:2]; \ } \ return self; \ } \ @@ -729,19 +729,19 @@ TIGHTDB_COLUMN_PROXY_DEF(CName4, CType4) \ #define TIGHTDB_TABLE_IMPL_4(TableName, CName1, CType1, CName2, CType2, CName3, CType3, CName4, CType4) \ @implementation TableName##_Cursor \ { \ - TightdbAccessor *_##CName1; \ - TightdbAccessor *_##CName2; \ - TightdbAccessor *_##CName3; \ - TightdbAccessor *_##CName4; \ + TightdbAccessor *_acc_##CName1; \ + TightdbAccessor *_acc_##CName2; \ + TightdbAccessor *_acc_##CName3; \ + TightdbAccessor *_acc_##CName4; \ } \ -(id)initWithTable:(TightdbTable *)table ndx:(size_t)ndx \ { \ self = [super initWithTable:table ndx:ndx]; \ if (self) { \ - _##CName1 = [[TightdbAccessor alloc] initWithCursor:self columnId:0]; \ - _##CName2 = [[TightdbAccessor alloc] initWithCursor:self columnId:1]; \ - _##CName3 = [[TightdbAccessor alloc] initWithCursor:self columnId:2]; \ - _##CName4 = [[TightdbAccessor alloc] initWithCursor:self columnId:3]; \ + _acc_##CName1 = [[TightdbAccessor alloc] initWithCursor:self columnId:0]; \ + _acc_##CName2 = [[TightdbAccessor alloc] initWithCursor:self columnId:1]; \ + _acc_##CName3 = [[TightdbAccessor alloc] initWithCursor:self columnId:2]; \ + _acc_##CName4 = [[TightdbAccessor alloc] initWithCursor:self columnId:3]; \ } \ return self; \ } \ @@ -987,21 +987,21 @@ TIGHTDB_COLUMN_PROXY_DEF(CName5, CType5) \ #define TIGHTDB_TABLE_IMPL_5(TableName, CName1, CType1, CName2, CType2, CName3, CType3, CName4, CType4, CName5, CType5) \ @implementation TableName##_Cursor \ { \ - TightdbAccessor *_##CName1; \ - TightdbAccessor *_##CName2; \ - TightdbAccessor *_##CName3; \ - TightdbAccessor *_##CName4; \ - TightdbAccessor *_##CName5; \ + TightdbAccessor *_acc_##CName1; \ + TightdbAccessor *_acc_##CName2; \ + TightdbAccessor *_acc_##CName3; \ + TightdbAccessor *_acc_##CName4; \ + TightdbAccessor *_acc_##CName5; \ } \ -(id)initWithTable:(TightdbTable *)table ndx:(size_t)ndx \ { \ self = [super initWithTable:table ndx:ndx]; \ if (self) { \ - _##CName1 = [[TightdbAccessor alloc] initWithCursor:self columnId:0]; \ - _##CName2 = [[TightdbAccessor alloc] initWithCursor:self columnId:1]; \ - _##CName3 = [[TightdbAccessor alloc] initWithCursor:self columnId:2]; \ - _##CName4 = [[TightdbAccessor alloc] initWithCursor:self columnId:3]; \ - _##CName5 = [[TightdbAccessor alloc] initWithCursor:self columnId:4]; \ + _acc_##CName1 = [[TightdbAccessor alloc] initWithCursor:self columnId:0]; \ + _acc_##CName2 = [[TightdbAccessor alloc] initWithCursor:self columnId:1]; \ + _acc_##CName3 = [[TightdbAccessor alloc] initWithCursor:self columnId:2]; \ + _acc_##CName4 = [[TightdbAccessor alloc] initWithCursor:self columnId:3]; \ + _acc_##CName5 = [[TightdbAccessor alloc] initWithCursor:self columnId:4]; \ } \ return self; \ } \ @@ -1262,23 +1262,23 @@ TIGHTDB_COLUMN_PROXY_DEF(CName6, CType6) \ #define TIGHTDB_TABLE_IMPL_6(TableName, CName1, CType1, CName2, CType2, CName3, CType3, CName4, CType4, CName5, CType5, CName6, CType6) \ @implementation TableName##_Cursor \ { \ - TightdbAccessor *_##CName1; \ - TightdbAccessor *_##CName2; \ - TightdbAccessor *_##CName3; \ - TightdbAccessor *_##CName4; \ - TightdbAccessor *_##CName5; \ - TightdbAccessor *_##CName6; \ + TightdbAccessor *_acc_##CName1; \ + TightdbAccessor *_acc_##CName2; \ + TightdbAccessor *_acc_##CName3; \ + TightdbAccessor *_acc_##CName4; \ + TightdbAccessor *_acc_##CName5; \ + TightdbAccessor *_acc_##CName6; \ } \ -(id)initWithTable:(TightdbTable *)table ndx:(size_t)ndx \ { \ self = [super initWithTable:table ndx:ndx]; \ if (self) { \ - _##CName1 = [[TightdbAccessor alloc] initWithCursor:self columnId:0]; \ - _##CName2 = [[TightdbAccessor alloc] initWithCursor:self columnId:1]; \ - _##CName3 = [[TightdbAccessor alloc] initWithCursor:self columnId:2]; \ - _##CName4 = [[TightdbAccessor alloc] initWithCursor:self columnId:3]; \ - _##CName5 = [[TightdbAccessor alloc] initWithCursor:self columnId:4]; \ - _##CName6 = [[TightdbAccessor alloc] initWithCursor:self columnId:5]; \ + _acc_##CName1 = [[TightdbAccessor alloc] initWithCursor:self columnId:0]; \ + _acc_##CName2 = [[TightdbAccessor alloc] initWithCursor:self columnId:1]; \ + _acc_##CName3 = [[TightdbAccessor alloc] initWithCursor:self columnId:2]; \ + _acc_##CName4 = [[TightdbAccessor alloc] initWithCursor:self columnId:3]; \ + _acc_##CName5 = [[TightdbAccessor alloc] initWithCursor:self columnId:4]; \ + _acc_##CName6 = [[TightdbAccessor alloc] initWithCursor:self columnId:5]; \ } \ return self; \ } \ @@ -1554,25 +1554,25 @@ TIGHTDB_COLUMN_PROXY_DEF(CName7, CType7) \ #define TIGHTDB_TABLE_IMPL_7(TableName, CName1, CType1, CName2, CType2, CName3, CType3, CName4, CType4, CName5, CType5, CName6, CType6, CName7, CType7) \ @implementation TableName##_Cursor \ { \ - TightdbAccessor *_##CName1; \ - TightdbAccessor *_##CName2; \ - TightdbAccessor *_##CName3; \ - TightdbAccessor *_##CName4; \ - TightdbAccessor *_##CName5; \ - TightdbAccessor *_##CName6; \ - TightdbAccessor *_##CName7; \ + TightdbAccessor *_acc_##CName1; \ + TightdbAccessor *_acc_##CName2; \ + TightdbAccessor *_acc_##CName3; \ + TightdbAccessor *_acc_##CName4; \ + TightdbAccessor *_acc_##CName5; \ + TightdbAccessor *_acc_##CName6; \ + TightdbAccessor *_acc_##CName7; \ } \ -(id)initWithTable:(TightdbTable *)table ndx:(size_t)ndx \ { \ self = [super initWithTable:table ndx:ndx]; \ if (self) { \ - _##CName1 = [[TightdbAccessor alloc] initWithCursor:self columnId:0]; \ - _##CName2 = [[TightdbAccessor alloc] initWithCursor:self columnId:1]; \ - _##CName3 = [[TightdbAccessor alloc] initWithCursor:self columnId:2]; \ - _##CName4 = [[TightdbAccessor alloc] initWithCursor:self columnId:3]; \ - _##CName5 = [[TightdbAccessor alloc] initWithCursor:self columnId:4]; \ - _##CName6 = [[TightdbAccessor alloc] initWithCursor:self columnId:5]; \ - _##CName7 = [[TightdbAccessor alloc] initWithCursor:self columnId:6]; \ + _acc_##CName1 = [[TightdbAccessor alloc] initWithCursor:self columnId:0]; \ + _acc_##CName2 = [[TightdbAccessor alloc] initWithCursor:self columnId:1]; \ + _acc_##CName3 = [[TightdbAccessor alloc] initWithCursor:self columnId:2]; \ + _acc_##CName4 = [[TightdbAccessor alloc] initWithCursor:self columnId:3]; \ + _acc_##CName5 = [[TightdbAccessor alloc] initWithCursor:self columnId:4]; \ + _acc_##CName6 = [[TightdbAccessor alloc] initWithCursor:self columnId:5]; \ + _acc_##CName7 = [[TightdbAccessor alloc] initWithCursor:self columnId:6]; \ } \ return self; \ } \ @@ -1863,27 +1863,27 @@ TIGHTDB_COLUMN_PROXY_DEF(CName8, CType8) \ #define TIGHTDB_TABLE_IMPL_8(TableName, CName1, CType1, CName2, CType2, CName3, CType3, CName4, CType4, CName5, CType5, CName6, CType6, CName7, CType7, CName8, CType8) \ @implementation TableName##_Cursor \ { \ - TightdbAccessor *_##CName1; \ - TightdbAccessor *_##CName2; \ - TightdbAccessor *_##CName3; \ - TightdbAccessor *_##CName4; \ - TightdbAccessor *_##CName5; \ - TightdbAccessor *_##CName6; \ - TightdbAccessor *_##CName7; \ - TightdbAccessor *_##CName8; \ + TightdbAccessor *_acc_##CName1; \ + TightdbAccessor *_acc_##CName2; \ + TightdbAccessor *_acc_##CName3; \ + TightdbAccessor *_acc_##CName4; \ + TightdbAccessor *_acc_##CName5; \ + TightdbAccessor *_acc_##CName6; \ + TightdbAccessor *_acc_##CName7; \ + TightdbAccessor *_acc_##CName8; \ } \ -(id)initWithTable:(TightdbTable *)table ndx:(size_t)ndx \ { \ self = [super initWithTable:table ndx:ndx]; \ if (self) { \ - _##CName1 = [[TightdbAccessor alloc] initWithCursor:self columnId:0]; \ - _##CName2 = [[TightdbAccessor alloc] initWithCursor:self columnId:1]; \ - _##CName3 = [[TightdbAccessor alloc] initWithCursor:self columnId:2]; \ - _##CName4 = [[TightdbAccessor alloc] initWithCursor:self columnId:3]; \ - _##CName5 = [[TightdbAccessor alloc] initWithCursor:self columnId:4]; \ - _##CName6 = [[TightdbAccessor alloc] initWithCursor:self columnId:5]; \ - _##CName7 = [[TightdbAccessor alloc] initWithCursor:self columnId:6]; \ - _##CName8 = [[TightdbAccessor alloc] initWithCursor:self columnId:7]; \ + _acc_##CName1 = [[TightdbAccessor alloc] initWithCursor:self columnId:0]; \ + _acc_##CName2 = [[TightdbAccessor alloc] initWithCursor:self columnId:1]; \ + _acc_##CName3 = [[TightdbAccessor alloc] initWithCursor:self columnId:2]; \ + _acc_##CName4 = [[TightdbAccessor alloc] initWithCursor:self columnId:3]; \ + _acc_##CName5 = [[TightdbAccessor alloc] initWithCursor:self columnId:4]; \ + _acc_##CName6 = [[TightdbAccessor alloc] initWithCursor:self columnId:5]; \ + _acc_##CName7 = [[TightdbAccessor alloc] initWithCursor:self columnId:6]; \ + _acc_##CName8 = [[TightdbAccessor alloc] initWithCursor:self columnId:7]; \ } \ return self; \ } \ @@ -2189,29 +2189,29 @@ TIGHTDB_COLUMN_PROXY_DEF(CName9, CType9) \ #define TIGHTDB_TABLE_IMPL_9(TableName, CName1, CType1, CName2, CType2, CName3, CType3, CName4, CType4, CName5, CType5, CName6, CType6, CName7, CType7, CName8, CType8, CName9, CType9) \ @implementation TableName##_Cursor \ { \ - TightdbAccessor *_##CName1; \ - TightdbAccessor *_##CName2; \ - TightdbAccessor *_##CName3; \ - TightdbAccessor *_##CName4; \ - TightdbAccessor *_##CName5; \ - TightdbAccessor *_##CName6; \ - TightdbAccessor *_##CName7; \ - TightdbAccessor *_##CName8; \ - TightdbAccessor *_##CName9; \ + TightdbAccessor *_acc_##CName1; \ + TightdbAccessor *_acc_##CName2; \ + TightdbAccessor *_acc_##CName3; \ + TightdbAccessor *_acc_##CName4; \ + TightdbAccessor *_acc_##CName5; \ + TightdbAccessor *_acc_##CName6; \ + TightdbAccessor *_acc_##CName7; \ + TightdbAccessor *_acc_##CName8; \ + TightdbAccessor *_acc_##CName9; \ } \ -(id)initWithTable:(TightdbTable *)table ndx:(size_t)ndx \ { \ self = [super initWithTable:table ndx:ndx]; \ if (self) { \ - _##CName1 = [[TightdbAccessor alloc] initWithCursor:self columnId:0]; \ - _##CName2 = [[TightdbAccessor alloc] initWithCursor:self columnId:1]; \ - _##CName3 = [[TightdbAccessor alloc] initWithCursor:self columnId:2]; \ - _##CName4 = [[TightdbAccessor alloc] initWithCursor:self columnId:3]; \ - _##CName5 = [[TightdbAccessor alloc] initWithCursor:self columnId:4]; \ - _##CName6 = [[TightdbAccessor alloc] initWithCursor:self columnId:5]; \ - _##CName7 = [[TightdbAccessor alloc] initWithCursor:self columnId:6]; \ - _##CName8 = [[TightdbAccessor alloc] initWithCursor:self columnId:7]; \ - _##CName9 = [[TightdbAccessor alloc] initWithCursor:self columnId:8]; \ + _acc_##CName1 = [[TightdbAccessor alloc] initWithCursor:self columnId:0]; \ + _acc_##CName2 = [[TightdbAccessor alloc] initWithCursor:self columnId:1]; \ + _acc_##CName3 = [[TightdbAccessor alloc] initWithCursor:self columnId:2]; \ + _acc_##CName4 = [[TightdbAccessor alloc] initWithCursor:self columnId:3]; \ + _acc_##CName5 = [[TightdbAccessor alloc] initWithCursor:self columnId:4]; \ + _acc_##CName6 = [[TightdbAccessor alloc] initWithCursor:self columnId:5]; \ + _acc_##CName7 = [[TightdbAccessor alloc] initWithCursor:self columnId:6]; \ + _acc_##CName8 = [[TightdbAccessor alloc] initWithCursor:self columnId:7]; \ + _acc_##CName9 = [[TightdbAccessor alloc] initWithCursor:self columnId:8]; \ } \ return self; \ } \ @@ -2532,31 +2532,31 @@ TIGHTDB_COLUMN_PROXY_DEF(CName10, CType10) \ #define TIGHTDB_TABLE_IMPL_10(TableName, CName1, CType1, CName2, CType2, CName3, CType3, CName4, CType4, CName5, CType5, CName6, CType6, CName7, CType7, CName8, CType8, CName9, CType9, CName10, CType10) \ @implementation TableName##_Cursor \ { \ - TightdbAccessor *_##CName1; \ - TightdbAccessor *_##CName2; \ - TightdbAccessor *_##CName3; \ - TightdbAccessor *_##CName4; \ - TightdbAccessor *_##CName5; \ - TightdbAccessor *_##CName6; \ - TightdbAccessor *_##CName7; \ - TightdbAccessor *_##CName8; \ - TightdbAccessor *_##CName9; \ - TightdbAccessor *_##CName10; \ + TightdbAccessor *_acc_##CName1; \ + TightdbAccessor *_acc_##CName2; \ + TightdbAccessor *_acc_##CName3; \ + TightdbAccessor *_acc_##CName4; \ + TightdbAccessor *_acc_##CName5; \ + TightdbAccessor *_acc_##CName6; \ + TightdbAccessor *_acc_##CName7; \ + TightdbAccessor *_acc_##CName8; \ + TightdbAccessor *_acc_##CName9; \ + TightdbAccessor *_acc_##CName10; \ } \ -(id)initWithTable:(TightdbTable *)table ndx:(size_t)ndx \ { \ self = [super initWithTable:table ndx:ndx]; \ if (self) { \ - _##CName1 = [[TightdbAccessor alloc] initWithCursor:self columnId:0]; \ - _##CName2 = [[TightdbAccessor alloc] initWithCursor:self columnId:1]; \ - _##CName3 = [[TightdbAccessor alloc] initWithCursor:self columnId:2]; \ - _##CName4 = [[TightdbAccessor alloc] initWithCursor:self columnId:3]; \ - _##CName5 = [[TightdbAccessor alloc] initWithCursor:self columnId:4]; \ - _##CName6 = [[TightdbAccessor alloc] initWithCursor:self columnId:5]; \ - _##CName7 = [[TightdbAccessor alloc] initWithCursor:self columnId:6]; \ - _##CName8 = [[TightdbAccessor alloc] initWithCursor:self columnId:7]; \ - _##CName9 = [[TightdbAccessor alloc] initWithCursor:self columnId:8]; \ - _##CName10 = [[TightdbAccessor alloc] initWithCursor:self columnId:9]; \ + _acc_##CName1 = [[TightdbAccessor alloc] initWithCursor:self columnId:0]; \ + _acc_##CName2 = [[TightdbAccessor alloc] initWithCursor:self columnId:1]; \ + _acc_##CName3 = [[TightdbAccessor alloc] initWithCursor:self columnId:2]; \ + _acc_##CName4 = [[TightdbAccessor alloc] initWithCursor:self columnId:3]; \ + _acc_##CName5 = [[TightdbAccessor alloc] initWithCursor:self columnId:4]; \ + _acc_##CName6 = [[TightdbAccessor alloc] initWithCursor:self columnId:5]; \ + _acc_##CName7 = [[TightdbAccessor alloc] initWithCursor:self columnId:6]; \ + _acc_##CName8 = [[TightdbAccessor alloc] initWithCursor:self columnId:7]; \ + _acc_##CName9 = [[TightdbAccessor alloc] initWithCursor:self columnId:8]; \ + _acc_##CName10 = [[TightdbAccessor alloc] initWithCursor:self columnId:9]; \ } \ return self; \ } \ @@ -2892,33 +2892,33 @@ TIGHTDB_COLUMN_PROXY_DEF(CName11, CType11) \ #define TIGHTDB_TABLE_IMPL_11(TableName, CName1, CType1, CName2, CType2, CName3, CType3, CName4, CType4, CName5, CType5, CName6, CType6, CName7, CType7, CName8, CType8, CName9, CType9, CName10, CType10, CName11, CType11) \ @implementation TableName##_Cursor \ { \ - TightdbAccessor *_##CName1; \ - TightdbAccessor *_##CName2; \ - TightdbAccessor *_##CName3; \ - TightdbAccessor *_##CName4; \ - TightdbAccessor *_##CName5; \ - TightdbAccessor *_##CName6; \ - TightdbAccessor *_##CName7; \ - TightdbAccessor *_##CName8; \ - TightdbAccessor *_##CName9; \ - TightdbAccessor *_##CName10; \ - TightdbAccessor *_##CName11; \ + TightdbAccessor *_acc_##CName1; \ + TightdbAccessor *_acc_##CName2; \ + TightdbAccessor *_acc_##CName3; \ + TightdbAccessor *_acc_##CName4; \ + TightdbAccessor *_acc_##CName5; \ + TightdbAccessor *_acc_##CName6; \ + TightdbAccessor *_acc_##CName7; \ + TightdbAccessor *_acc_##CName8; \ + TightdbAccessor *_acc_##CName9; \ + TightdbAccessor *_acc_##CName10; \ + TightdbAccessor *_acc_##CName11; \ } \ -(id)initWithTable:(TightdbTable *)table ndx:(size_t)ndx \ { \ self = [super initWithTable:table ndx:ndx]; \ if (self) { \ - _##CName1 = [[TightdbAccessor alloc] initWithCursor:self columnId:0]; \ - _##CName2 = [[TightdbAccessor alloc] initWithCursor:self columnId:1]; \ - _##CName3 = [[TightdbAccessor alloc] initWithCursor:self columnId:2]; \ - _##CName4 = [[TightdbAccessor alloc] initWithCursor:self columnId:3]; \ - _##CName5 = [[TightdbAccessor alloc] initWithCursor:self columnId:4]; \ - _##CName6 = [[TightdbAccessor alloc] initWithCursor:self columnId:5]; \ - _##CName7 = [[TightdbAccessor alloc] initWithCursor:self columnId:6]; \ - _##CName8 = [[TightdbAccessor alloc] initWithCursor:self columnId:7]; \ - _##CName9 = [[TightdbAccessor alloc] initWithCursor:self columnId:8]; \ - _##CName10 = [[TightdbAccessor alloc] initWithCursor:self columnId:9]; \ - _##CName11 = [[TightdbAccessor alloc] initWithCursor:self columnId:10]; \ + _acc_##CName1 = [[TightdbAccessor alloc] initWithCursor:self columnId:0]; \ + _acc_##CName2 = [[TightdbAccessor alloc] initWithCursor:self columnId:1]; \ + _acc_##CName3 = [[TightdbAccessor alloc] initWithCursor:self columnId:2]; \ + _acc_##CName4 = [[TightdbAccessor alloc] initWithCursor:self columnId:3]; \ + _acc_##CName5 = [[TightdbAccessor alloc] initWithCursor:self columnId:4]; \ + _acc_##CName6 = [[TightdbAccessor alloc] initWithCursor:self columnId:5]; \ + _acc_##CName7 = [[TightdbAccessor alloc] initWithCursor:self columnId:6]; \ + _acc_##CName8 = [[TightdbAccessor alloc] initWithCursor:self columnId:7]; \ + _acc_##CName9 = [[TightdbAccessor alloc] initWithCursor:self columnId:8]; \ + _acc_##CName10 = [[TightdbAccessor alloc] initWithCursor:self columnId:9]; \ + _acc_##CName11 = [[TightdbAccessor alloc] initWithCursor:self columnId:10]; \ } \ return self; \ } \ @@ -3269,35 +3269,35 @@ TIGHTDB_COLUMN_PROXY_DEF(CName12, CType12) \ #define TIGHTDB_TABLE_IMPL_12(TableName, CName1, CType1, CName2, CType2, CName3, CType3, CName4, CType4, CName5, CType5, CName6, CType6, CName7, CType7, CName8, CType8, CName9, CType9, CName10, CType10, CName11, CType11, CName12, CType12) \ @implementation TableName##_Cursor \ { \ - TightdbAccessor *_##CName1; \ - TightdbAccessor *_##CName2; \ - TightdbAccessor *_##CName3; \ - TightdbAccessor *_##CName4; \ - TightdbAccessor *_##CName5; \ - TightdbAccessor *_##CName6; \ - TightdbAccessor *_##CName7; \ - TightdbAccessor *_##CName8; \ - TightdbAccessor *_##CName9; \ - TightdbAccessor *_##CName10; \ - TightdbAccessor *_##CName11; \ - TightdbAccessor *_##CName12; \ + TightdbAccessor *_acc_##CName1; \ + TightdbAccessor *_acc_##CName2; \ + TightdbAccessor *_acc_##CName3; \ + TightdbAccessor *_acc_##CName4; \ + TightdbAccessor *_acc_##CName5; \ + TightdbAccessor *_acc_##CName6; \ + TightdbAccessor *_acc_##CName7; \ + TightdbAccessor *_acc_##CName8; \ + TightdbAccessor *_acc_##CName9; \ + TightdbAccessor *_acc_##CName10; \ + TightdbAccessor *_acc_##CName11; \ + TightdbAccessor *_acc_##CName12; \ } \ -(id)initWithTable:(TightdbTable *)table ndx:(size_t)ndx \ { \ self = [super initWithTable:table ndx:ndx]; \ if (self) { \ - _##CName1 = [[TightdbAccessor alloc] initWithCursor:self columnId:0]; \ - _##CName2 = [[TightdbAccessor alloc] initWithCursor:self columnId:1]; \ - _##CName3 = [[TightdbAccessor alloc] initWithCursor:self columnId:2]; \ - _##CName4 = [[TightdbAccessor alloc] initWithCursor:self columnId:3]; \ - _##CName5 = [[TightdbAccessor alloc] initWithCursor:self columnId:4]; \ - _##CName6 = [[TightdbAccessor alloc] initWithCursor:self columnId:5]; \ - _##CName7 = [[TightdbAccessor alloc] initWithCursor:self columnId:6]; \ - _##CName8 = [[TightdbAccessor alloc] initWithCursor:self columnId:7]; \ - _##CName9 = [[TightdbAccessor alloc] initWithCursor:self columnId:8]; \ - _##CName10 = [[TightdbAccessor alloc] initWithCursor:self columnId:9]; \ - _##CName11 = [[TightdbAccessor alloc] initWithCursor:self columnId:10]; \ - _##CName12 = [[TightdbAccessor alloc] initWithCursor:self columnId:11]; \ + _acc_##CName1 = [[TightdbAccessor alloc] initWithCursor:self columnId:0]; \ + _acc_##CName2 = [[TightdbAccessor alloc] initWithCursor:self columnId:1]; \ + _acc_##CName3 = [[TightdbAccessor alloc] initWithCursor:self columnId:2]; \ + _acc_##CName4 = [[TightdbAccessor alloc] initWithCursor:self columnId:3]; \ + _acc_##CName5 = [[TightdbAccessor alloc] initWithCursor:self columnId:4]; \ + _acc_##CName6 = [[TightdbAccessor alloc] initWithCursor:self columnId:5]; \ + _acc_##CName7 = [[TightdbAccessor alloc] initWithCursor:self columnId:6]; \ + _acc_##CName8 = [[TightdbAccessor alloc] initWithCursor:self columnId:7]; \ + _acc_##CName9 = [[TightdbAccessor alloc] initWithCursor:self columnId:8]; \ + _acc_##CName10 = [[TightdbAccessor alloc] initWithCursor:self columnId:9]; \ + _acc_##CName11 = [[TightdbAccessor alloc] initWithCursor:self columnId:10]; \ + _acc_##CName12 = [[TightdbAccessor alloc] initWithCursor:self columnId:11]; \ } \ return self; \ } \ @@ -3663,37 +3663,37 @@ TIGHTDB_COLUMN_PROXY_DEF(CName13, CType13) \ #define TIGHTDB_TABLE_IMPL_13(TableName, CName1, CType1, CName2, CType2, CName3, CType3, CName4, CType4, CName5, CType5, CName6, CType6, CName7, CType7, CName8, CType8, CName9, CType9, CName10, CType10, CName11, CType11, CName12, CType12, CName13, CType13) \ @implementation TableName##_Cursor \ { \ - TightdbAccessor *_##CName1; \ - TightdbAccessor *_##CName2; \ - TightdbAccessor *_##CName3; \ - TightdbAccessor *_##CName4; \ - TightdbAccessor *_##CName5; \ - TightdbAccessor *_##CName6; \ - TightdbAccessor *_##CName7; \ - TightdbAccessor *_##CName8; \ - TightdbAccessor *_##CName9; \ - TightdbAccessor *_##CName10; \ - TightdbAccessor *_##CName11; \ - TightdbAccessor *_##CName12; \ - TightdbAccessor *_##CName13; \ + TightdbAccessor *_acc_##CName1; \ + TightdbAccessor *_acc_##CName2; \ + TightdbAccessor *_acc_##CName3; \ + TightdbAccessor *_acc_##CName4; \ + TightdbAccessor *_acc_##CName5; \ + TightdbAccessor *_acc_##CName6; \ + TightdbAccessor *_acc_##CName7; \ + TightdbAccessor *_acc_##CName8; \ + TightdbAccessor *_acc_##CName9; \ + TightdbAccessor *_acc_##CName10; \ + TightdbAccessor *_acc_##CName11; \ + TightdbAccessor *_acc_##CName12; \ + TightdbAccessor *_acc_##CName13; \ } \ -(id)initWithTable:(TightdbTable *)table ndx:(size_t)ndx \ { \ self = [super initWithTable:table ndx:ndx]; \ if (self) { \ - _##CName1 = [[TightdbAccessor alloc] initWithCursor:self columnId:0]; \ - _##CName2 = [[TightdbAccessor alloc] initWithCursor:self columnId:1]; \ - _##CName3 = [[TightdbAccessor alloc] initWithCursor:self columnId:2]; \ - _##CName4 = [[TightdbAccessor alloc] initWithCursor:self columnId:3]; \ - _##CName5 = [[TightdbAccessor alloc] initWithCursor:self columnId:4]; \ - _##CName6 = [[TightdbAccessor alloc] initWithCursor:self columnId:5]; \ - _##CName7 = [[TightdbAccessor alloc] initWithCursor:self columnId:6]; \ - _##CName8 = [[TightdbAccessor alloc] initWithCursor:self columnId:7]; \ - _##CName9 = [[TightdbAccessor alloc] initWithCursor:self columnId:8]; \ - _##CName10 = [[TightdbAccessor alloc] initWithCursor:self columnId:9]; \ - _##CName11 = [[TightdbAccessor alloc] initWithCursor:self columnId:10]; \ - _##CName12 = [[TightdbAccessor alloc] initWithCursor:self columnId:11]; \ - _##CName13 = [[TightdbAccessor alloc] initWithCursor:self columnId:12]; \ + _acc_##CName1 = [[TightdbAccessor alloc] initWithCursor:self columnId:0]; \ + _acc_##CName2 = [[TightdbAccessor alloc] initWithCursor:self columnId:1]; \ + _acc_##CName3 = [[TightdbAccessor alloc] initWithCursor:self columnId:2]; \ + _acc_##CName4 = [[TightdbAccessor alloc] initWithCursor:self columnId:3]; \ + _acc_##CName5 = [[TightdbAccessor alloc] initWithCursor:self columnId:4]; \ + _acc_##CName6 = [[TightdbAccessor alloc] initWithCursor:self columnId:5]; \ + _acc_##CName7 = [[TightdbAccessor alloc] initWithCursor:self columnId:6]; \ + _acc_##CName8 = [[TightdbAccessor alloc] initWithCursor:self columnId:7]; \ + _acc_##CName9 = [[TightdbAccessor alloc] initWithCursor:self columnId:8]; \ + _acc_##CName10 = [[TightdbAccessor alloc] initWithCursor:self columnId:9]; \ + _acc_##CName11 = [[TightdbAccessor alloc] initWithCursor:self columnId:10]; \ + _acc_##CName12 = [[TightdbAccessor alloc] initWithCursor:self columnId:11]; \ + _acc_##CName13 = [[TightdbAccessor alloc] initWithCursor:self columnId:12]; \ } \ return self; \ } \ @@ -4074,39 +4074,39 @@ TIGHTDB_COLUMN_PROXY_DEF(CName14, CType14) \ #define TIGHTDB_TABLE_IMPL_14(TableName, CName1, CType1, CName2, CType2, CName3, CType3, CName4, CType4, CName5, CType5, CName6, CType6, CName7, CType7, CName8, CType8, CName9, CType9, CName10, CType10, CName11, CType11, CName12, CType12, CName13, CType13, CName14, CType14) \ @implementation TableName##_Cursor \ { \ - TightdbAccessor *_##CName1; \ - TightdbAccessor *_##CName2; \ - TightdbAccessor *_##CName3; \ - TightdbAccessor *_##CName4; \ - TightdbAccessor *_##CName5; \ - TightdbAccessor *_##CName6; \ - TightdbAccessor *_##CName7; \ - TightdbAccessor *_##CName8; \ - TightdbAccessor *_##CName9; \ - TightdbAccessor *_##CName10; \ - TightdbAccessor *_##CName11; \ - TightdbAccessor *_##CName12; \ - TightdbAccessor *_##CName13; \ - TightdbAccessor *_##CName14; \ + TightdbAccessor *_acc_##CName1; \ + TightdbAccessor *_acc_##CName2; \ + TightdbAccessor *_acc_##CName3; \ + TightdbAccessor *_acc_##CName4; \ + TightdbAccessor *_acc_##CName5; \ + TightdbAccessor *_acc_##CName6; \ + TightdbAccessor *_acc_##CName7; \ + TightdbAccessor *_acc_##CName8; \ + TightdbAccessor *_acc_##CName9; \ + TightdbAccessor *_acc_##CName10; \ + TightdbAccessor *_acc_##CName11; \ + TightdbAccessor *_acc_##CName12; \ + TightdbAccessor *_acc_##CName13; \ + TightdbAccessor *_acc_##CName14; \ } \ -(id)initWithTable:(TightdbTable *)table ndx:(size_t)ndx \ { \ self = [super initWithTable:table ndx:ndx]; \ if (self) { \ - _##CName1 = [[TightdbAccessor alloc] initWithCursor:self columnId:0]; \ - _##CName2 = [[TightdbAccessor alloc] initWithCursor:self columnId:1]; \ - _##CName3 = [[TightdbAccessor alloc] initWithCursor:self columnId:2]; \ - _##CName4 = [[TightdbAccessor alloc] initWithCursor:self columnId:3]; \ - _##CName5 = [[TightdbAccessor alloc] initWithCursor:self columnId:4]; \ - _##CName6 = [[TightdbAccessor alloc] initWithCursor:self columnId:5]; \ - _##CName7 = [[TightdbAccessor alloc] initWithCursor:self columnId:6]; \ - _##CName8 = [[TightdbAccessor alloc] initWithCursor:self columnId:7]; \ - _##CName9 = [[TightdbAccessor alloc] initWithCursor:self columnId:8]; \ - _##CName10 = [[TightdbAccessor alloc] initWithCursor:self columnId:9]; \ - _##CName11 = [[TightdbAccessor alloc] initWithCursor:self columnId:10]; \ - _##CName12 = [[TightdbAccessor alloc] initWithCursor:self columnId:11]; \ - _##CName13 = [[TightdbAccessor alloc] initWithCursor:self columnId:12]; \ - _##CName14 = [[TightdbAccessor alloc] initWithCursor:self columnId:13]; \ + _acc_##CName1 = [[TightdbAccessor alloc] initWithCursor:self columnId:0]; \ + _acc_##CName2 = [[TightdbAccessor alloc] initWithCursor:self columnId:1]; \ + _acc_##CName3 = [[TightdbAccessor alloc] initWithCursor:self columnId:2]; \ + _acc_##CName4 = [[TightdbAccessor alloc] initWithCursor:self columnId:3]; \ + _acc_##CName5 = [[TightdbAccessor alloc] initWithCursor:self columnId:4]; \ + _acc_##CName6 = [[TightdbAccessor alloc] initWithCursor:self columnId:5]; \ + _acc_##CName7 = [[TightdbAccessor alloc] initWithCursor:self columnId:6]; \ + _acc_##CName8 = [[TightdbAccessor alloc] initWithCursor:self columnId:7]; \ + _acc_##CName9 = [[TightdbAccessor alloc] initWithCursor:self columnId:8]; \ + _acc_##CName10 = [[TightdbAccessor alloc] initWithCursor:self columnId:9]; \ + _acc_##CName11 = [[TightdbAccessor alloc] initWithCursor:self columnId:10]; \ + _acc_##CName12 = [[TightdbAccessor alloc] initWithCursor:self columnId:11]; \ + _acc_##CName13 = [[TightdbAccessor alloc] initWithCursor:self columnId:12]; \ + _acc_##CName14 = [[TightdbAccessor alloc] initWithCursor:self columnId:13]; \ } \ return self; \ } \ @@ -4502,41 +4502,41 @@ TIGHTDB_COLUMN_PROXY_DEF(CName15, CType15) \ #define TIGHTDB_TABLE_IMPL_15(TableName, CName1, CType1, CName2, CType2, CName3, CType3, CName4, CType4, CName5, CType5, CName6, CType6, CName7, CType7, CName8, CType8, CName9, CType9, CName10, CType10, CName11, CType11, CName12, CType12, CName13, CType13, CName14, CType14, CName15, CType15) \ @implementation TableName##_Cursor \ { \ - TightdbAccessor *_##CName1; \ - TightdbAccessor *_##CName2; \ - TightdbAccessor *_##CName3; \ - TightdbAccessor *_##CName4; \ - TightdbAccessor *_##CName5; \ - TightdbAccessor *_##CName6; \ - TightdbAccessor *_##CName7; \ - TightdbAccessor *_##CName8; \ - TightdbAccessor *_##CName9; \ - TightdbAccessor *_##CName10; \ - TightdbAccessor *_##CName11; \ - TightdbAccessor *_##CName12; \ - TightdbAccessor *_##CName13; \ - TightdbAccessor *_##CName14; \ - TightdbAccessor *_##CName15; \ + TightdbAccessor *_acc_##CName1; \ + TightdbAccessor *_acc_##CName2; \ + TightdbAccessor *_acc_##CName3; \ + TightdbAccessor *_acc_##CName4; \ + TightdbAccessor *_acc_##CName5; \ + TightdbAccessor *_acc_##CName6; \ + TightdbAccessor *_acc_##CName7; \ + TightdbAccessor *_acc_##CName8; \ + TightdbAccessor *_acc_##CName9; \ + TightdbAccessor *_acc_##CName10; \ + TightdbAccessor *_acc_##CName11; \ + TightdbAccessor *_acc_##CName12; \ + TightdbAccessor *_acc_##CName13; \ + TightdbAccessor *_acc_##CName14; \ + TightdbAccessor *_acc_##CName15; \ } \ -(id)initWithTable:(TightdbTable *)table ndx:(size_t)ndx \ { \ self = [super initWithTable:table ndx:ndx]; \ if (self) { \ - _##CName1 = [[TightdbAccessor alloc] initWithCursor:self columnId:0]; \ - _##CName2 = [[TightdbAccessor alloc] initWithCursor:self columnId:1]; \ - _##CName3 = [[TightdbAccessor alloc] initWithCursor:self columnId:2]; \ - _##CName4 = [[TightdbAccessor alloc] initWithCursor:self columnId:3]; \ - _##CName5 = [[TightdbAccessor alloc] initWithCursor:self columnId:4]; \ - _##CName6 = [[TightdbAccessor alloc] initWithCursor:self columnId:5]; \ - _##CName7 = [[TightdbAccessor alloc] initWithCursor:self columnId:6]; \ - _##CName8 = [[TightdbAccessor alloc] initWithCursor:self columnId:7]; \ - _##CName9 = [[TightdbAccessor alloc] initWithCursor:self columnId:8]; \ - _##CName10 = [[TightdbAccessor alloc] initWithCursor:self columnId:9]; \ - _##CName11 = [[TightdbAccessor alloc] initWithCursor:self columnId:10]; \ - _##CName12 = [[TightdbAccessor alloc] initWithCursor:self columnId:11]; \ - _##CName13 = [[TightdbAccessor alloc] initWithCursor:self columnId:12]; \ - _##CName14 = [[TightdbAccessor alloc] initWithCursor:self columnId:13]; \ - _##CName15 = [[TightdbAccessor alloc] initWithCursor:self columnId:14]; \ + _acc_##CName1 = [[TightdbAccessor alloc] initWithCursor:self columnId:0]; \ + _acc_##CName2 = [[TightdbAccessor alloc] initWithCursor:self columnId:1]; \ + _acc_##CName3 = [[TightdbAccessor alloc] initWithCursor:self columnId:2]; \ + _acc_##CName4 = [[TightdbAccessor alloc] initWithCursor:self columnId:3]; \ + _acc_##CName5 = [[TightdbAccessor alloc] initWithCursor:self columnId:4]; \ + _acc_##CName6 = [[TightdbAccessor alloc] initWithCursor:self columnId:5]; \ + _acc_##CName7 = [[TightdbAccessor alloc] initWithCursor:self columnId:6]; \ + _acc_##CName8 = [[TightdbAccessor alloc] initWithCursor:self columnId:7]; \ + _acc_##CName9 = [[TightdbAccessor alloc] initWithCursor:self columnId:8]; \ + _acc_##CName10 = [[TightdbAccessor alloc] initWithCursor:self columnId:9]; \ + _acc_##CName11 = [[TightdbAccessor alloc] initWithCursor:self columnId:10]; \ + _acc_##CName12 = [[TightdbAccessor alloc] initWithCursor:self columnId:11]; \ + _acc_##CName13 = [[TightdbAccessor alloc] initWithCursor:self columnId:12]; \ + _acc_##CName14 = [[TightdbAccessor alloc] initWithCursor:self columnId:13]; \ + _acc_##CName15 = [[TightdbAccessor alloc] initWithCursor:self columnId:14]; \ } \ return self; \ } \ diff --git a/src/tightdb/objc/tightdb.h.py b/src/tightdb/objc/tightdb.h.py index 566dd75b95..bf98b33308 100644 --- a/src/tightdb/objc/tightdb.h.py +++ b/src/tightdb/objc/tightdb.h.py @@ -102,7 +102,7 @@ @implementation TableName##_Cursor \\ { \\ %for $j in range($num_cols) - TightdbAccessor *_##CName${j+1}; \\ + TightdbAccessor *_acc_##CName${j+1}; \\ %end for } \\ -(id)initWithTable:(TightdbTable *)table ndx:(size_t)ndx \\ @@ -110,7 +110,7 @@ self = [super initWithTable:table ndx:ndx]; \\ if (self) { \\ %for $j in range($num_cols) - _##CName${j+1} = [[TightdbAccessor alloc] initWithCursor:self columnId:${j}]; \\ + _acc_##CName${j+1} = [[TightdbAccessor alloc] initWithCursor:self columnId:${j}]; \\ %end for } \\ return self; \\ From 55a810b95df5788e23da52205b0a51658c97f2c1 Mon Sep 17 00:00:00 2001 From: Thomas Andersen Date: Fri, 5 Jul 2013 17:20:48 +0200 Subject: [PATCH 6/6] Added insertRowAtIndex & getRowAtIndex. Also added some more error handling. --- src/tightdb/objc/cursor.h | 7 + src/tightdb/objc/cursor_objc.mm | 43 ++++- src/tightdb/objc/table.h | 23 ++- src/tightdb/objc/table_objc.mm | 258 +++++++++++++++++++++++--- src/tightdb/objc/test/err_handling.mm | 7 + src/tightdb/objc/test/table.m | 44 ++++- src/tightdb/objc/util.hpp | 8 + 7 files changed, 346 insertions(+), 44 deletions(-) diff --git a/src/tightdb/objc/cursor.h b/src/tightdb/objc/cursor.h index b385fb5fbb..595af2972f 100644 --- a/src/tightdb/objc/cursor.h +++ b/src/tightdb/objc/cursor.h @@ -37,18 +37,23 @@ @interface TightdbAccessor: NSObject -(id)initWithCursor:(TightdbCursor *)cursor columnId:(size_t)columnId; -(BOOL)getBool; +-(NSNumber *)getBoolWithError:(NSError *__autoreleasing *)error; -(BOOL)setBool:(BOOL)value; -(BOOL)setBool:(BOOL)value error:(NSError *__autoreleasing *)error; -(int64_t)getInt; +-(NSNumber *)getIntWithError:(NSError *__autoreleasing *)error; -(BOOL)setInt:(int64_t)value; -(BOOL)setInt:(int64_t)value error:(NSError *__autoreleasing *)error; -(float)getFloat; +-(NSNumber *)getFloatWithError:(NSError *__autoreleasing *)error; -(BOOL)setFloat:(float)value; -(BOOL)setFloat:(float)value error:(NSError *__autoreleasing *)error; -(double)getDouble; +-(NSNumber *)getDoubleWithError:(NSError *__autoreleasing *)error; -(BOOL)setDouble:(double)value; -(BOOL)setDouble:(double)value error:(NSError *__autoreleasing *)error; -(NSString *)getString; +-(NSString *)getStringWithError:(NSError *__autoreleasing *)error; -(BOOL)setString:(NSString *)value; -(BOOL)setString:(NSString *)value error:(NSError *__autoreleasing *)error; -(TightdbBinary *)getBinary; @@ -57,10 +62,12 @@ -(BOOL)setBinary:(const char *)data size:(size_t)size; -(BOOL)setBinary:(const char *)data size:(size_t)size error:(NSError *__autoreleasing *)error; -(time_t)getDate; +-(NSNumber *)getDateWithError:(NSError *__autoreleasing *)error; -(BOOL)setDate:(time_t)value; -(BOOL)setDate:(time_t)value error:(NSError *__autoreleasing *)error; -(id)getSubtable:(Class)obj; -(TightdbMixed *)getMixed; +-(TightdbMixed *)getMixedWithError:(NSError *__autoreleasing *)error; -(BOOL)setMixed:(TightdbMixed *)value; -(BOOL)setMixed:(TightdbMixed *)value error:(NSError *__autoreleasing *)error; @end diff --git a/src/tightdb/objc/cursor_objc.mm b/src/tightdb/objc/cursor_objc.mm index 26d219cb7e..21b4f2eca1 100644 --- a/src/tightdb/objc/cursor_objc.mm +++ b/src/tightdb/objc/cursor_objc.mm @@ -68,10 +68,13 @@ -(id)initWithCursor:(TightdbCursor *)cursor columnId:(size_t)columnId return self; } - -(BOOL)getBool { - return [_cursor.table getBool:_columnId ndx:_cursor.ndx]; + return [[self getBoolWithError:nil] boolValue]; +} +-(NSNumber *)getBoolWithError:(NSError *__autoreleasing *)error +{ + return [_cursor.table getBool:_columnId ndx:_cursor.ndx error:error]; } -(BOOL)setBool:(BOOL)value @@ -86,7 +89,11 @@ -(BOOL)setBool:(BOOL)value error:(NSError *__autoreleasing *)error -(int64_t)getInt { - return [_cursor.table get:_columnId ndx:_cursor.ndx]; + return [[self getIntWithError:nil] longLongValue]; +} +-(NSNumber *)getIntWithError:(NSError *__autoreleasing *)error +{ + return [_cursor.table get:_columnId ndx:_cursor.ndx error:error]; } -(BOOL)setInt:(int64_t)value @@ -101,7 +108,11 @@ -(BOOL)setInt:(int64_t)value error:(NSError *__autoreleasing *)error -(float)getFloat { - return [_cursor.table getFloat:_columnId ndx:_cursor.ndx]; + return [[self getFloatWithError:nil] floatValue]; +} +-(NSNumber *)getFloatWithError:(NSError *__autoreleasing *)error +{ + return [_cursor.table getFloat:_columnId ndx:_cursor.ndx error:error]; } -(BOOL)setFloat:(float)value @@ -116,7 +127,11 @@ -(BOOL)setFloat:(float)value error:(NSError *__autoreleasing *)error -(double)getDouble { - return [_cursor.table getDouble:_columnId ndx:_cursor.ndx]; + return [[self getDoubleWithError:nil] doubleValue]; +} +-(NSNumber *)getDoubleWithError:(NSError *__autoreleasing *)error +{ + return [_cursor.table getDouble:_columnId ndx:_cursor.ndx error:error]; } -(BOOL)setDouble:(double)value @@ -131,7 +146,11 @@ -(BOOL)setDouble:(double)value error:(NSError *__autoreleasing *)error -(NSString *)getString { - return [_cursor.table getString:_columnId ndx:_cursor.ndx]; + return [self getStringWithError:nil]; +} +-(NSString *)getStringWithError:(NSError *__autoreleasing *)error +{ + return [_cursor.table getString:_columnId ndx:_cursor.ndx error:error]; } -(BOOL)setString:(NSString *)value @@ -171,7 +190,11 @@ -(BOOL)setBinary:(const char *)data size:(size_t)size error:(NSError *__autorele -(time_t)getDate { - return [_cursor.table getDate:_columnId ndx:_cursor.ndx]; + return [[self getDateWithError:nil] longLongValue]; +} +-(NSNumber *)getDateWithError:(NSError *__autoreleasing *)error +{ + return [_cursor.table getDate:_columnId ndx:_cursor.ndx error:error]; } -(BOOL)setDate:(time_t)value @@ -191,7 +214,11 @@ -(id)getSubtable:(Class)obj -(TightdbMixed *)getMixed { - return [_cursor.table getMixed:_columnId ndx:_cursor.ndx]; + return [self getMixedWithError:nil]; +} +-(TightdbMixed *)getMixedWithError:(NSError *__autoreleasing *)error +{ + return [_cursor.table getMixed:_columnId ndx:_cursor.ndx error:error]; } -(BOOL)setMixed:(TightdbMixed *)value diff --git a/src/tightdb/objc/table.h b/src/tightdb/objc/table.h index 464d3b94ac..7cbac50090 100644 --- a/src/tightdb/objc/table.h +++ b/src/tightdb/objc/table.h @@ -96,6 +96,7 @@ /// The specified table class must be one that is declared by using /// one of the table macros TIGHTDB_TABLE_*. -(TightdbTable *)getSubtable:(size_t)colNdx ndx:(size_t)ndx; +-(TightdbTable *)getSubtable:(size_t)colNdx ndx:(size_t)ndx error:(NSError *__autoreleasing *)error; -(id)getSubtable:(size_t)colNdx ndx:(size_t)ndx withClass:(Class)obj; //@} @@ -135,21 +136,28 @@ -(BOOL)removeLastWithError:(NSError *__autoreleasing *)error; // Adaptive ints. --(int64_t)get:(size_t)colNdx ndx:(size_t)ndx; +-(NSNumber *)get:(size_t)colNdx ndx:(size_t)ndx; +-(NSNumber *)get:(size_t)colNdx ndx:(size_t)ndx error:(NSError *__autoreleasing *)error; -(BOOL)set:(size_t)colNdx ndx:(size_t)ndx value:(int64_t)value; -(BOOL)set:(size_t)colNdx ndx:(size_t)ndx value:(int64_t)value error:(NSError *__autoreleasing *)error; --(BOOL)getBool:(size_t)colNdx ndx:(size_t)ndx; +-(NSNumber *)getBool:(size_t)colNdx ndx:(size_t)ndx; +-(NSNumber *)getBool:(size_t)colNdx ndx:(size_t)ndx error:(NSError *__autoreleasing *)error; -(BOOL)setBool:(size_t)colNdx ndx:(size_t)ndx value:(BOOL)value; -(BOOL)setBool:(size_t)colNdx ndx:(size_t)ndx value:(BOOL)value error:(NSError *__autoreleasing *)error; --(float)getFloat:(size_t)colNdx ndx:(size_t)ndx; +-(NSNumber *)getFloat:(size_t)colNdx ndx:(size_t)ndx; +-(NSNumber *)getFloat:(size_t)colNdx ndx:(size_t)ndx error:(NSError *__autoreleasing *)error; -(BOOL)setFloat:(size_t)colNdx ndx:(size_t)ndx value:(float)value; -(BOOL)setFloat:(size_t)colNdx ndx:(size_t)ndx value:(float)value error:(NSError *__autoreleasing *)error; --(double)getDouble:(size_t)colNdx ndx:(size_t)ndx; +-(NSNumber *)getDouble:(size_t)colNdx ndx:(size_t)ndx; +-(NSNumber *)getDouble:(size_t)colNdx ndx:(size_t)ndx error:(NSError *__autoreleasing *)error; -(BOOL)setDouble:(size_t)colNdx ndx:(size_t)ndx value:(double)value; -(BOOL)setDouble:(size_t)colNdx ndx:(size_t)ndx value:(double)value error:(NSError *__autoreleasing *)error; --(time_t)getDate:(size_t)colNdx ndx:(size_t)ndx; +-(NSNumber *)getDate:(size_t)colNdx ndx:(size_t)ndx; +-(NSNumber *)getDate:(size_t)colNdx ndx:(size_t)ndx error:(NSError *__autoreleasing *)error; -(BOOL)setDate:(size_t)colNdx ndx:(size_t)ndx value:(time_t)value; -(BOOL)setDate:(size_t)colNdx ndx:(size_t)ndx value:(time_t)value error:(NSError *__autoreleasing *)error; +-(NSArray *)getRowAtIndex:(size_t)ndx; +-(NSArray *)getRowAtIndex:(size_t)ndx error:(NSError *__autoreleasing *)error; // NOTE: Low-level insert functions. Always insert in all columns at once // and call InsertDone after to avoid table getting un-balanced. @@ -169,16 +177,20 @@ -(BOOL)insertBinary:(size_t)colNdx ndx:(size_t)ndx data:(const char *)data size:(size_t)size error:(NSError *__autoreleasing *)error; -(BOOL)insertDate:(size_t)colNdx ndx:(size_t)ndx value:(time_t)value; -(BOOL)insertDate:(size_t)colNdx ndx:(size_t)ndx value:(time_t)value error:(NSError *__autoreleasing *)error; +-(BOOL)insertRowAtIndex:(size_t)ndx, ...; +-(BOOL)insertRowAtIndex:(size_t)ndx error:(NSError *__autoreleasing *)error,...; -(BOOL)insertDone; -(BOOL)insertDoneWithError:(NSError *__autoreleasing *)error; // Strings -(NSString *)getString:(size_t)colNdx ndx:(size_t)ndx; +-(NSString *)getString:(size_t)colNdx ndx:(size_t)ndx error:(NSError *__autoreleasing *)error; -(BOOL)setString:(size_t)colNdx ndx:(size_t)ndx value:(NSString *)value; -(BOOL)setString:(size_t)colNdx ndx:(size_t)ndx value:(NSString *)value error:(NSError *__autoreleasing *)error; // Binary -(TightdbBinary *)getBinary:(size_t)colNdx ndx:(size_t)ndx; +-(TightdbBinary *)getBinary:(size_t)colNdx ndx:(size_t)ndx error:(NSError *__autoreleasing *)error; -(BOOL)setBinary:(size_t)colNdx ndx:(size_t)ndx value:(TightdbBinary *)value; -(BOOL)setBinary:(size_t)colNdx ndx:(size_t)ndx value:(TightdbBinary *)value error:(NSError *__autoreleasing *)error; -(BOOL)setBinary:(size_t)colNdx ndx:(size_t)ndx data:(const char *)data size:(size_t)size; @@ -193,6 +205,7 @@ // Mixed -(TightdbMixed *)getMixed:(size_t)colNdx ndx:(size_t)ndx; +-(TightdbMixed *)getMixed:(size_t)colNdx ndx:(size_t)ndx error:(NSError *__autoreleasing *)error; -(TightdbType)getMixedType:(size_t)colNdx ndx:(size_t)ndx; -(BOOL)insertMixed:(size_t)colNdx ndx:(size_t)ndx value:(TightdbMixed *)value; -(BOOL)insertMixed:(size_t)colNdx ndx:(size_t)ndx value:(TightdbMixed *)value error:(NSError *__autoreleasing *)error; diff --git a/src/tightdb/objc/table_objc.mm b/src/tightdb/objc/table_objc.mm index 0ca634d10e..1833269e2a 100644 --- a/src/tightdb/objc/table_objc.mm +++ b/src/tightdb/objc/table_objc.mm @@ -612,16 +612,23 @@ -(BOOL)isEqual:(TightdbTable *)other -(TightdbTable *)getSubtable:(size_t)col_ndx ndx:(size_t)ndx { - const tightdb::DataType t = _table->get_column_type(col_ndx); - if (t != tightdb::type_Table && t != tightdb::type_Mixed) return nil; - tightdb::TableRef r = _table->get_subtable(col_ndx, ndx); - if (!r) return nil; - TightdbTable *table = [[TightdbTable alloc] _initRaw]; - if (TIGHTDB_UNLIKELY(!table)) return nil; - [table setTable:move(r)]; - [table setParent:self]; - [table setReadOnly:_readOnly]; - return table; + return [self getSubtable:col_ndx ndx:ndx error:nil]; +} +-(TightdbTable *)getSubtable:(size_t)col_ndx ndx:(size_t)ndx error:(NSError *__autoreleasing *)error +{ + TIGHTDB_TABLEBOUNDS_ERRHANDLER(col_ndx, ndx, error, return nil); + TIGHTDB_EXCEPTION_ERRHANDLER( + const tightdb::DataType t = _table->get_column_type(col_ndx); + if (t != tightdb::type_Table && t != tightdb::type_Mixed) return nil; + tightdb::TableRef r = _table->get_subtable(col_ndx, ndx); + if (!r) return nil; + TightdbTable *table = [[TightdbTable alloc] _initRaw]; + if (TIGHTDB_UNLIKELY(!table)) return nil; + [table setTable:move(r)]; + [table setParent:self]; + [table setReadOnly:_readOnly]; + return table; + , @"com.tightdb.table", return nil); } // FIXME: Check that the specified class derives from TightdbTable. @@ -796,9 +803,16 @@ -(BOOL)removeLastWithError:(NSError *__autoreleasing *)error , @"com.tightdb.table", return NO); return YES; } --(int64_t)get:(size_t)col_ndx ndx:(size_t)ndx +-(NSNumber *)get:(size_t)col_ndx ndx:(size_t)ndx { - return _table->get_int(col_ndx, ndx); + return [self get:col_ndx ndx:ndx error:nil]; +} +-(NSNumber *)get:(size_t)col_ndx ndx:(size_t)ndx error:(NSError *__autoreleasing *)error +{ + TIGHTDB_TABLEBOUNDS_ERRHANDLER(col_ndx, ndx, error, return nil); + TIGHTDB_EXCEPTION_ERRHANDLER( + return [NSNumber numberWithLongLong:_table->get_int(col_ndx, ndx)]; + , @"com.tightdb.table", return nil); } -(BOOL)set:(size_t)col_ndx ndx:(size_t)ndx value:(int64_t)value @@ -819,9 +833,16 @@ -(BOOL)set:(size_t)col_ndx ndx:(size_t)ndx value:(int64_t)value error:(NSError * return YES; } --(BOOL)getBool:(size_t)col_ndx ndx:(size_t)ndx +-(NSNumber *)getBool:(size_t)col_ndx ndx:(size_t)ndx { - return _table->get_bool(col_ndx, ndx); + return [self getBool:col_ndx ndx:ndx error:nil]; +} +-(NSNumber *)getBool:(size_t)col_ndx ndx:(size_t)ndx error:(NSError *__autoreleasing *)error +{ + TIGHTDB_TABLEBOUNDS_ERRHANDLER(col_ndx, ndx, error, return nil); + TIGHTDB_EXCEPTION_ERRHANDLER( + return [NSNumber numberWithBool:_table->get_bool(col_ndx, ndx)]; + , @"com.tightdb.table", return nil); } -(BOOL)setBool:(size_t)col_ndx ndx:(size_t)ndx value:(BOOL)value @@ -842,9 +863,16 @@ -(BOOL)setBool:(size_t)col_ndx ndx:(size_t)ndx value:(BOOL)value error:(NSError return YES; } --(float)getFloat:(size_t)col_ndx ndx:(size_t)ndx +-(NSNumber *)getFloat:(size_t)col_ndx ndx:(size_t)ndx +{ + return [self getFloat:col_ndx ndx:ndx error:nil]; +} +-(NSNumber *)getFloat:(size_t)col_ndx ndx:(size_t)ndx error:(NSError *__autoreleasing *)error { - return _table->get_float(col_ndx, ndx); + TIGHTDB_TABLEBOUNDS_ERRHANDLER(col_ndx, ndx, error, return nil); + TIGHTDB_EXCEPTION_ERRHANDLER( + return [NSNumber numberWithFloat:_table->get_float(col_ndx, ndx)]; + , @"com.tightdb.table", return nil); } -(BOOL)setFloat:(size_t)col_ndx ndx:(size_t)ndx value:(float)value @@ -865,9 +893,16 @@ -(BOOL)setFloat:(size_t)col_ndx ndx:(size_t)ndx value:(float)value error:(NSErro return YES; } --(double)getDouble:(size_t)col_ndx ndx:(size_t)ndx +-(NSNumber *)getDouble:(size_t)col_ndx ndx:(size_t)ndx +{ + return [self getDouble:col_ndx ndx:ndx error:nil]; +} +-(NSNumber *)getDouble:(size_t)col_ndx ndx:(size_t)ndx error:(NSError *__autoreleasing *)error { - return _table->get_double(col_ndx, ndx); + TIGHTDB_TABLEBOUNDS_ERRHANDLER(col_ndx, ndx, error, return nil); + TIGHTDB_EXCEPTION_ERRHANDLER( + return [NSNumber numberWithDouble:_table->get_double(col_ndx, ndx)]; + , @"com.tightdb.table", return nil); } -(BOOL)setDouble:(size_t)col_ndx ndx:(size_t)ndx value:(double)value @@ -888,9 +923,16 @@ -(BOOL)setDouble:(size_t)col_ndx ndx:(size_t)ndx value:(double)value error:(NSEr return YES; } --(time_t)getDate:(size_t)col_ndx ndx:(size_t)ndx +-(NSNumber *)getDate:(size_t)col_ndx ndx:(size_t)ndx +{ + return [self getDate:col_ndx ndx:ndx error:nil]; +} +-(NSNumber *)getDate:(size_t)col_ndx ndx:(size_t)ndx error:(NSError *__autoreleasing *)error { - return _table->get_date(col_ndx, ndx).get_date(); + TIGHTDB_TABLEBOUNDS_ERRHANDLER(col_ndx, ndx, error, return nil); + TIGHTDB_EXCEPTION_ERRHANDLER( + return [NSNumber numberWithLong:_table->get_date(col_ndx, ndx).get_date()]; + , @"com.tightdb.table", return nil); } -(BOOL)setDate:(size_t)col_ndx ndx:(size_t)ndx value:(time_t)value @@ -911,6 +953,57 @@ -(BOOL)setDate:(size_t)col_ndx ndx:(size_t)ndx value:(time_t)value error:(NSErro return YES; } + + +-(NSArray *)getRowAtIndex:(size_t)ndx +{ + return [self getRowAtIndex:ndx error:nil]; +} + +-(NSArray *)getRowAtIndex:(size_t)ndx error:(NSError *__autoreleasing *)error +{ + size_t count = [self getColumnCount]; + NSMutableArray *row = [NSMutableArray arrayWithCapacity:count]; + for (size_t i = 0; i < count; ++i) { + TightdbType type = [self getColumnType:i]; + id value; + switch (type) { + case tightdb_Int: + value = [self get:i ndx:ndx error:error]; + break; + case tightdb_Float: + value = [self getFloat:i ndx:ndx error:error]; + break; + case tightdb_Double: + value = [self getDouble:i ndx:ndx error:error]; + break; + case tightdb_String: + value = [self getString:i ndx:ndx error:error]; + break; + case tightdb_Bool: + value = [self getBool:i ndx:ndx error:error]; + break; + case tightdb_Binary: + value = [self getBinary:i ndx:ndx error:error]; + break; + case tightdb_Date: + value = [self getDate:i ndx:ndx error:error]; + break; + case tightdb_Mixed: + value = [self getMixed:i ndx:ndx error:error]; + break; + case tightdb_Table: + value = [self getSubtable:i ndx:ndx error:error]; + break; + + } + if (!value) + return nil; + [row addObject:value]; + } + return row; +} + -(BOOL)insertBool:(size_t)col_ndx ndx:(size_t)ndx value:(BOOL)value { return [self insertBool:col_ndx ndx:ndx value:value error:nil]; @@ -1056,6 +1149,91 @@ -(BOOL)insertDate:(size_t)col_ndx ndx:(size_t)ndx value:(time_t)value error:(NSE return YES; } +-(BOOL)insertRowAtIndex:(size_t)ndx, ... +{ + va_list args; + va_start(args, ndx); + BOOL result = [self insertRowAtIndex:ndx error:nil, args]; + va_end(args); + return result; +} + +-(BOOL)insertRowAtIndex:(size_t)ndx error:(NSError *__autoreleasing *)error, ... +{ + if (ndx>[self count]) { + if (error) + *error = make_tightdb_error(@"com.tightdb.table", tdb_err_Bounds, [NSString stringWithFormat:@"Insert index: %zd greater than number of rows: %zd", ndx, [self count]]); + return NO; + } + va_list args; + va_start(args, error); + size_t count = [self getColumnCount]; + for (size_t i = 0; i < count; ++i) { + BOOL result = NO; + TightdbType type = [self getColumnType:i]; + switch (type) { + case tightdb_Int: + { + int64_t value = va_arg(args, int64_t); + result = [self insertInt:i ndx:ndx value:value error:error]; + break; + } + case tightdb_Float: + { + float value = va_arg(args, double); + result = [self insertFloat:i ndx:ndx value:value error:error]; + break; + } + case tightdb_Double: + { + double value = va_arg(args, double); + result = [self insertDouble:i ndx:ndx value:value error:error]; + break; + } + case tightdb_String: + { + NSString *value = va_arg(args, NSString *); + result = [self insertString:i ndx:ndx value:value error:error]; + break; + } + case tightdb_Bool: + { + BOOL value = va_arg(args, int); + result = [self insertBool:i ndx:ndx value:value error:error]; + break; + } + case tightdb_Binary: + { + TightdbBinary *value = va_arg(args, TightdbBinary *); + result = [self insertBinary:i ndx:ndx value:value error:error]; + break; + } + case tightdb_Date: + { + time_t value = va_arg(args, time_t); + result = [self insertDate:i ndx:ndx value:value error:error]; + break; + } + case tightdb_Mixed: + { + TightdbMixed *value = va_arg(args, TightdbMixed *); + result = [self insertMixed:i ndx:ndx value:value error:error]; + break; + } + case tightdb_Table: + { + if (error) + *error = make_tightdb_error(@"com.tightdb.table", tdb_err_Bounds, @"Subtable not supported in insert row"); + return NO; + } + } + if (!result) + return NO; + } + + return [self insertDoneWithError:error]; +} + -(BOOL)insertDone { return [self insertDoneWithError:nil]; @@ -1071,7 +1249,14 @@ -(BOOL)insertDoneWithError:(NSError *__autoreleasing *)error -(NSString *)getString:(size_t)col_ndx ndx:(size_t)ndx { - return to_objc_string(_table->get_string(col_ndx, ndx)); + return [self getString:col_ndx ndx:ndx error:nil]; +} +-(NSString *)getString:(size_t)col_ndx ndx:(size_t)ndx error:(NSError *__autoreleasing *)error +{ + TIGHTDB_TABLEBOUNDS_ERRHANDLER(col_ndx, ndx, error, return nil); + TIGHTDB_EXCEPTION_ERRHANDLER( + return to_objc_string(_table->get_string(col_ndx, ndx)); + , @"com.tightdb.table", return nil); } -(BOOL)setString:(size_t)col_ndx ndx:(size_t)ndx value:(NSString *)value @@ -1091,9 +1276,17 @@ -(BOOL)setString:(size_t)col_ndx ndx:(size_t)ndx value:(NSString *)value error:( return YES; } + -(TightdbBinary *)getBinary:(size_t)col_ndx ndx:(size_t)ndx { - return [[TightdbBinary alloc] initWithBinary:_table->get_binary(col_ndx, ndx)]; + return [self getBinary:col_ndx ndx:ndx error:nil]; +} +-(TightdbBinary *)getBinary:(size_t)col_ndx ndx:(size_t)ndx error:(NSError *__autoreleasing *)error +{ + TIGHTDB_TABLEBOUNDS_ERRHANDLER(col_ndx, ndx, error, return nil); + TIGHTDB_EXCEPTION_ERRHANDLER( + return [[TightdbBinary alloc] initWithBinary:_table->get_binary(col_ndx, ndx)]; + , @"com.tightdb.table", return nil); } -(BOOL)setBinary:(size_t)col_ndx ndx:(size_t)ndx value:(TightdbBinary *)value @@ -1191,14 +1384,21 @@ -(BOOL)clearSubtable:(size_t)col_ndx ndx:(size_t)row_ndx error:(NSError *__autor return YES; } --(TightdbMixed *)getMixed:(size_t)col_ndx ndx:(size_t)row_ndx +-(TightdbMixed *)getMixed:(size_t)col_ndx ndx:(size_t)ndx { - tightdb::Mixed tmp = _table->get_mixed(col_ndx, row_ndx); - TightdbMixed *mixed = [TightdbMixed mixedWithMixed:tmp]; - if ([mixed getType] == tightdb_Table) { - [mixed setTable:[self getSubtable:col_ndx ndx:row_ndx]]; - } - return mixed; + return [self getMixed:col_ndx ndx:ndx error:nil]; +} +-(TightdbMixed *)getMixed:(size_t)col_ndx ndx:(size_t)ndx error:(NSError *__autoreleasing *)error +{ + TIGHTDB_TABLEBOUNDS_ERRHANDLER(col_ndx, ndx, error, return nil); + TIGHTDB_EXCEPTION_ERRHANDLER( + tightdb::Mixed tmp = _table->get_mixed(col_ndx, ndx); + TightdbMixed *mixed = [TightdbMixed mixedWithMixed:tmp]; + if ([mixed getType] == tightdb_Table) { + [mixed setTable:[self getSubtable:col_ndx ndx:ndx error:error]]; + } + return mixed; + , @"com.tightdb.table", return nil); } -(TightdbType)getMixedType:(size_t)col_ndx ndx:(size_t)row_ndx diff --git a/src/tightdb/objc/test/err_handling.mm b/src/tightdb/objc/test/err_handling.mm index 43dab78b11..7ac6bdc33a 100644 --- a/src/tightdb/objc/test/err_handling.mm +++ b/src/tightdb/objc/test/err_handling.mm @@ -363,6 +363,7 @@ -(void)testErrorInsert - (void)testQueryErrHandling { @autoreleasepool { + NSError *error; TestQueryErrAllTypes *table = [[TestQueryErrAllTypes alloc] init]; NSLog(@"Table: %@", table); STAssertNotNil(table, @"Table is nil"); @@ -373,7 +374,13 @@ - (void)testQueryErrHandling time_t timeNow = [[NSDate date] timeIntervalSince1970]; // TestQueryErrSub *subtab1 = [[TestQueryErrSub alloc] init]; TestQueryErrSub *subtab2 = [[TestQueryErrSub alloc] init]; + if (![subtab2 insertRowAtIndex:0 error:&error, 50]) { + NSLog(@"%@", [error localizedDescription]); + STFail(@"Insert failed."); + } [subtab2 addAge:100]; + STAssertEquals([subtab2 count], size_t(2), @"subtab2 should contain 2 rows"); + TightdbMixed *mixInt1 = [TightdbMixed mixedWithInt64:1]; TightdbMixed *mixSubtab = [TightdbMixed mixedWithTable:subtab2]; diff --git a/src/tightdb/objc/test/table.m b/src/tightdb/objc/test/table.m index 84e49e9bd9..b327cb0226 100644 --- a/src/tightdb/objc/test/table.m +++ b/src/tightdb/objc/test/table.m @@ -52,9 +52,9 @@ - (void)testTable [_table set:1 ndx:ndx value:10]; // Verify - if ([_table get:0 ndx:ndx] != 0) + if ([[_table get:0 ndx:ndx] longLongValue] != 0) STFail(@"First not zero"); - if ([_table get:1 ndx:ndx] != 10) + if ([[_table get:1 ndx:ndx] longLongValue] != 10) STFail(@"Second not 10"); } TEST_CHECK_ALLOC; @@ -134,4 +134,44 @@ - (void)testDataTypes TEST_CHECK_ALLOC; } +- (void)testTableInsertMultiple +{ + @autoreleasepool { + NSError *error; + TightdbTable *_table = [[TightdbTable alloc] initWithError:&error]; + NSLog(@"Table: %@", _table); + STAssertNotNil(_table, @"Table is nil"); + + // Create columns + [_table addColumn:tightdb_Bool name:@"boolCol" error:&error]; + [_table addColumn:tightdb_Int name:@"intCol" error:&error]; + [_table addColumn:tightdb_Float name:@"floatCol" error:&error]; + [_table addColumn:tightdb_Double name:@"doubleCol" error:&error]; + [_table addColumn:tightdb_String name:@"stringCol" error:&error]; + + // Insert values. + for(int i=0;i<100;++i) { + if (![_table insertRowAtIndex:0 error:&error, YES, 10+i, 88.44f+(float)i, 909.99+ (double)i, [NSString stringWithFormat:@"Hello kitty: %d", i]]) { + NSLog(@"%@", [error localizedDescription]); + STFail(@"Insert row failed"); + } + } + + for(int i=99, row = 0;i>=0;--i, ++row) { + STAssertEquals([[_table getBool:0 ndx:row] boolValue], YES, @"Column 1 bool = YES"); + STAssertEquals([[_table get:1 ndx:row] longLongValue], (int64_t)10+i, @"Column 2 int = 10"); + STAssertEquals([[_table getFloat:2 ndx:row] floatValue], 88.44f+(float)i, @"Column 3 float = 88.44"); + STAssertEquals([[_table getDouble:3 ndx:row] doubleValue], 909.99+(double)i, @"Column 4 double = 909.99"); + NSString *str = [NSString stringWithFormat:@"Hello kitty: %d", i]; + STAssertEqualObjects([_table getString:4 ndx:row], str, @"Column 5 string = Hello kitty"); + } + + // Test out of bounds: + STAssertEquals([[_table getBool:0 ndx:100] boolValue], NO, @"Row 100 out of bounds"); + STAssertEquals([[_table getBool:5 ndx:0] boolValue], NO, @"Column 5 out of bounds"); + + } + TEST_CHECK_ALLOC; +} + @end diff --git a/src/tightdb/objc/util.hpp b/src/tightdb/objc/util.hpp index c4d898dfbb..4f40f5a590 100644 --- a/src/tightdb/objc/util.hpp +++ b/src/tightdb/objc/util.hpp @@ -52,6 +52,7 @@ enum TightdbErr { tdb_err_FailRdOnly = 2, tdb_err_FileAccess = 3, tdb_err_Resource = 4, + tdb_err_Bounds = 5, }; inline NSError *make_tightdb_error(NSString *domain, TightdbErr code, NSString *desc) @@ -82,6 +83,13 @@ catch (std::exception &ex) { \ failAction; \ } +#define TIGHTDB_TABLEBOUNDS_ERRHANDLER(column, row, errVar, failAction) \ +if (column >= [self getColumnCount] || row >= [self count]) { \ + if (errVar) \ + *errVar = make_tightdb_error(@"com.tightdb.table", tdb_err_Bounds, [NSString stringWithFormat:@"Out of bounds: %zd, %zd", column, row]); \ + failAction; \ +} + inline NSString* to_objc_string(tightdb::StringData s) {