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

Opening a Realm as read-only #260

Merged
merged 24 commits into from
Feb 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
45e0add
Configuration isReadOnly implemented
desistefanova Feb 16, 2022
0e736d9
Configuration read-only tests added + documentation
desistefanova Feb 17, 2022
8827966
CHANGELOG updated
desistefanova Feb 17, 2022
1bc9fe9
Update lib/src/configuration.dart
desistefanova Feb 18, 2022
2929f9c
Update lib/src/configuration.dart
desistefanova Feb 18, 2022
2a8aa07
Update lib/src/configuration.dart
desistefanova Feb 18, 2022
07210b7
Update lib/src/configuration.dart
desistefanova Feb 18, 2022
d2b65f4
Update test/realm_test.dart
desistefanova Feb 18, 2022
7778014
Update test/realm_test.dart
desistefanova Feb 18, 2022
cc75297
Update lib/src/configuration.dart
desistefanova Feb 18, 2022
72fdbff
Update lib/src/configuration.dart
desistefanova Feb 18, 2022
d586b6f
Update lib/src/native/realm_core.dart
desistefanova Feb 18, 2022
88649a9
Update lib/src/native/realm_core.dart
desistefanova Feb 18, 2022
bac56c0
Update test/realm_test.dart
desistefanova Feb 18, 2022
375f424
Update test/realm_test.dart
desistefanova Feb 18, 2022
b96430a
Merge branch 'master' into config_isReadOnly
desistefanova Feb 18, 2022
949cc35
Configuration and schema API documentation
desistefanova Feb 18, 2022
ad4407f
Updated CHANGELOG
desistefanova Feb 18, 2022
ea51d30
deleted redundant tests
desistefanova Feb 18, 2022
edffc2b
updated CHANGELOG
desistefanova Feb 18, 2022
3e797e1
empty rows
desistefanova Feb 18, 2022
cc6782d
Fixed comments
desistefanova Feb 18, 2022
1c056fe
Fixed comments
desistefanova Feb 18, 2022
7e2885e
updated CHANGELOG
desistefanova Feb 18, 2022
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ x.x.x Release notes (yyyy-MM-dd)
* Support change notifications on query results. ([208](https://github.com/realm/realm-dart/pull/208))
* Added support checking if Realm lists and Realm objects are valid. ([#183](https://github.com/realm/realm-dart/pull/183))
* Support query on lists of realm objects. ([239](https://github.com/realm/realm-dart/pull/239))
* Added support for opening Realm in read-only mode. ([#260](https://github.com/realm/realm-dart/pull/260))

### Compatibility
* Dart ^2.15 on Windows, MacOS and Linux
Expand Down
22 changes: 18 additions & 4 deletions lib/src/configuration.dart
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,17 @@ class Configuration {
RealmSchema get schema => _schema;

/// Creates a [Configuration] with schema objects for opening a [Realm].
Configuration(List<SchemaObject> schemaObjects)
/// [readOnly] controls whether a [Realm] is opened as readonly.
/// This allows opening it from locked locations such as resources,
/// bundled with an application. The realm file must already exists.
Configuration(List<SchemaObject> schemaObjects, {bool readOnly = false})
: _schema = RealmSchema(schemaObjects),
_handle = realmCore.createConfig() {
schemaVersion = 0;
path = defaultPath;
if (readOnly) {
isReadOnly = true;
}
realmCore.setSchema(this);
}

Expand All @@ -53,7 +59,7 @@ class Configuration {
}

/// The platform dependent path to the default realm file - `default.realm`.
///
///
/// If set it should contain the name of the realm file. Ex. /mypath/myrealm.realm
static String get defaultPath => _defaultPath ??= _initDefaultPath();
static set defaultPath(String value) => _defaultPath = value;
Expand Down Expand Up @@ -83,10 +89,18 @@ class Configuration {
/// If omitted the [defaultPath] for the platform will be used.
String get path => realmCore.getConfigPath(this);
set path(String value) => realmCore.setConfigPath(this, value);

/// Gets or sets a value indicating whether a [Realm] is opened as readonly.
/// This allows opening it from locked locations such as resources,
/// bundled with an application.
///
/// The realm file must already exists at [path]
bool get isReadOnly => realmCore.getConfigReadOnly(this);
set isReadOnly(bool value) => realmCore.setConfigReadOnly(this, value);
}

/// A collection of properties describing the underlying schema of a [RealmObject].
///
///
/// {@category Configuration}
class SchemaObject {
/// Schema object type.
Expand All @@ -103,7 +117,7 @@ class SchemaObject {
}

/// Describes the complete set of classes which may be stored in a `Realm`
///
///
/// {@category Configuration}
class RealmSchema extends Iterable<SchemaObject> {
///@nodoc
Expand Down
10 changes: 10 additions & 0 deletions lib/src/native/realm_core.dart
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,16 @@ class _RealmCore {
_realmLib.realm_config_set_schema_version(config.handle._pointer, version);
}

bool getConfigReadOnly(Configuration config) {
int mode = _realmLib.realm_config_get_schema_mode(config.handle._pointer);
return mode == realm_schema_mode.RLM_SCHEMA_MODE_READ_ONLY;
}

void setConfigReadOnly(Configuration config, bool value) {
int mode = value ? realm_schema_mode.RLM_SCHEMA_MODE_READ_ONLY : realm_schema_mode.RLM_SCHEMA_MODE_AUTOMATIC;
_realmLib.realm_config_set_schema_mode(config.handle._pointer, mode);
}

ConfigHandle createConfig() {
final configPtr = _realmLib.realm_config_new();
return ConfigHandle._(configPtr);
Expand Down
53 changes: 45 additions & 8 deletions test/realm_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,45 @@ Future<void> main([List<String>? args]) async {
config.schemaVersion = 3;
expect(config.schemaVersion, equals(3));
});

test('Configuration readOnly - opening non existing realm throws', () {
Configuration config = Configuration([Car.schema], readOnly: true);
expect(() => Realm(config), throws<RealmException>("Message: No such table exists"));
});

test('Configuration readOnly - open existing realm with read-only config', () {
Configuration config = Configuration([Car.schema]);
var realm = Realm(config);
realm.close();

// Open an existing realm as readonly.
config = Configuration([Car.schema], readOnly: true);
realm = Realm(config);
realm.close();
});

test('Configuration readOnly - reading is possible', () {
Configuration config = Configuration([Car.schema]);
var realm = Realm(config);
realm.write(() => realm.add(Car("Mustang")));
realm.close();

config.isReadOnly = true;
realm = Realm(config);
var cars = realm.all<Car>();
realm.close();
});

test('Configuration readOnly - writing on read-only Realms throws', () {
Configuration config = Configuration([Car.schema]);
var realm = Realm(config);
realm.close();

config = Configuration([Car.schema], readOnly: true);
realm = Realm(config);
expect(() => realm.write(() {}), throws<RealmException>("Can't perform transactions on read-only Realms."));
realm.close();
});
});

group('RealmClass tests:', () {
Expand Down Expand Up @@ -898,15 +937,15 @@ Future<void> main([List<String>? args]) async {
var config = Configuration([Dog.schema, Person.schema]);
var realm = Realm(config);

realm.write(() {
realm.write(() {
realm.add(Dog("Lassy"));
});

var callbackCalled = false;
final subscription = realm.all<Dog>().changes.listen((changes) {
final subscription = realm.all<Dog>().changes.listen((changes) {
callbackCalled = true;
});

await Future<void>.delayed(Duration(milliseconds: 10));
expect(callbackCalled, true);

Expand All @@ -930,10 +969,10 @@ Future<void> main([List<String>? args]) async {
var realm = Realm(config);

var callbackCalled = false;
final subscription = realm.all<Dog>().changes.listen((changes) {
final subscription = realm.all<Dog>().changes.listen((changes) {
callbackCalled = true;
});

await Future<void>.delayed(Duration(milliseconds: 10));
expect(callbackCalled, true);

Expand All @@ -951,8 +990,7 @@ Future<void> main([List<String>? args]) async {
realm.add(Dog("Lassy1"));
});
await Future<void>.delayed(Duration(milliseconds: 10));
expect(callbackCalled,true);

expect(callbackCalled, true);

await subscription.cancel();
await Future<void>.delayed(Duration(milliseconds: 10));
Expand Down Expand Up @@ -1610,7 +1648,6 @@ Future<void> main([List<String>? args]) async {
realm.close();
});


test('Realm adding objects graph', () {
var studentMichele = Student(1)
..name = "Michele Ernesto"
Expand Down