Skip to content

Commit 58b168b

Browse files
committed
Experiments
1 parent 06aacec commit 58b168b

File tree

37 files changed

+1303
-36
lines changed

37 files changed

+1303
-36
lines changed

packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/RealmInterop.kt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ expect object RealmInterop {
200200
fun realm_config_set_automatic_backlink_handling(config: RealmConfigurationPointer, enabled: Boolean)
201201
fun realm_config_set_data_initialization_function(config: RealmConfigurationPointer, callback: DataInitializationCallback)
202202
fun realm_config_set_in_memory(config: RealmConfigurationPointer, inMemory: Boolean)
203+
fun realm_config_set_relaxed_schema(config: RealmConfigurationPointer, relaxedSchema: Boolean)
203204
fun realm_schema_validate(schema: RealmSchemaPointer, mode: SchemaValidationMode): Boolean
204205

205206
fun realm_create_scheduler(): RealmSchedulerPointer
@@ -299,15 +300,26 @@ expect object RealmInterop {
299300
fun realm_get_col_key(realm: RealmPointer, classKey: ClassKey, col: String): PropertyKey
300301

301302
fun MemAllocator.realm_get_value(obj: RealmObjectPointer, key: PropertyKey): RealmValue
303+
fun MemAllocator.realm_get_value_by_name(obj: RealmObjectPointer, name: String): RealmValue
302304
fun realm_set_value(
303305
obj: RealmObjectPointer,
304306
key: PropertyKey,
305307
value: RealmValue,
306308
isDefault: Boolean
307309
)
310+
fun realm_set_value_by_name(
311+
obj: RealmObjectPointer,
312+
name: String,
313+
value: RealmValue,
314+
)
315+
fun realm_has_property(obj: RealmObjectPointer, name: String): Boolean
316+
fun realm_get_additional_properties(obj: RealmObjectPointer): List<String>
317+
fun realm_erase_property(obj: RealmObjectPointer, key: String): Boolean
308318
fun realm_set_embedded(obj: RealmObjectPointer, key: PropertyKey): RealmObjectPointer
309319
fun realm_set_list(obj: RealmObjectPointer, key: PropertyKey): RealmListPointer
320+
fun realm_set_list_by_name(obj: RealmObjectPointer, propertyName: String): RealmListPointer
310321
fun realm_set_dictionary(obj: RealmObjectPointer, key: PropertyKey): RealmMapPointer
322+
fun realm_set_dictionary_by_name(obj: RealmObjectPointer, propertyName: String): RealmMapPointer
311323
fun realm_object_add_int(obj: RealmObjectPointer, key: PropertyKey, value: Long)
312324
fun <T> realm_object_get_parent(
313325
obj: RealmObjectPointer,
@@ -316,6 +328,7 @@ expect object RealmInterop {
316328

317329
// list
318330
fun realm_get_list(obj: RealmObjectPointer, key: PropertyKey): RealmListPointer
331+
fun realm_get_list_by_name(obj: RealmObjectPointer, propertyName: String): RealmListPointer
319332
fun realm_get_backlinks(obj: RealmObjectPointer, sourceClassKey: ClassKey, sourcePropertyKey: PropertyKey): RealmResultsPointer
320333
fun realm_list_size(list: RealmListPointer): Long
321334
fun MemAllocator.realm_list_get(list: RealmListPointer, index: Long): RealmValue
@@ -354,6 +367,7 @@ expect object RealmInterop {
354367

355368
// dictionary
356369
fun realm_get_dictionary(obj: RealmObjectPointer, key: PropertyKey): RealmMapPointer
370+
fun realm_get_dictionary_by_name(obj: RealmObjectPointer, propertyName: String): RealmMapPointer
357371
fun realm_dictionary_clear(dictionary: RealmMapPointer)
358372
fun realm_dictionary_size(dictionary: RealmMapPointer): Long
359373
fun realm_dictionary_to_results(dictionary: RealmMapPointer): RealmResultsPointer

packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/sync/ProtocolErrorCode.kt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,6 @@ expect enum class WebsocketErrorCode : CodeDescription {
110110
RLM_ERR_WEBSOCKET_UNAUTHORIZED,
111111
RLM_ERR_WEBSOCKET_FORBIDDEN,
112112
RLM_ERR_WEBSOCKET_MOVEDPERMANENTLY,
113-
RLM_ERR_WEBSOCKET_CLIENT_TOO_OLD,
114-
RLM_ERR_WEBSOCKET_CLIENT_TOO_NEW,
115-
RLM_ERR_WEBSOCKET_PROTOCOL_MISMATCH,
116113
RLM_ERR_WEBSOCKET_RESOLVE_FAILED,
117114
RLM_ERR_WEBSOCKET_CONNECTION_FAILED,
118115
RLM_ERR_WEBSOCKET_READ_ERROR,

packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/RealmInterop.kt

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,10 @@ actual object RealmInterop {
216216
realmc.realm_config_set_in_memory(config.cptr(), inMemory)
217217
}
218218

219+
actual fun realm_config_set_relaxed_schema(config: RealmConfigurationPointer, relaxedSchema: Boolean) {
220+
realmc.realm_config_set_flexible_schema(config.cptr(), relaxedSchema)
221+
}
222+
219223
actual fun realm_create_scheduler(): RealmSchedulerPointer =
220224
LongPointerWrapper(realmc.realm_create_generic_scheduler())
221225

@@ -489,6 +493,15 @@ actual object RealmInterop {
489493
return RealmValue(struct)
490494
}
491495

496+
actual fun MemAllocator.realm_get_value_by_name(
497+
obj: RealmObjectPointer,
498+
name: String,
499+
): RealmValue {
500+
val struct = allocRealmValueT()
501+
realmc.realm_get_value_by_name((obj as LongPointerWrapper).ptr, name, struct)
502+
return RealmValue(struct)
503+
}
504+
492505
actual fun realm_set_value(
493506
obj: RealmObjectPointer,
494507
key: PropertyKey,
@@ -498,6 +511,29 @@ actual object RealmInterop {
498511
realmc.realm_set_value(obj.cptr(), key.key, value.value, isDefault)
499512
}
500513

514+
actual fun realm_set_value_by_name(
515+
obj: RealmObjectPointer,
516+
name: String,
517+
value: RealmValue,
518+
) {
519+
realmc.realm_set_value_by_name(obj.cptr(), name, value.value)
520+
}
521+
522+
actual fun realm_has_property(obj: RealmObjectPointer, name: String): Boolean {
523+
val found = BooleanArray(1)
524+
realmc.realm_has_property(obj.cptr(), name, found)
525+
return found[0]
526+
}
527+
528+
actual fun realm_get_additional_properties(obj: RealmObjectPointer): List<String> {
529+
@Suppress("UNCHECKED_CAST")
530+
val properties = realmc.realm_get_additional_properties_helper(obj.cptr()) as Array<String>
531+
return properties.asList()
532+
}
533+
actual fun realm_erase_property(obj: RealmObjectPointer, key: String): Boolean {
534+
return realmc.realm_erase_additional_property(obj.cptr(), key)
535+
}
536+
501537
actual fun realm_set_embedded(obj: RealmObjectPointer, key: PropertyKey): RealmObjectPointer {
502538
return LongPointerWrapper(realmc.realm_set_embedded(obj.cptr(), key.key))
503539
}
@@ -506,10 +542,18 @@ actual object RealmInterop {
506542
realmc.realm_set_list(obj.cptr(), key.key)
507543
return realm_get_list(obj, key)
508544
}
545+
actual fun realm_set_list_by_name(obj: RealmObjectPointer, propertyName: String): RealmListPointer {
546+
realmc.realm_set_list_by_name(obj.cptr(), propertyName)
547+
return realm_get_list_by_name(obj, propertyName)
548+
}
509549
actual fun realm_set_dictionary(obj: RealmObjectPointer, key: PropertyKey): RealmMapPointer {
510550
realmc.realm_set_dictionary(obj.cptr(), key.key)
511551
return realm_get_dictionary(obj, key)
512552
}
553+
actual fun realm_set_dictionary_by_name(obj: RealmObjectPointer, propertyName: String): RealmMapPointer {
554+
realmc.realm_set_dictionary_by_name(obj.cptr(), propertyName)
555+
return realm_get_dictionary_by_name(obj, propertyName)
556+
}
513557

514558
actual fun realm_object_add_int(obj: RealmObjectPointer, key: PropertyKey, value: Long) {
515559
realmc.realm_object_add_int(obj.cptr(), key.key, value)
@@ -542,6 +586,14 @@ actual object RealmInterop {
542586
)
543587
)
544588
}
589+
actual fun realm_get_list_by_name(obj: RealmObjectPointer, propertyName: String): RealmListPointer {
590+
return LongPointerWrapper(
591+
realmc.realm_get_list_by_name(
592+
(obj as LongPointerWrapper).ptr,
593+
propertyName
594+
)
595+
)
596+
}
545597

546598
actual fun realm_get_backlinks(obj: RealmObjectPointer, sourceClassKey: ClassKey, sourcePropertyKey: PropertyKey): RealmResultsPointer {
547599
return LongPointerWrapper(
@@ -731,6 +783,14 @@ actual object RealmInterop {
731783
return LongPointerWrapper(ptr)
732784
}
733785

786+
actual fun realm_get_dictionary_by_name(
787+
obj: RealmObjectPointer,
788+
propertyName: String
789+
): RealmMapPointer {
790+
val ptr = realmc.realm_get_dictionary_by_name(obj.cptr(), propertyName)
791+
return LongPointerWrapper(ptr)
792+
}
793+
734794
actual fun realm_dictionary_clear(dictionary: RealmMapPointer) {
735795
realmc.realm_dictionary_clear(dictionary.cptr())
736796
}

packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/sync/ProtocolErrorCode.kt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,9 +120,6 @@ actual enum class WebsocketErrorCode(
120120
RLM_ERR_WEBSOCKET_UNAUTHORIZED("Unauthorized", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_UNAUTHORIZED),
121121
RLM_ERR_WEBSOCKET_FORBIDDEN("Forbidden", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_FORBIDDEN),
122122
RLM_ERR_WEBSOCKET_MOVEDPERMANENTLY("MovedPermanently", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_MOVEDPERMANENTLY),
123-
RLM_ERR_WEBSOCKET_CLIENT_TOO_OLD("ClientTooOld", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_CLIENT_TOO_OLD),
124-
RLM_ERR_WEBSOCKET_CLIENT_TOO_NEW("ClientTooNew", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_CLIENT_TOO_NEW),
125-
RLM_ERR_WEBSOCKET_PROTOCOL_MISMATCH("ProtocolMismatch", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_PROTOCOL_MISMATCH),
126123

127124
RLM_ERR_WEBSOCKET_RESOLVE_FAILED("ResolveFailed", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_RESOLVE_FAILED),
128125
RLM_ERR_WEBSOCKET_CONNECTION_FAILED("ConnectionFailed", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_CONNECTION_FAILED),

packages/external/core

Submodule core updated 180 files

packages/jni-swig-stub/realm.i

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,7 @@ import static io.realm.kotlin.internal.interop.realm_errno_e.*;
377377
bool* erased, bool* out_erased, bool* did_refresh, bool* did_run,
378378
bool* found, bool* out_collection_was_cleared, bool* did_compact,
379379
bool* collection_was_cleared, bool* out_collection_was_deleted,
380-
bool* out_was_deleted};
380+
bool* out_was_deleted, bool* out_has_property };
381381

382382
// uint64_t output parameter for realm_get_num_versions
383383
%apply int64_t* OUTPUT { uint64_t* out_versions_count };

packages/jni-swig-stub/src/main/jni/realm_api_helpers.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1411,3 +1411,25 @@ jobjectArray realm_get_log_category_names() {
14111411

14121412
return array;
14131413
}
1414+
1415+
jobjectArray realm_get_additional_properties_helper(realm_object_t* obj) {
1416+
JNIEnv* env = get_env(true);
1417+
1418+
size_t count = 0;
1419+
realm_get_additional_properties(obj, nullptr, 0xffffff, &count);
1420+
1421+
const char** properties = new const char*[count];
1422+
realm_get_additional_properties(obj, properties, count, &count);
1423+
// FIXME Guard count != count
1424+
1425+
auto array = env->NewObjectArray(count, JavaClassGlobalDef::java_lang_string(), nullptr);
1426+
1427+
for(size_t i = 0; i < count; i++) {
1428+
jstring string = env->NewStringUTF(properties[i]);
1429+
env->SetObjectArrayElement(array, i, string);
1430+
}
1431+
1432+
delete[] properties;
1433+
1434+
return array;
1435+
}

packages/jni-swig-stub/src/main/jni/realm_api_helpers.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,5 +162,6 @@ bool realm_sync_websocket_message(int64_t observer_ptr, jbyteArray data, size_t
162162
void realm_sync_websocket_closed(int64_t observer_ptr, bool was_clean, int error_code, const char* reason);
163163

164164
jobjectArray realm_get_log_category_names();
165+
jobjectArray realm_get_additional_properties_helper(realm_object_t* obj);
165166

166167
#endif //TEST_REALM_API_HELPERS_H

packages/library-base/src/commonMain/kotlin/io/realm/kotlin/BaseRealm.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ public interface BaseRealm : Versioned {
3131
* @return the schema of the realm.
3232
*/
3333
public fun schema(): RealmSchema
34+
// public fun schema(fullSchema: Boolean = false): RealmSchema
3435

3536
/**
3637
* Returns the schema version of the realm.

packages/library-base/src/commonMain/kotlin/io/realm/kotlin/Configuration.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,9 @@ public interface Configuration {
170170
*/
171171
public val initialRealmFileConfiguration: InitialRealmFileConfiguration?
172172

173+
// FIXME DOCS
174+
public val relaxedSchema: Boolean
175+
173176
/**
174177
* Base class for configuration builders that holds properties available to both
175178
* [RealmConfiguration] and [SyncConfiguration].
@@ -209,6 +212,7 @@ public interface Configuration {
209212
protected var initialDataCallback: InitialDataCallback? = null
210213
protected var inMemory: Boolean = false
211214
protected var initialRealmFileConfiguration: InitialRealmFileConfiguration? = null
215+
protected var relaxedSchema: Boolean = false
212216

213217
/**
214218
* Sets the filename of the realm file.
@@ -399,6 +403,12 @@ public interface Configuration {
399403
return this as S
400404
}
401405

406+
// FIXME Docs
407+
public fun relaxedSchema(relaxedSchema: Boolean): S {
408+
this.relaxedSchema = relaxedSchema
409+
return this as S
410+
}
411+
402412
protected fun validateEncryptionKey(encryptionKey: ByteArray): ByteArray {
403413
if (encryptionKey.size != Realm.ENCRYPTION_KEY_LENGTH) {
404414
throw IllegalArgumentException("The provided key must be ${Realm.ENCRYPTION_KEY_LENGTH} bytes. The provided key was ${encryptionKey.size} bytes.")

packages/library-base/src/commonMain/kotlin/io/realm/kotlin/RealmConfiguration.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ public interface RealmConfiguration : Configuration {
181181
initialDataCallback,
182182
inMemory,
183183
initialRealmFileConfiguration,
184+
relaxedSchema,
184185
realmLogger
185186
)
186187
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/*
2+
* Copyright 2023 Realm Inc.
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
* http://www.apache.org/licenses/LICENSE-2.0
7+
* Unless required by applicable law or agreed to in writing, software
8+
* distributed under the License is distributed on an "AS IS" BASIS,
9+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
10+
* or implied.
11+
* See the License for the specific language governing permissions and
12+
* limitations under the License.
13+
*
14+
*/
15+
package io.realm.kotlin.annotations
16+
17+
@MustBeDocumented
18+
@Target(
19+
AnnotationTarget.FUNCTION,
20+
)
21+
@RequiresOptIn(level = RequiresOptIn.Level.ERROR)
22+
public annotation class DynamicAPI
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* Copyright 2024 Realm Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.realm.kotlin.dynamic.getgeneric
18+
19+
import io.realm.kotlin.annotations.DynamicAPI
20+
import io.realm.kotlin.internal.RealmObjectHelper
21+
import io.realm.kotlin.internal.runIfManagedOrThrow
22+
import io.realm.kotlin.types.BaseRealmObject
23+
import kotlin.reflect.KType
24+
import kotlin.reflect.typeOf
25+
26+
// Proposal 1 of generic/dynamic API
27+
// This seems like the most promising
28+
@DynamicAPI
29+
public inline operator fun <reified T> BaseRealmObject.get(propertyName: String): T {
30+
return get(propertyName, typeOf<T>())
31+
}
32+
33+
@DynamicAPI
34+
public operator fun <T> BaseRealmObject.set(name: String, value: T) {
35+
return this.runIfManagedOrThrow {
36+
RealmObjectHelper.setValueByName(this, name, value)
37+
}
38+
}
39+
40+
@PublishedApi
41+
internal fun <T> BaseRealmObject.get(propertyName: String, type: KType): T {
42+
return this.runIfManagedOrThrow {
43+
RealmObjectHelper.dynamicGetFromKType(
44+
obj = this,
45+
propertyName = propertyName,
46+
type = type
47+
)
48+
}
49+
}
50+
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* Copyright 2024 Realm Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.realm.kotlin.dynamic.getinterface
18+
19+
import io.realm.kotlin.internal.RealmObjectHelper
20+
import io.realm.kotlin.internal.runIfManagedOrThrow
21+
import io.realm.kotlin.types.BaseRealmObject
22+
import kotlin.reflect.KType
23+
import kotlin.reflect.typeOf
24+
25+
// Proposal 2 of generic/dynamic API
26+
// Hiding things a bit by only exposing it on a specific type. This is a bit cumbersome as you
27+
// cannot use a single entry point to get into the dynamic domain (requires to use .relaxed
28+
// everywhere)
29+
public interface RelaxedRealmObject
30+
31+
// FIXME Naming
32+
// - Extras?
33+
public val BaseRealmObject.relaxed: RelaxedRealmObject
34+
get() = this as RelaxedRealmObject
35+
36+
37+
public inline operator fun <reified T> RelaxedRealmObject.get(propertyName: String): T {
38+
return get(propertyName, typeOf<T>())
39+
}
40+
41+
public operator fun <T> RelaxedRealmObject.set(name: String, value: T) {
42+
return (this as BaseRealmObject).runIfManagedOrThrow {
43+
RealmObjectHelper.setValueByName(this, name, value)
44+
}
45+
}
46+
47+
@PublishedApi
48+
internal fun <T> RelaxedRealmObject.get(propertyName: String, type: KType): T {
49+
return (this as BaseRealmObject).runIfManagedOrThrow {
50+
RealmObjectHelper.dynamicGetFromKType(
51+
obj = this,
52+
propertyName = propertyName,
53+
type = type
54+
)
55+
}
56+
}

0 commit comments

Comments
 (0)