Skip to content

Commit 49c5912

Browse files
authored
Upgrade to core 14 (#8496)
1 parent 33a1eee commit 49c5912

18 files changed

+326
-187
lines changed

CHANGELOG.md

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,66 @@
1+
x.y.z Release notes (yyyy-MM-dd)
2+
=============================================================
3+
4+
This version introduces a new Realm file format version (v24). Opening existing
5+
Realm files will automatically upgrade the files, making them unable to be
6+
opened by older versions. This upgrade process should typically be very fast
7+
unless you have large Sets of AnyRealmValue, String, or Data, which have to be rewritten.
8+
9+
A backup will automatically be created next to the Realm before performing the
10+
upgrade. Downgrading to older versions of Realm will attempt to automatically
11+
restore the backup, or it will be deleted after three months.
12+
13+
### Enhancements
14+
* Storage of Decimal128 properties has been optimised similarly to Int
15+
properties so that the individual values will take up 0 bits (if all nulls),
16+
32 bits, 64 bits or 128 bits depending on what is needed.
17+
([Core #6111](https://github.com/realm/realm-core/pull/6111))
18+
* Improve file compaction performance on arm64 platforms for encrypted files
19+
between 16kB and 4MB in size. ([PR #7492](https://github.com/realm/realm-core/pull/7492)).
20+
21+
### Fixed
22+
* Sorting on binary Data was done by comparing bytes as signed char rather than
23+
unsigned char, resulting in very strange orders (since sorting on Data was
24+
enabled in v6.0.4)
25+
* Sorting on AnyRealmValue did not use a valid total ordering, and certain
26+
combinations of values could result in values not being sorted or potentially
27+
even crashes. The resolution for this will result in some previously-valid
28+
combinations of values of different types being sorted in different orders
29+
than previously (since the introduction of AnyRealmValue in 10.8.0).
30+
* RLMSet/MutableSet was inconsistent about if it considered a String and a Data
31+
containing the utf-8 encoded bytes of that String to be equivalent. They are
32+
now always considered distinct. (since the introduction of sets in v10.8.0).
33+
* Equality queries on a Mixed property with an index could sometimes return
34+
incorrect results if values of different types happened to have the same hash
35+
code. ([Core 6407](https://github.com/realm/realm-core/issues/6407) since v10.8.0).
36+
* Creating more than 8388606 links pointing to a single object would crash.
37+
([Core #6577](https://github.com/realm/realm-core/issues/6577), since v5.0.0)
38+
* A Realm generated on a non-apple ARM 64 device and copied to another platform
39+
(and vice-versa) were non-portable due to a sorting order difference. This
40+
impacts strings or binaries that have their first difference at a non-ascii
41+
character. These items may not be found in a set, or in an indexed column if
42+
the strings had a long common prefix (> 200 characters).
43+
([Core #6670](https://github.com/realm/realm-core/pull/6670), since 2.0.0 for indexes, and since since the introduction of sets in v10.8.0)
44+
* Fix a spurious crash related to opening a Realm on background thread while
45+
the process was in the middle of exiting ([Core #7420](https://github.com/realm/realm-core/pull/7420)).
46+
* Opening a Realm with a cached user while offline would fail to retry some
47+
steps of the connection process and instead report a fatal error.
48+
([#7349](https://github.com/realm/realm-core/issues/7349), since v10.46.0)
49+
50+
### Breaking Changes
51+
* Drop support for opening pre-v5.0.0 Realm files.
52+
53+
### Compatibility
54+
* Realm Studio: 14.0.1 or later.
55+
* APIs are backwards compatible with all previous releases in the 10.x.y series.
56+
* Carthage release for Swift is built with Xcode 15.3.0.
57+
* CocoaPods: 1.10 or later.
58+
* Xcode: 14.2-15.3.0. Note that we will be dropping support for Xcode 14 when
59+
Apple begins requiring Xcode 15 for app store submissions on April 29.
60+
61+
### Internal
62+
* Upgraded realm-core from 13.26.0 to 14.3.0
63+
164
10.48.1 Release notes (2024-03-15)
265
=============================================================
366

Package.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import PackageDescription
44
import Foundation
55

6-
let coreVersion = Version("13.26.0")
6+
let coreVersion = Version("14.3.0")
77
let cocoaVersion = Version("10.48.1")
88

99
let cxxSettings: [CXXSetting] = [

Realm/ObjectServerTests/RLMSyncTestCase.mm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -705,7 +705,7 @@ - (RLMMongoCollection *)collectionForType:(Class)type app:(RLMApp *)app {
705705
@end
706706

707707
int64_t RLMGetClientFileIdent(RLMRealm *realm) {
708-
return realm::SyncSession::OnlyForTesting::get_file_ident(*realm->_realm->sync_session()).ident;
708+
return realm->_realm->sync_session()->get_file_ident().ident;
709709
}
710710

711711
#endif // TARGET_OS_OSX

Realm/RLMBSON_Private.hpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,7 @@
2121

2222
namespace realm::bson {
2323
class Bson;
24-
template <typename> class IndexedMap;
25-
using BsonDocument = IndexedMap<Bson>;
24+
class BsonDocument;
2625
}
2726

2827
realm::bson::Bson RLMConvertRLMBSONToBson(id<RLMBSON> b);

Realm/RLMLogger.mm

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,15 +75,15 @@ static RLMLogLevel logLevelForLevel(Level logLevel) {
7575
}
7676

7777
struct CocoaLogger : public Logger {
78-
void do_log(Level level, const std::string& message) override {
78+
void do_log(const realm::util::LogCategory&, Level level, const std::string& message) override {
7979
NSLog(@"%@: %@", levelPrefix(level), RLMStringDataToNSString(message));
8080
}
8181
};
8282

8383
class CustomLogger : public Logger {
8484
public:
8585
RLMLoggerFunction function;
86-
void do_log(Level level, const std::string& message) override {
86+
void do_log(const realm::util::LogCategory&, Level level, const std::string& message) override {
8787
@autoreleasepool {
8888
if (function) {
8989
function(logLevelForLevel(level), RLMStringDataToNSString(message));

Realm/RLMMongoCollection.mm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ - (void)insertOneDocument:(NSDictionary<NSString *, id<RLMBSON>> *)document
188188
- (void)insertManyDocuments:(NSArray<NSDictionary<NSString *, id<RLMBSON>> *> *)documents
189189
completion:(RLMMongoInsertManyBlock)completion {
190190
self.collection.insert_many(toBsonArray(documents),
191-
[completion](std::vector<realm::bson::Bson> insertedIds,
191+
[completion](realm::bson::BsonArray insertedIds,
192192
std::optional<realm::app::AppError> error) {
193193
if (error) {
194194
return completion(nil, makeError(*error));

Realm/RLMObservation.mm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,7 @@ void RLMClearTable(RLMClassInfo &objectSchema) {
374374
}
375375

376376
NSString *name = observer->columnName(link.origin_col_key);
377-
if (observer->getRow().get_table()->get_column_type(link.origin_col_key) != type_LinkList) {
377+
if (!link.origin_col_key.is_list()) {
378378
_changes.push_back({observer, name});
379379
continue;
380380
}

Realm/RLMQueryUtil.mm

Lines changed: 64 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -684,32 +684,30 @@ Query make_diacritic_insensitive_constraint(NSPredicateOperatorType operatorType
684684
}
685685
}
686686

687+
// static_assert is always evaluated even if it's inside a if constexpr
688+
// unless the value is derived from the template argument, in which case it's
689+
// only evaluated if that branch is active
690+
template <typename> struct AlwaysFalse : std::false_type {};
691+
687692
template <typename C, typename T>
688-
void QueryBuilder::do_add_diacritic_sensitive_string_constraint(NSPredicateOperatorType operatorType,
689-
NSComparisonPredicateOptions predicateOptions,
690-
C&& column, T&& value) {
691-
bool caseSensitive = !(predicateOptions & NSCaseInsensitivePredicateOption);
693+
Query make_diacritic_sensitive_constraint(NSPredicateOperatorType operatorType,
694+
bool caseSensitive, C& column, T const& value)
695+
{
692696
switch (operatorType) {
693697
case NSBeginsWithPredicateOperatorType:
694-
add_substring_constraint(value, column.begins_with(value, caseSensitive));
695-
break;
698+
return column.begins_with(value, caseSensitive);
696699
case NSEndsWithPredicateOperatorType:
697-
add_substring_constraint(value, column.ends_with(value, caseSensitive));
698-
break;
700+
return column.ends_with(value, caseSensitive);
699701
case NSContainsPredicateOperatorType:
700-
add_substring_constraint(value, column.contains(value, caseSensitive));
701-
break;
702+
return column.contains(value, caseSensitive);
702703
case NSEqualToPredicateOperatorType:
703-
m_query.and_query(column.equal(value, caseSensitive));
704-
break;
704+
return column.equal(value, caseSensitive);
705705
case NSNotEqualToPredicateOperatorType:
706-
m_query.and_query(column.not_equal(value, caseSensitive));
707-
break;
706+
return column.not_equal(value, caseSensitive);
708707
case NSLikePredicateOperatorType:
709-
m_query.and_query(column.like(value, caseSensitive));
710-
break;
708+
return column.like(value, caseSensitive);
711709
default: {
712-
if constexpr (is_any_v<C, Columns<String>, Columns<Lst<String>>, Columns<Set<String>>>) {
710+
if constexpr (is_any_v<C, Columns<String>, Columns<Lst<String>>, Columns<Set<String>>, ColumnDictionaryKeys>) {
713711
unsupportedOperator(RLMPropertyTypeString, operatorType);
714712
}
715713
else if constexpr (is_any_v<C, Columns<Binary>, Columns<Lst<Binary>>, Columns<Set<Binary>>>) {
@@ -726,10 +724,56 @@ Query make_diacritic_insensitive_constraint(NSPredicateOperatorType operatorType
726724
@"Operator '%@' not supported for string queries on Dictionary.",
727725
operatorName(operatorType));
728726
}
727+
else {
728+
static_assert(AlwaysFalse<C>::value, "unsupported column type");
729+
}
729730
}
730731
}
731732
}
732733

734+
template <typename C, typename T>
735+
void QueryBuilder::do_add_diacritic_sensitive_string_constraint(NSPredicateOperatorType operatorType,
736+
NSComparisonPredicateOptions predicateOptions,
737+
C&& column, T&& value) {
738+
bool caseSensitive = !(predicateOptions & NSCaseInsensitivePredicateOption);
739+
Query condition = make_diacritic_sensitive_constraint(operatorType, caseSensitive, column, value);
740+
741+
// Queries on Mixed used to coerce Strings to Binary and vice-versa. Core
742+
// no longer does this, but we can maintain compatibility by doing the
743+
// coercion and checking both
744+
// NEXT-MAJOR: we should remove this and realign with core's behavior
745+
if constexpr (is_any_v<C, Columns<Mixed>, Columns<Lst<Mixed>>, Columns<Set<Mixed>>, Columns<Dictionary>>) {
746+
Mixed m = value;
747+
if (!m.is_null()) {
748+
if (m.get_type() == type_String) {
749+
m = m.export_to_type<BinaryData>();
750+
}
751+
else {
752+
m = m.export_to_type<StringData>();
753+
}
754+
755+
// Equality and substring operations need (col == strValue OR col == binValue),
756+
// but not equals needs (col != strValue AND col != binValue)
757+
if (operatorType != NSNotEqualToPredicateOperatorType) {
758+
condition.Or();
759+
}
760+
761+
condition.and_query(make_diacritic_sensitive_constraint(operatorType, caseSensitive, column, m));
762+
}
763+
}
764+
switch (operatorType) {
765+
case NSBeginsWithPredicateOperatorType:
766+
case NSEndsWithPredicateOperatorType:
767+
case NSContainsPredicateOperatorType:
768+
add_substring_constraint(value, std::move(condition));
769+
break;
770+
771+
default:
772+
m_query.and_query(std::move(condition));
773+
break;
774+
}
775+
}
776+
733777
template <typename C, typename T>
734778
void QueryBuilder::add_diacritic_sensitive_string_constraint(NSPredicateOperatorType operatorType,
735779
NSComparisonPredicateOptions predicateOptions,
@@ -1297,11 +1341,6 @@ KeyPath key_path_from_string(RLMSchema *schema, RLMObjectSchema *objectSchema, N
12971341

12981342
#pragma mark Collection Operations
12991343

1300-
// static_assert is always evaluated even if it's inside a if constexpr
1301-
// unless the value is derived from the template argument, in which case it's
1302-
// only evaluated if that branch is active
1303-
template <CollectionOperation::Type> struct AlwaysFalse : std::false_type {};
1304-
13051344
template <CollectionOperation::Type OperationType, typename Column>
13061345
auto collection_operation_expr_2(Column&& column) {
13071346
if constexpr (OperationType == CollectionOperation::Minimum) {
@@ -1317,7 +1356,8 @@ auto collection_operation_expr_2(Column&& column) {
13171356
return column.average();
13181357
}
13191358
else {
1320-
static_assert(AlwaysFalse<OperationType>::value, "invalid operation type");
1359+
static_assert(AlwaysFalse<std::integral_constant<CollectionOperation::Type, OperationType>>::value,
1360+
"invalid operation type");
13211361
}
13221362
}
13231363

@@ -1660,7 +1700,7 @@ bool is_self_value_for_key_path_function_expression(NSExpression *expression)
16601700
ColumnReference collectionColumn = column_reference_from_key_path(key_path_from_string(m_schema, objectSchema, keyPath), true);
16611701
RLMPrecondition(collectionColumn.property().dictionary, @"Invalid predicate",
16621702
@"Invalid keypath '%@': only dictionaries support subscript predicates.", functionExpression);
1663-
add_mixed_constraint(operatorType, options, collectionColumn.resolve<Dictionary>().key(mapKey.UTF8String), right.constantValue);
1703+
add_mixed_constraint(operatorType, options, std::move(collectionColumn.resolve<Dictionary>().key(mapKey.UTF8String)), right.constantValue);
16641704
}
16651705

16661706
void QueryBuilder::apply_function_expression(RLMObjectSchema *objectSchema, NSExpression *functionExpression,

Realm/RLMSyncConfiguration.mm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ void RLMSetConfigInfoForClientResetCallbacks(realm::SyncConfig& syncConfig, RLMR
205205

206206
- (id<RLMBSON>)partitionValue {
207207
if (!_config->partition_value.empty()) {
208-
return RLMConvertBsonToRLMBSON(realm::bson::parse(_config->partition_value.c_str()));
208+
return RLMConvertBsonToRLMBSON(realm::bson::parse(_config->partition_value));
209209
}
210210
return nil;
211211
}

Realm/RLMSyncManager.mm

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ RLMSyncLogLevel logLevelForLevel(Level logLevel) {
7373
#pragma mark - Loggers
7474

7575
struct CocoaSyncLogger : public realm::util::Logger {
76-
void do_log(Level, const std::string& message) override {
76+
void do_log(const realm::util::LogCategory&, Level, const std::string& message) override {
7777
NSLog(@"Sync: %@", RLMStringDataToNSString(message));
7878
}
7979
};
@@ -86,7 +86,7 @@ void do_log(Level, const std::string& message) override {
8686

8787
struct CallbackLogger : public realm::util::Logger {
8888
RLMSyncLogFunction logFn;
89-
void do_log(Level level, const std::string& message) override {
89+
void do_log(const realm::util::LogCategory&, Level level, const std::string& message) override {
9090
@autoreleasepool {
9191
logFn(logLevelForLevel(level), RLMStringDataToNSString(message));
9292
}
@@ -202,7 +202,7 @@ - (void)resetForTesting {
202202
_logger = nil;
203203
_authorizationHeaderName = nil;
204204
_customRequestHeaders = nil;
205-
_syncManager->reset_for_testing();
205+
_syncManager->tear_down_for_testing();
206206
}
207207

208208
- (std::shared_ptr<realm::SyncManager>)syncManager {

0 commit comments

Comments
 (0)