Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
0.6.3 (2020-05-07)
------------------
* Update FlatBuffers to 1.12.0
* Provide error hinting when DB can't be created (e.g. when an app docs directory isn't passed properly on Flutter).

0.6.2 (2020-03-09)
------------------
* Support large object arrays on 32-bit platforms/emulators.
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ Installation
Add the following dependencies to your `pubspec.yaml`:
```yaml
dependencies:
objectbox: ^0.6.2
objectbox: ^0.6.3

dev_dependencies:
build_runner: ^1.0.0
objectbox_generator: ^0.6.2
objectbox_generator: ^0.6.3
```

Proceed based on whether you're developing a Flutter app or a standalone dart program:
Expand Down
49 changes: 38 additions & 11 deletions example/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,45 @@ Finally, you will create a `Box<Note>` which gives you a typed interface for sto
import 'objectbox.g.dart'; // this file will be generated by ObjectBox after running `pub run build_runner build`

void main() {
var store = Store(getObjectBoxModel()); // Note: getObjectBoxModel() is generated for you in objectbox.g.dart
var box = Box<Note>(store);
var note = Note(text: "Hello");
note.id = box.put(note);
print("new note got id ${note.id}");
print("refetched note: ${box.get(note.id)}");
store.close();
var store = Store(getObjectBoxModel()); // Note: getObjectBoxModel() is generated for you in objectbox.g.dart
var box = Box<Note>(store);

var note = Note(text: "Hello");
note.id = box.put(note);
print("new note got id ${note.id}");
print("refetched note: ${box.get(note.id)}");

store.close();
}
```

See also
Flutter
--------
* sample [Flutter android app](flutter/objectbox_demo) - requires Flutter 1.12
* See a [Flutter example app](flutter/objectbox_demo) - requires Flutter 1.12

As opposed to a plain Dart app which runs directly on your PC, there are more restrictions where your Flutter app can
write data. Therefore, you should give ObjectBox a full path to a per-app documents directory, where to store the data
even when a user closes your app.

If you didn't specify this path to ObjectBox, it would try to use a default "objectbox" directory where the app is
currently running, but it doesn't have permissions to write there: `failed to create store: 10199 Dir does not exist: objectbox (30)`.

To configure ObjectBox properly, you can use `getApplicationDocumentsDirectory()` from the `path_provider` package.
See [Flutter: read & write files](https://flutter.dev/docs/cookbook/persistence/reading-writing-files) for more info.
Have a look how it's done in the Flutter example app:
```dart
import 'package:path_provider/path_provider.dart';

class _MyHomePageState extends State<MyHomePage> {
Store _store;

@override
void initState() {
super.initState();

getApplicationDocumentsDirectory().then((dir) {
_store = Store(getObjectBoxModel(), directory: dir.path + "/objectbox");
});
}
}
```
4 changes: 2 additions & 2 deletions example/flutter/objectbox_demo/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ dependencies:
cupertino_icons: ^0.1.2
path_provider: any
intl: any
objectbox: ^0.6.2
objectbox: ^0.6.3

dev_dependencies:
flutter_test:
sdk: flutter
build_runner: ^1.0.0
objectbox_generator: ^0.6.2
objectbox_generator: ^0.6.3

flutter:
uses-material-design: true
Expand Down
4 changes: 2 additions & 2 deletions example/flutter/objectbox_demo_desktop/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ dependencies:
flutter:
sdk: flutter
cupertino_icons: ^0.1.0
objectbox: ^0.6.2
objectbox: ^0.6.3

dev_dependencies:
flutter_test:
sdk: flutter
build_runner: ^1.0.0
objectbox_generator: ^0.6.2
objectbox_generator: ^0.6.3

flutter:
uses-material-design: true
Expand Down
4 changes: 2 additions & 2 deletions generator/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: objectbox_generator
version: 0.6.2
version: 0.6.3
repository: https://github.com/objectbox/objectbox-dart
homepage: https://objectbox.io
description: ObjectBox binding code generator - finds annotated entities and adds them to the ObjectBox DB model.
Expand All @@ -8,7 +8,7 @@ environment:
sdk: ">=2.5.0 <3.0.0"

dependencies:
objectbox: 0.6.2
objectbox: 0.6.3
build: ^1.0.0
source_gen: ^0.9.0
analyzer: ">=0.35.0 <0.100.0"
Expand Down
15 changes: 7 additions & 8 deletions lib/src/bindings/helpers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,26 @@ import "bindings.dart";
import "constants.dart";
import "../common.dart";

checkObx(errorCode) {
if (errorCode != OBXError.OBX_SUCCESS) throw ObjectBoxException(lastObxErrorString(errorCode));
checkObx(int code) {
if (code != OBXError.OBX_SUCCESS) throw latestNativeError(codeIfMissing: code);
}

Pointer<T> checkObxPtr<T extends NativeType>(Pointer<T> ptr, String msg) {
Pointer<T> checkObxPtr<T extends NativeType>(Pointer<T> ptr, String dartMsg) {
if (ptr == null || ptr.address == 0) {
final info = lastObxErrorString();
throw ObjectBoxException(info.isEmpty ? msg : "$msg: $info");
throw latestNativeError(dartMsg: dartMsg);
}
return ptr;
}

String lastObxErrorString([int err = 0]) {
ObjectBoxException latestNativeError({String dartMsg, int codeIfMissing}) {
int code = bindings.obx_last_error_code();
String text = cString(bindings.obx_last_error_message());

if (code == 0 && text.isEmpty) {
return (err != 0) ? "code $err" : "unknown native error";
return ObjectBoxException(dartMsg: dartMsg, nativeCode: codeIfMissing, nativeMsg: 'unknown native error');
}

return code == 0 ? text : "$code $text";
return ObjectBoxException(dartMsg: dartMsg, nativeCode: code, nativeMsg: text);
}

String cString(Pointer<Utf8> charPtr) {
Expand Down
5 changes: 3 additions & 2 deletions lib/src/bindings/structs.dart
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,9 @@ class OBX_bytes extends Struct {
int length;

/// Get access to the data (no-copy)
Uint8List get data =>
isEmpty ? throw ObjectBoxException("can't access data of empty OBX_bytes") : _dataPtr.asTypedList(length);
Uint8List get data => isEmpty
? throw ObjectBoxException(dartMsg: "can't access data of empty OBX_bytes")
: _dataPtr.asTypedList(length);

bool get isEmpty => length == 0 || _dataPtr.address == 0;

Expand Down
2 changes: 1 addition & 1 deletion lib/src/box.dart
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class Box<T> {
int id = propVals[_modelEntity.idProperty.name];
if (id == null || id == 0) {
id = bindings.obx_box_id_for_put(_cBox, 0);
if (id == 0) throw ObjectBoxException(lastObxErrorString());
if (id == 0) throw latestNativeError();
propVals[_modelEntity.idProperty.name] = id;
}

Expand Down
24 changes: 16 additions & 8 deletions lib/src/common.dart
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,20 @@ Version versionLib() {
}

class ObjectBoxException implements Exception {
final String message;
final String msg;

ObjectBoxException(msg)
: message = "ObjectBoxException: " + msg,
msg = msg;

String toString() => message;
final String dartMsg;
final int nativeCode;
final String nativeMsg;

ObjectBoxException({String dartMsg, int nativeCode, String nativeMsg})
: dartMsg = dartMsg,
nativeCode = nativeCode,
nativeMsg = nativeMsg;

@override
String toString() {
var result = 'ObjectBoxException: ';
if (dartMsg != null) result += dartMsg + ': ';
if (nativeCode != 0) result += '$nativeCode ';
return result + nativeMsg;
}
}
2 changes: 1 addition & 1 deletion lib/src/model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class Model {
int code = bindings.obx_model_error_code(_cModel);
String text = cString(bindings.obx_model_error_message(_cModel));

throw ObjectBoxException("$code $text");
throw ObjectBoxException(nativeCode: code, nativeMsg: text);
}

void addEntity(ModelEntity entity) {
Expand Down
2 changes: 1 addition & 1 deletion lib/src/query/builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class QueryBuilder<T> {
void _throwExceptionIfNecessary() {
if (bindings.obx_qb_error_code(_cBuilder) != OBXError.OBX_SUCCESS) {
final msg = cString(bindings.obx_qb_error_message(_cBuilder));
throw ObjectBoxException("$msg");
throw ObjectBoxException(nativeMsg: msg);
}
}

Expand Down
19 changes: 18 additions & 1 deletion lib/src/store.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import "bindings/bindings.dart";
import "bindings/helpers.dart";
import "modelinfo/index.dart";
import "model.dart";
import "common.dart";

enum TxMode {
Read,
Expand Down Expand Up @@ -40,7 +41,23 @@ class Store {
rethrow;
}
_cStore = bindings.obx_store_open(opt);
checkObxPtr(_cStore, "failed to create store");

try {
checkObxPtr(_cStore, "failed to create store");
} on ObjectBoxException catch (e) {
// Recognize common problems when trying to open/create a database
// 10199 = OBX_ERROR_STORAGE_GENERAL
if (e.nativeCode == 10199 && e.nativeMsg != null && e.nativeMsg.contains('Dir does not exist')) {
// 13 = permissions denied, 30 = read-only filesystem
if (e.nativeMsg.endsWith(' (13)') || e.nativeMsg.endsWith(' (30)')) {
final msg = e.nativeMsg +
" - this usually indicates a problem with permissions; if you're using Flutter you may need to use " +
"getApplicationDocumentsDirectory() from the path_provider package, see example/README.md";
throw ObjectBoxException(dartMsg: e.dartMsg, nativeCode: e.nativeCode, nativeMsg: msg);
}
}
rethrow;
}
}

/// Closes this store.
Expand Down
4 changes: 2 additions & 2 deletions pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: objectbox
version: 0.6.2
version: 0.6.3
repository: https://github.com/objectbox/objectbox-dart
homepage: https://objectbox.io
description: ObjectBox is a super-fast NoSQL ACID compliant object database.
Expand All @@ -9,7 +9,7 @@ environment:

dependencies:
# take care updating flatbuffers - keep aligned with other bindings
flat_buffers: 1.11.0
flat_buffers: 1.12.0
ffi: ^0.1.3

dev_dependencies:
Expand Down
4 changes: 2 additions & 2 deletions test/basics_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ void main() {
// sanity check - the result is a null pointer
expect(cStore, isA<ffi.Pointer>().having((ptr) => ptr.address, "address", equals(0)));

final error = lastObxErrorString();
expect(error, matches('Argument .+ must not be null'));
final error = latestNativeError();
expect(error.nativeMsg, matches('Argument .+ must not be null'));
});
}