Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Primary key support for int and string columns #868

Merged
merged 32 commits into from
Sep 9, 2014
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
37ba88b
primary keys and upsert for int and string
alazier Sep 3, 2014
bdede30
Merge branch 'master' into al-primary
alazier Sep 3, 2014
1398f73
don't allow primary properties to be changed, tests
alazier Sep 3, 2014
0d72c2d
fixes for upsert
alazier Sep 3, 2014
a414e8f
Extract duplicated code in setter creation
tgoyne Sep 4, 2014
3f97586
Merge pull request #871 from realm/tg-setter-extract
alazier Sep 4, 2014
f4dbe9d
Merge branch 'master' into al-primary
alazier Sep 4, 2014
a96f8b6
fix for hash and isEqual
alazier Sep 4, 2014
25b1c56
Merge branch 'al-primary' of https://github.com/realm/realm-objc into…
alazier Sep 4, 2014
8f93a6e
add createOrUpdate methods on RLMObject
alazier Sep 4, 2014
b84d48f
fix for swift test
alazier Sep 4, 2014
0c5e502
pr fixes
alazier Sep 4, 2014
e5d2016
fix for other swift test
alazier Sep 4, 2014
1c25a95
more swift test fixes
alazier Sep 4, 2014
f81affc
factor out code for creating or updating rows on insert
alazier Sep 4, 2014
4485852
store primary key in metadata
alazier Sep 5, 2014
7d33383
fix for updating nested objects, fix for creating object with primary…
alazier Sep 5, 2014
7487f8f
add test condition for updating objects in RLMArray properties
alazier Sep 5, 2014
4b7d8c9
comment cleanup
alazier Sep 5, 2014
491ae35
migration support for primary keys
alazier Sep 8, 2014
8cc6818
Merge branch 'al-primary' of https://github.com/realm/realm-objc into…
alazier Sep 8, 2014
1b12214
Add full support for 16, 32 and 64-bit Ints in Swift
tgoyne Aug 26, 2014
2a83952
Fix typo
tgoyne Sep 5, 2014
3f2bd6a
Eliminate a few more #ifs
tgoyne Sep 5, 2014
95e03cd
Merge pull request #876 from realm/tg-swift-int64
alazier Sep 8, 2014
bee3ec6
changelog
alazier Sep 8, 2014
ef513f0
Merge branch 'master' of https://github.com/realm/realm-objc into al-…
alazier Sep 8, 2014
9495a1d
Merge branch 'al-primary' of https://github.com/realm/realm-objc into…
alazier Sep 8, 2014
9d66782
add basic primary key/usert test for swift
alazier Sep 9, 2014
7e2a646
update changelog
alazier Sep 9, 2014
dc90399
changelog/docs
alazier Sep 9, 2014
a47719a
merge and pr fixes
alazier Sep 9, 2014
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Realm/RLMAccessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ void RLMDynamicValidatedSet(RLMObject *obj, NSString *propName, id val);
id RLMDynamicGet(RLMObject *obj, NSString *propName);

// by property/column
void RLMDynamicSet(RLMObject *obj, RLMProperty *prop, id val);
void RLMDynamicSet(RLMObject *obj, RLMProperty *prop, id val, BOOL enforceUnique);

//
// Class modification
Expand Down
155 changes: 82 additions & 73 deletions Realm/RLMAccessor.mm
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
#import "RLMProperty_Private.h"
#import "RLMArray_Private.hpp"
#import "RLMUtil.hpp"
#import "RLMObjectSchema.h"
#import "RLMObjectSchema_Private.hpp"
#import "RLMObjectStore.hpp"

#import <objc/runtime.h>
Expand Down Expand Up @@ -52,17 +52,26 @@ static inline long long RLMGetLong(__unsafe_unretained RLMObject *obj, NSUIntege
RLMVerifyAttached(obj);
return obj->_row.get_int(colIndex);
}
static inline void RLMSetLong(__unsafe_unretained RLMObject *obj, NSUInteger colIndex, long long val) {
static inline void RLMSetValue(__unsafe_unretained RLMObject *obj, NSUInteger colIndex, long long val) {
RLMVerifyInWriteTransaction(obj);
obj->_row.set_int(colIndex, val);
}
static inline void RLMSetValueUnique(__unsafe_unretained RLMObject *obj, NSUInteger colIndex, NSString *propName, long long val) {
RLMVerifyInWriteTransaction(obj);
if (obj->_row.get_table()->find_first_int(colIndex, val) != tightdb::not_found) {
NSString *reason = [NSString stringWithFormat:@"Setting primary key with existing value '%lld' for property '%@'",
val, propName];
@throw [NSException exceptionWithName:@"RLMException" reason:reason userInfo:nil];
}
obj->_row.set_int(colIndex, val);
}

// float getter/setter
static inline float RLMGetFloat(__unsafe_unretained RLMObject *obj, NSUInteger colIndex) {
RLMVerifyAttached(obj);
return obj->_row.get_float(colIndex);
}
static inline void RLMSetFloat(__unsafe_unretained RLMObject *obj, NSUInteger colIndex, float val) {
static inline void RLMSetValue(__unsafe_unretained RLMObject *obj, NSUInteger colIndex, float val) {
RLMVerifyInWriteTransaction(obj);
obj->_row.set_float(colIndex, val);
}
Expand All @@ -72,7 +81,7 @@ static inline double RLMGetDouble(__unsafe_unretained RLMObject *obj, NSUInteger
RLMVerifyAttached(obj);
return obj->_row.get_double(colIndex);
}
static inline void RLMSetDouble(__unsafe_unretained RLMObject *obj, NSUInteger colIndex, double val) {
static inline void RLMSetValue(__unsafe_unretained RLMObject *obj, NSUInteger colIndex, double val) {
RLMVerifyInWriteTransaction(obj);
obj->_row.set_double(colIndex, val);
}
Expand All @@ -82,7 +91,7 @@ static inline bool RLMGetBool(__unsafe_unretained RLMObject *obj, NSUInteger col
RLMVerifyAttached(obj);
return obj->_row.get_bool(colIndex);
}
static inline void RLMSetBool(__unsafe_unretained RLMObject *obj, NSUInteger colIndex, bool val) {
static inline void RLMSetValue(__unsafe_unretained RLMObject *obj, NSUInteger colIndex, bool val) {
RLMVerifyInWriteTransaction(obj);
obj->_row.set_bool(colIndex, val);
}
Expand All @@ -92,18 +101,29 @@ static inline void RLMSetBool(__unsafe_unretained RLMObject *obj, NSUInteger col
RLMVerifyAttached(obj);
return RLMStringDataToNSString(obj->_row.get_string(colIndex));
}
static inline void RLMSetString(__unsafe_unretained RLMObject *obj, NSUInteger colIndex, __unsafe_unretained NSString *val) {
static inline void RLMSetValue(__unsafe_unretained RLMObject *obj, NSUInteger colIndex, __unsafe_unretained NSString *val) {
RLMVerifyInWriteTransaction(obj);
obj->_row.set_string(colIndex, RLMStringDataWithNSString(val));
}
static inline void RLMSetValueUnique(__unsafe_unretained RLMObject *obj, NSUInteger colIndex, NSString *propName,
__unsafe_unretained NSString *val) {
RLMVerifyInWriteTransaction(obj);
tightdb::StringData str = RLMStringDataWithNSString(val);
if (obj->_row.get_table()->find_first_string(colIndex, str) != tightdb::not_found) {
NSString *reason = [NSString stringWithFormat:@"Setting unique property '%@' with existing value '%@'",
val, propName];
@throw [NSException exceptionWithName:@"RLMException" reason:reason userInfo:nil];
}
obj->_row.set_string(colIndex, str);
}

// date getter/setter
static inline NSDate *RLMGetDate(__unsafe_unretained RLMObject *obj, NSUInteger colIndex) {
RLMVerifyAttached(obj);
tightdb::DateTime dt = obj->_row.get_datetime(colIndex);
return [NSDate dateWithTimeIntervalSince1970:dt.get_datetime()];
}
static inline void RLMSetDate(__unsafe_unretained RLMObject *obj, NSUInteger colIndex, __unsafe_unretained NSDate *date) {
static inline void RLMSetValue(__unsafe_unretained RLMObject *obj, NSUInteger colIndex, __unsafe_unretained NSDate *date) {
RLMVerifyInWriteTransaction(obj);
std::time_t time = date.timeIntervalSince1970;
obj->_row.set_datetime(colIndex, tightdb::DateTime(time));
Expand All @@ -115,7 +135,7 @@ static inline void RLMSetDate(__unsafe_unretained RLMObject *obj, NSUInteger col
tightdb::BinaryData data = obj->_row.get_binary(colIndex);
return [NSData dataWithBytes:data.data() length:data.size()];
}
static inline void RLMSetData(__unsafe_unretained RLMObject *obj, NSUInteger colIndex, __unsafe_unretained NSData *data) {
static inline void RLMSetValue(__unsafe_unretained RLMObject *obj, NSUInteger colIndex, __unsafe_unretained NSData *data) {
RLMVerifyInWriteTransaction(obj);
obj->_row.set_binary(colIndex, RLMBinaryDataForNSData(data));
}
Expand All @@ -130,10 +150,10 @@ static inline void RLMSetData(__unsafe_unretained RLMObject *obj, NSUInteger col
NSUInteger index = obj->_row.get_link(colIndex);
return RLMCreateObjectAccessor(obj.realm, objectClassName, index);
}
static inline void RLMSetLink(__unsafe_unretained RLMObject *obj, NSUInteger colIndex, __unsafe_unretained id val) {
static inline void RLMSetValue(__unsafe_unretained RLMObject *obj, NSUInteger colIndex, __unsafe_unretained RLMObject *val) {
RLMVerifyInWriteTransaction(obj);

if (!val || val == NSNull.null) {
if (!val || (id)val == NSNull.null) {
// if null
obj->_row.nullify_link(colIndex);
}
Expand All @@ -158,7 +178,7 @@ static inline void RLMSetLink(__unsafe_unretained RLMObject *obj, NSUInteger col
realm:obj.realm];
return ar;
}
static inline void RLMSetArray(__unsafe_unretained RLMObject *obj, NSUInteger colIndex, __unsafe_unretained id<NSFastEnumeration> val) {
static inline void RLMSetValue(__unsafe_unretained RLMObject *obj, NSUInteger colIndex, __unsafe_unretained id<NSFastEnumeration> val) {
RLMVerifyInWriteTransaction(obj);

tightdb::LinkViewRef linkView = obj->_row.get_linklist(colIndex);
Expand Down Expand Up @@ -209,7 +229,7 @@ static inline id RLMGetAnyProperty(__unsafe_unretained RLMObject *obj, NSUIntege
}
}
}
static inline void RLMSetAnyProperty(__unsafe_unretained RLMObject *obj, NSUInteger col_ndx, __unsafe_unretained id val) {
static inline void RLMSetValue(__unsafe_unretained RLMObject *obj, NSUInteger col_ndx, __unsafe_unretained id val) {
RLMVerifyInWriteTransaction(obj);

// FIXME - enable when Any supports links
Expand Down Expand Up @@ -306,58 +326,36 @@ static IMP RLMAccessorGetter(RLMProperty *prop, char accessorCode, NSString *obj
}
}

template<typename ArgType, typename StorageType=ArgType>
static IMP RLMMakeSetter(NSUInteger colIndex, bool isPrimary) {
if (isPrimary) {
return imp_implementationWithBlock(^(__unused RLMObject *obj, __unused ArgType val) {
@throw [NSException exceptionWithName:@"RLMException"
reason:@"Primary key can't be changed after an object is inserted."
userInfo:nil];
});
}
return imp_implementationWithBlock(^(RLMObject *obj, ArgType val) {
RLMSetValue(obj, colIndex, static_cast<StorageType>(val));
});
}

// dynamic setter with column closure
static IMP RLMAccessorSetter(RLMProperty *prop, char accessorCode) {
NSUInteger colIndex = prop.column;
switch (accessorCode) {
case 'i':
return imp_implementationWithBlock(^(RLMObject *obj, int val) {
RLMSetLong(obj, colIndex, val);
});
case 'l':
return imp_implementationWithBlock(^(RLMObject *obj, long val) {
RLMSetLong(obj, colIndex, val);
});
case 'f':
return imp_implementationWithBlock(^(RLMObject *obj, float val) {
RLMSetFloat(obj, colIndex, val);
});
case 'd':
return imp_implementationWithBlock(^(RLMObject *obj, double val) {
RLMSetDouble(obj, colIndex, val);
});
case 'B':
return imp_implementationWithBlock(^(RLMObject *obj, bool val) {
RLMSetBool(obj, colIndex, val);
});
case 'c':
return imp_implementationWithBlock(^(RLMObject *obj, BOOL val) {
RLMSetBool(obj, colIndex, val);
});
case 's':
return imp_implementationWithBlock(^(RLMObject *obj, NSString *val) {
RLMSetString(obj, colIndex, val);
});
case 'a':
return imp_implementationWithBlock(^(RLMObject *obj, NSDate *date) {
RLMSetDate(obj, colIndex, date);
});
case 'e':
return imp_implementationWithBlock(^(RLMObject *obj, NSData *data) {
RLMSetData(obj, colIndex, data);
});
case 'k':
return imp_implementationWithBlock(^(RLMObject *obj, RLMObject *link) {
RLMSetLink(obj, colIndex, link);
});
case 't':
return imp_implementationWithBlock(^(RLMObject *obj, RLMArray *val) {
RLMSetArray(obj, colIndex, val);
});
case '@':
return imp_implementationWithBlock(^(RLMObject *obj, id val) {
RLMSetAnyProperty(obj, colIndex, val);
});
case 'i': return RLMMakeSetter<int, long long>(colIndex, prop.isPrimary);
case 'l': return RLMMakeSetter<long, long long>(colIndex, prop.isPrimary);
case 'f': return RLMMakeSetter<float>(colIndex, prop.isPrimary);
case 'd': return RLMMakeSetter<double>(colIndex, prop.isPrimary);
case 'B': return RLMMakeSetter<bool>(colIndex, prop.isPrimary);
case 'c': return RLMMakeSetter<BOOL, bool>(colIndex, prop.isPrimary);
case 's': return RLMMakeSetter<NSString *>(colIndex, prop.isPrimary);
case 'a': return RLMMakeSetter<NSDate *>(colIndex, prop.isPrimary);
case 'e': return RLMMakeSetter<NSData *>(colIndex, prop.isPrimary);
case 'k': return RLMMakeSetter<RLMObject *>(colIndex, prop.isPrimary);
case 't': return RLMMakeSetter<RLMArray *>(colIndex, prop.isPrimary);
case '@': return RLMMakeSetter<id>(colIndex, prop.isPrimary);
default:
@throw [NSException exceptionWithName:@"RLMException"
reason:@"Invalid accessor code"
Expand Down Expand Up @@ -559,7 +557,8 @@ Class RLMStandaloneAccessorClassForObjectClass(Class objectClass, RLMObjectSchem
}

void RLMDynamicValidatedSet(RLMObject *obj, NSString *propName, id val) {
RLMProperty *prop = obj.objectSchema[propName];
RLMObjectSchema *schema = obj.objectSchema;
RLMProperty *prop = schema[propName];
if (!prop) {
@throw [NSException exceptionWithName:@"RLMException"
reason:@"Invalid property name"
Expand All @@ -572,43 +571,53 @@ void RLMDynamicValidatedSet(RLMObject *obj, NSString *propName, id val) {
userInfo:@{@"Property name:" : propName ?: @"nil",
@"Value": val ? [val description] : @"nil"}];
}
RLMDynamicSet(obj, (RLMProperty *)prop, val);
RLMDynamicSet(obj, (RLMProperty *)prop, val, prop.isPrimary);
}

void RLMDynamicSet(__unsafe_unretained RLMObject *obj, __unsafe_unretained RLMProperty *prop, __unsafe_unretained id val) {
void RLMDynamicSet(__unsafe_unretained RLMObject *obj, __unsafe_unretained RLMProperty *prop, __unsafe_unretained id val, BOOL enforceUnique) {
NSUInteger col = prop.column;
switch (accessorCodeForType(prop.objcType, prop.type)) {
case 'i':
case 'l':
RLMSetLong(obj, col, [val longLongValue]);
if (enforceUnique) {
RLMSetValueUnique(obj, col, prop.name, [val longLongValue]);
}
else {
RLMSetValue(obj, col, [val longLongValue]);
}
break;
case 'f':
RLMSetFloat(obj, col, [val floatValue]);
RLMSetValue(obj, col, [val floatValue]);
break;
case 'd':
RLMSetDouble(obj, col, [val doubleValue]);
RLMSetValue(obj, col, [val doubleValue]);
break;
case 'B':
case 'c':
RLMSetBool(obj, col, (bool)[val boolValue]);
RLMSetValue(obj, col, (bool)[val boolValue]);
break;
case 's':
RLMSetString(obj, col, val);
if (enforceUnique) {
RLMSetValueUnique(obj, col, prop.name, (NSString *)val);
}
else {
RLMSetValue(obj, col, (NSString *)val);
}
break;
case 'a':
RLMSetDate(obj, col, val);
RLMSetValue(obj, col, (NSDate *)val);
break;
case 'e':
RLMSetData(obj, col, val);
RLMSetValue(obj, col, (NSData *)val);
break;
case 'k':
RLMSetLink(obj, col, val);
RLMSetValue(obj, col, (RLMObject *)val);
break;
case 't':
RLMSetArray(obj, col, val);
RLMSetValue(obj, col, (RLMArray *)val);
break;
case '@':
RLMSetAnyProperty(obj, col, val);
RLMSetValue(obj, col, val);
break;
default:
@throw [NSException exceptionWithName:@"RLMException"
Expand Down
9 changes: 8 additions & 1 deletion Realm/RLMArray.mm
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,14 @@ - (void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject {

- (NSUInteger)indexOfObject:(RLMObject *)object {
RLMValidateMatchingObjectType(self, object);
return [_backingArray indexOfObject:object];
NSUInteger index = 0;
for (RLMObject *cmp in _backingArray) {
if ([object isEqualToObject:cmp]) {
return index;
}
index++;
}
return NSNotFound;
}

- (void)deleteObjectsFromRealm {
Expand Down
2 changes: 1 addition & 1 deletion Realm/RLMConstants.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
Attributes which can be returned when implementing attributesForProperty:
*/

typedef NS_ENUM(NSUInteger, RLMPropertyAttributes) {
typedef NS_OPTIONS(NSUInteger, RLMPropertyAttributes) {
/**
Create an index for this property for improved search performance.
*/
Expand Down
Loading