Skip to content

Commit f6aa84a

Browse files
committed
offline fixes
1 parent 4496dce commit f6aa84a

File tree

8 files changed

+122
-146
lines changed

8 files changed

+122
-146
lines changed

lib/src/adapter/adapter.dart

Lines changed: 25 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ abstract class _BaseAdapter<T extends DataModelMixin<T>> with _Lifecycle {
4545
@visibleForTesting
4646
final LocalStorage storage;
4747

48+
Database get db => storage.db;
49+
4850
bool _stopInitialization = false;
4951

5052
// None of these fields below can be late finals as they might be re-initialized
@@ -88,7 +90,7 @@ abstract class _BaseAdapter<T extends DataModelMixin<T>> with _Lifecycle {
8890

8991
@mustCallSuper
9092
Future<void> onInitialized() async {
91-
storage.db.execute('''
93+
db.execute('''
9294
CREATE TABLE IF NOT EXISTS $internalType (
9395
key INTEGER PRIMARY KEY AUTOINCREMENT,
9496
data TEXT
@@ -120,7 +122,7 @@ abstract class _BaseAdapter<T extends DataModelMixin<T>> with _Lifecycle {
120122

121123
/// Returns all models of type [T] in local storage.
122124
List<T> findAllLocal() {
123-
final result = storage.db.select('SELECT key, data FROM $internalType');
125+
final result = db.select('SELECT key, data FROM $internalType');
124126
return _deserializeFromResult(result);
125127
}
126128

@@ -131,7 +133,7 @@ abstract class _BaseAdapter<T extends DataModelMixin<T>> with _Lifecycle {
131133
}
132134
final intKeys = keys.map((key) => key.detypifyKey()).toList();
133135

134-
final result = storage.db.select(
136+
final result = db.select(
135137
'SELECT key, data FROM $internalType WHERE key IN (${intKeys.map((_) => '?').join(', ')})',
136138
intKeys);
137139
return _deserializeFromResult(result);
@@ -158,7 +160,7 @@ abstract class _BaseAdapter<T extends DataModelMixin<T>> with _Lifecycle {
158160

159161
/// Whether [key] exists in local storage.
160162
bool exists(String key) {
161-
final result = storage.db.select(
163+
final result = db.select(
162164
'SELECT EXISTS(SELECT 1 FROM $internalType WHERE key = ?) AS e;',
163165
[key.detypifyKey()]);
164166
return result.first['e'] == 1;
@@ -174,7 +176,7 @@ abstract class _BaseAdapter<T extends DataModelMixin<T>> with _Lifecycle {
174176
final key = model._key!.detypifyKey();
175177
final map = serialize(model, withRelationships: false);
176178
final data = jsonEncode(map);
177-
storage.db.execute(
179+
db.execute(
178180
'REPLACE INTO $internalType (key, data) VALUES (?, ?)', [key, data]);
179181
return model;
180182
}
@@ -243,7 +245,7 @@ abstract class _BaseAdapter<T extends DataModelMixin<T>> with _Lifecycle {
243245
/// Deletes models with [keys] from local storage.
244246
void deleteLocalByKeys(Iterable<String> keys, {bool notify = true}) {
245247
final intKeys = keys.map((k) => k.detypifyKey()).toList();
246-
storage.db.execute(
248+
db.execute(
247249
'DELETE FROM $internalType WHERE key IN (${keys.map((_) => '?').join(', ')})',
248250
intKeys);
249251
core.deleteKeys(keys);
@@ -257,21 +259,21 @@ abstract class _BaseAdapter<T extends DataModelMixin<T>> with _Lifecycle {
257259
// TODO SELECT name FROM sqlite_master WHERE type='table' AND name='your_table_name';
258260
// leave async in case some impls need to remove files
259261
for (final adapter in adapters.values) {
260-
storage.db.execute('DELETE FROM ${adapter.internalType}');
262+
db.execute('DELETE FROM ${adapter.internalType}');
261263
}
262264
core._notify([internalType], type: DataGraphEventType.clear);
263265
}
264266

265267
/// Counts all models of type [T] in local storage.
266268
int get countLocal {
267-
final result = storage.db.select('SELECT count(*) FROM $internalType');
269+
final result = db.select('SELECT count(*) FROM $internalType');
268270
return result.first['count(*)'];
269271
}
270272

271273
/// Gets all keys of type [T] in local storage.
272274
Set<String> get keys {
273-
final result = storage.db
274-
.select('SELECT key FROM _keys WHERE type = ?', [internalType]);
275+
final result =
276+
db.select('SELECT key FROM _keys WHERE type = ?', [internalType]);
275277
return result
276278
.map((r) => r['key'].toString().typifyWith(internalType))
277279
.toSet();
@@ -313,27 +315,17 @@ abstract class _BaseAdapter<T extends DataModelMixin<T>> with _Lifecycle {
313315
@visibleForTesting
314316
@nonVirtual
315317
Set<OfflineOperation<T>> get offlineOperations {
316-
// TODO restore
317-
final edges = []; // storage.edgesFor([(_offlineAdapterKey, null)]);
318-
return edges
319-
.map((e) {
320-
try {
321-
// extract type from e.g. _offline:findOne/users#3@d7bcc9
322-
final label = DataRequestLabel.parse(e.name.denamespace());
323-
if (label.type == internalType) {
324-
// get first edge value
325-
final map = json.decode(e.to) as Map<String, dynamic>;
326-
return OfflineOperation<T>.fromJson(
327-
label, map, this as Adapter<T>);
328-
}
329-
} catch (_) {
330-
// TODO restore
331-
// if there were any errors parsing labels or json ignore and remove
332-
// storage.removeEdgesFor([(_offlineAdapterKey, e.name)]);
333-
}
334-
})
335-
.nonNulls
336-
.toSet();
318+
final result = db.select('SELECT * FROM _offline_operations');
319+
return result.map((r) {
320+
return OfflineOperation<T>(
321+
label: DataRequestLabel.parse(r['label']),
322+
httpRequest: r['request'],
323+
timestamp: r['timestamp'],
324+
headers: Map<String, String>.from(jsonDecode(r['headers'])),
325+
body: r['body'],
326+
key: r['key'],
327+
adapter: this as Adapter<T>);
328+
}).toSet();
337329
}
338330

339331
Object? _resolveId(Object obj) {
@@ -391,7 +383,7 @@ abstract class _BaseAdapter<T extends DataModelMixin<T>> with _Lifecycle {
391383
// TODO optimize: put outside loop and query edgesFor just once
392384
if (fromKey != null && relationship._uninitializedKeys == null) {
393385
// TODO DRY!
394-
final result = storage.db.select(
386+
final result = db.select(
395387
'SELECT src, dest FROM _edges WHERE (src = ? AND name = ?) OR (dest = ? AND inverse = ?)',
396388
[fromKey, metadata.name, fromKey, metadata.name]);
397389
relationship._uninitializedKeys = {for (final r in result) r['dest']};
@@ -409,9 +401,7 @@ abstract class _BaseAdapter<T extends DataModelMixin<T>> with _Lifecycle {
409401

410402
T deserialize(Map<String, dynamic> map, {String? key});
411403

412-
Map<String, RelationshipMeta> get relationshipMetas {
413-
throw UnimplementedError('');
414-
}
404+
Map<String, RelationshipMeta> get relationshipMetas;
415405

416406
Map<String, dynamic> transformSerialize(Map<String, dynamic> map,
417407
{bool withRelationships = true}) {

lib/src/adapter/remote_adapter.dart

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -505,7 +505,6 @@ mixin _RemoteAdapter<T extends DataModelMixin<T>> on _SerializationAdapter<T> {
505505
key: label.model!._key);
506506
final model = data.model!;
507507

508-
// TODO group?
509508
// if there has been a migration to a new key, delete the old one
510509
if (model._key != label.model!._key) {
511510
deleteLocalByKeys({label.model!._key!});

lib/src/model/data_model.dart

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,7 @@ part of flutter_data;
22

33
abstract class DataModel<T extends DataModel<T>> with DataModelMixin<T> {
44
DataModel() {
5-
// _internalTypes will be empty in an isolate,
6-
// where we don't want to auto init
7-
// TODO this will autoinit in isolate, ok!??
8-
// if (DataHelpers._internalTypes.isNotEmpty) {
95
init();
10-
// }
116
}
127

138
/// Returns a model [Adapter]

lib/src/storage/local_storage.dart

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,25 @@ class LocalStorage {
3939
dest INTEGER NOT NULL,
4040
inverse TEXT
4141
);
42+
CREATE INDEX src_name_idx ON _edges(src, name);
43+
CREATE INDEX dest_inverse_idx ON _edges(dest, inverse);
4244
4345
CREATE TABLE IF NOT EXISTS _keys (
4446
key INTEGER PRIMARY KEY AUTOINCREMENT,
4547
type TEXT NOT NULL,
4648
id TEXT,
4749
is_int INTEGER DEFAULT 0
4850
);
51+
CREATE INDEX id_idx ON _keys(id);
52+
53+
CREATE TABLE IF NOT EXISTS _offline_operations (
54+
label TEXT PRIMARY KEY,
55+
request TEXT NOT NULL,
56+
timestamp DATETIME,
57+
headers TEXT,
58+
body TEXT,
59+
key TEXT
60+
);
4961
''');
5062
} catch (e, stackTrace) {
5163
print('[flutter_data] Failed to open:\n$e\n$stackTrace');

lib/src/utils/framework.dart

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -115,13 +115,13 @@ class RelationshipMeta<T extends DataModelMixin<T>>
115115
});
116116

117117
// get topmost parent
118-
RelationshipMeta get _top {
119-
RelationshipMeta? current = this;
120-
while (current?.parent != null) {
121-
current = current!.parent;
122-
}
123-
return current!;
124-
}
118+
// RelationshipMeta get _top {
119+
// RelationshipMeta? current = this;
120+
// while (current?.parent != null) {
121+
// current = current!.parent;
122+
// }
123+
// return current!;
124+
// }
125125

126126
RelationshipMeta<T> clone({RelationshipMeta? parent}) {
127127
final meta = RelationshipMeta<T>(

0 commit comments

Comments
 (0)