mirror of https://github.com/AMT-Cheif/drift.git
Create a real example for the web backend
This commit is contained in:
parent
c806a4a7b1
commit
311a47c704
|
@ -0,0 +1,11 @@
|
|||
# See https://github.com/dart-lang/build/tree/master/build_web_compilers#configuration
|
||||
targets:
|
||||
$default:
|
||||
builders:
|
||||
build_web_compilers|entrypoint:
|
||||
generate_for:
|
||||
- web/**.dart
|
||||
options:
|
||||
dart2js_args:
|
||||
- --no-source-maps
|
||||
- -O4
|
|
@ -0,0 +1,47 @@
|
|||
import 'package:moor/moor_web.dart';
|
||||
|
||||
part 'database.g.dart';
|
||||
|
||||
const int _doneEntriesCount = 20;
|
||||
|
||||
@DataClassName('Entry')
|
||||
class TodoEntries extends Table {
|
||||
IntColumn get id => integer().autoIncrement()();
|
||||
|
||||
TextColumn get content => text()();
|
||||
BoolColumn get done => boolean().withDefault(const Constant(false))();
|
||||
}
|
||||
|
||||
@UseMoor(tables: [
|
||||
TodoEntries
|
||||
], queries: {
|
||||
'hiddenEntryCount': 'SELECT COUNT(*) - $_doneEntriesCount AS entries '
|
||||
'FROM todo_entries WHERE done'
|
||||
})
|
||||
class Database extends _$Database {
|
||||
Database() : super(WebDatabase('app', logStatements: true));
|
||||
|
||||
@override
|
||||
final int schemaVersion = 1;
|
||||
|
||||
Stream<List<Entry>> incompleteEntries() {
|
||||
return (select(todoEntries)..where((e) => not(e.done))).watch();
|
||||
}
|
||||
|
||||
Stream<List<Entry>> newestDoneEntries() {
|
||||
return (select(todoEntries)
|
||||
..where((e) => e.done)
|
||||
..orderBy(
|
||||
[(e) => OrderingTerm(expression: e.id, mode: OrderingMode.desc)])
|
||||
..limit(_doneEntriesCount))
|
||||
.watch();
|
||||
}
|
||||
|
||||
Future createTodoEntry(String desc) {
|
||||
return into(todoEntries).insert(TodoEntriesCompanion(content: Value(desc)));
|
||||
}
|
||||
|
||||
Future setCompleted(Entry entry, bool done) {
|
||||
return update(todoEntries).write(entry.copyWith(done: done));
|
||||
}
|
||||
}
|
|
@ -7,32 +7,30 @@ part of 'database.dart';
|
|||
// **************************************************************************
|
||||
|
||||
// ignore_for_file: unnecessary_brace_in_string_interps
|
||||
class TodoEntry extends DataClass implements Insertable<TodoEntry> {
|
||||
class Entry extends DataClass implements Insertable<Entry> {
|
||||
final int id;
|
||||
final String content;
|
||||
final DateTime creationDate;
|
||||
TodoEntry(
|
||||
{@required this.id, @required this.content, @required this.creationDate});
|
||||
factory TodoEntry.fromData(Map<String, dynamic> data, GeneratedDatabase db,
|
||||
final bool done;
|
||||
Entry({@required this.id, @required this.content, @required this.done});
|
||||
factory Entry.fromData(Map<String, dynamic> data, GeneratedDatabase db,
|
||||
{String prefix}) {
|
||||
final effectivePrefix = prefix ?? '';
|
||||
final intType = db.typeSystem.forDartType<int>();
|
||||
final stringType = db.typeSystem.forDartType<String>();
|
||||
final dateTimeType = db.typeSystem.forDartType<DateTime>();
|
||||
return TodoEntry(
|
||||
final boolType = db.typeSystem.forDartType<bool>();
|
||||
return Entry(
|
||||
id: intType.mapFromDatabaseResponse(data['${effectivePrefix}id']),
|
||||
content:
|
||||
stringType.mapFromDatabaseResponse(data['${effectivePrefix}content']),
|
||||
creationDate: dateTimeType
|
||||
.mapFromDatabaseResponse(data['${effectivePrefix}creation_date']),
|
||||
done: boolType.mapFromDatabaseResponse(data['${effectivePrefix}done']),
|
||||
);
|
||||
}
|
||||
factory TodoEntry.fromJson(Map<String, dynamic> json,
|
||||
factory Entry.fromJson(Map<String, dynamic> json,
|
||||
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
|
||||
return TodoEntry(
|
||||
return Entry(
|
||||
id: serializer.fromJson<int>(json['id']),
|
||||
content: serializer.fromJson<String>(json['content']),
|
||||
creationDate: serializer.fromJson<DateTime>(json['creationDate']),
|
||||
done: serializer.fromJson<bool>(json['done']),
|
||||
);
|
||||
}
|
||||
@override
|
||||
|
@ -41,64 +39,61 @@ class TodoEntry extends DataClass implements Insertable<TodoEntry> {
|
|||
return {
|
||||
'id': serializer.toJson<int>(id),
|
||||
'content': serializer.toJson<String>(content),
|
||||
'creationDate': serializer.toJson<DateTime>(creationDate),
|
||||
'done': serializer.toJson<bool>(done),
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
T createCompanion<T extends UpdateCompanion<TodoEntry>>(bool nullToAbsent) {
|
||||
T createCompanion<T extends UpdateCompanion<Entry>>(bool nullToAbsent) {
|
||||
return TodoEntriesCompanion(
|
||||
id: id == null && nullToAbsent ? const Value.absent() : Value(id),
|
||||
content: content == null && nullToAbsent
|
||||
? const Value.absent()
|
||||
: Value(content),
|
||||
creationDate: creationDate == null && nullToAbsent
|
||||
? const Value.absent()
|
||||
: Value(creationDate),
|
||||
done: done == null && nullToAbsent ? const Value.absent() : Value(done),
|
||||
) as T;
|
||||
}
|
||||
|
||||
TodoEntry copyWith({int id, String content, DateTime creationDate}) =>
|
||||
TodoEntry(
|
||||
Entry copyWith({int id, String content, bool done}) => Entry(
|
||||
id: id ?? this.id,
|
||||
content: content ?? this.content,
|
||||
creationDate: creationDate ?? this.creationDate,
|
||||
done: done ?? this.done,
|
||||
);
|
||||
@override
|
||||
String toString() {
|
||||
return (StringBuffer('TodoEntry(')
|
||||
return (StringBuffer('Entry(')
|
||||
..write('id: $id, ')
|
||||
..write('content: $content, ')
|
||||
..write('creationDate: $creationDate')
|
||||
..write('done: $done')
|
||||
..write(')'))
|
||||
.toString();
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => $mrjf($mrjc(
|
||||
$mrjc($mrjc(0, id.hashCode), content.hashCode), creationDate.hashCode));
|
||||
int get hashCode => $mrjf(
|
||||
$mrjc($mrjc($mrjc(0, id.hashCode), content.hashCode), done.hashCode));
|
||||
@override
|
||||
bool operator ==(other) =>
|
||||
identical(this, other) ||
|
||||
(other is TodoEntry &&
|
||||
(other is Entry &&
|
||||
other.id == id &&
|
||||
other.content == content &&
|
||||
other.creationDate == creationDate);
|
||||
other.done == done);
|
||||
}
|
||||
|
||||
class TodoEntriesCompanion extends UpdateCompanion<TodoEntry> {
|
||||
class TodoEntriesCompanion extends UpdateCompanion<Entry> {
|
||||
final Value<int> id;
|
||||
final Value<String> content;
|
||||
final Value<DateTime> creationDate;
|
||||
final Value<bool> done;
|
||||
const TodoEntriesCompanion({
|
||||
this.id = const Value.absent(),
|
||||
this.content = const Value.absent(),
|
||||
this.creationDate = const Value.absent(),
|
||||
this.done = const Value.absent(),
|
||||
});
|
||||
}
|
||||
|
||||
class $TodoEntriesTable extends TodoEntries
|
||||
with TableInfo<$TodoEntriesTable, TodoEntry> {
|
||||
with TableInfo<$TodoEntriesTable, Entry> {
|
||||
final GeneratedDatabase _db;
|
||||
final String _alias;
|
||||
$TodoEntriesTable(this._db, [this._alias]);
|
||||
|
@ -122,19 +117,17 @@ class $TodoEntriesTable extends TodoEntries
|
|||
);
|
||||
}
|
||||
|
||||
final VerificationMeta _creationDateMeta =
|
||||
const VerificationMeta('creationDate');
|
||||
GeneratedDateTimeColumn _creationDate;
|
||||
final VerificationMeta _doneMeta = const VerificationMeta('done');
|
||||
GeneratedBoolColumn _done;
|
||||
@override
|
||||
GeneratedDateTimeColumn get creationDate =>
|
||||
_creationDate ??= _constructCreationDate();
|
||||
GeneratedDateTimeColumn _constructCreationDate() {
|
||||
return GeneratedDateTimeColumn('creation_date', $tableName, false,
|
||||
defaultValue: currentDateAndTime);
|
||||
GeneratedBoolColumn get done => _done ??= _constructDone();
|
||||
GeneratedBoolColumn _constructDone() {
|
||||
return GeneratedBoolColumn('done', $tableName, false,
|
||||
defaultValue: const Constant(true));
|
||||
}
|
||||
|
||||
@override
|
||||
List<GeneratedColumn> get $columns => [id, content, creationDate];
|
||||
List<GeneratedColumn> get $columns => [id, content, done];
|
||||
@override
|
||||
$TodoEntriesTable get asDslTable => this;
|
||||
@override
|
||||
|
@ -156,13 +149,11 @@ class $TodoEntriesTable extends TodoEntries
|
|||
} else if (content.isRequired && isInserting) {
|
||||
context.missing(_contentMeta);
|
||||
}
|
||||
if (d.creationDate.present) {
|
||||
if (d.done.present) {
|
||||
context.handle(
|
||||
_creationDateMeta,
|
||||
creationDate.isAcceptableValue(
|
||||
d.creationDate.value, _creationDateMeta));
|
||||
} else if (creationDate.isRequired && isInserting) {
|
||||
context.missing(_creationDateMeta);
|
||||
_doneMeta, done.isAcceptableValue(d.done.value, _doneMeta));
|
||||
} else if (done.isRequired && isInserting) {
|
||||
context.missing(_doneMeta);
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
@ -170,9 +161,9 @@ class $TodoEntriesTable extends TodoEntries
|
|||
@override
|
||||
Set<GeneratedColumn> get $primaryKey => {id};
|
||||
@override
|
||||
TodoEntry map(Map<String, dynamic> data, {String tablePrefix}) {
|
||||
Entry map(Map<String, dynamic> data, {String tablePrefix}) {
|
||||
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : null;
|
||||
return TodoEntry.fromData(data, _db, prefix: effectivePrefix);
|
||||
return Entry.fromData(data, _db, prefix: effectivePrefix);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -184,9 +175,8 @@ class $TodoEntriesTable extends TodoEntries
|
|||
if (d.content.present) {
|
||||
map['content'] = Variable<String, StringType>(d.content.value);
|
||||
}
|
||||
if (d.creationDate.present) {
|
||||
map['creation_date'] =
|
||||
Variable<DateTime, DateTimeType>(d.creationDate.value);
|
||||
if (d.done.present) {
|
||||
map['done'] = Variable<bool, BoolType>(d.done.value);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
@ -197,10 +187,38 @@ class $TodoEntriesTable extends TodoEntries
|
|||
}
|
||||
}
|
||||
|
||||
class HiddenEntryCountResult {
|
||||
final int entries;
|
||||
HiddenEntryCountResult({
|
||||
this.entries,
|
||||
});
|
||||
}
|
||||
|
||||
abstract class _$Database extends GeneratedDatabase {
|
||||
_$Database(QueryExecutor e) : super(const SqlTypeSystem.withDefaults(), e);
|
||||
$TodoEntriesTable _todoEntries;
|
||||
$TodoEntriesTable get todoEntries => _todoEntries ??= $TodoEntriesTable(this);
|
||||
HiddenEntryCountResult _rowToHiddenEntryCountResult(QueryRow row) {
|
||||
return HiddenEntryCountResult(
|
||||
entries: row.readInt('entries'),
|
||||
);
|
||||
}
|
||||
|
||||
Future<List<HiddenEntryCountResult>> hiddenEntryCount(
|
||||
{QueryEngine operateOn}) {
|
||||
return (operateOn ?? this).customSelect(
|
||||
'SELECT COUNT(*) - 20 AS entries FROM todo_entries WHERE done',
|
||||
variables: []).then((rows) => rows.map(_rowToHiddenEntryCountResult).toList());
|
||||
}
|
||||
|
||||
Stream<List<HiddenEntryCountResult>> watchHiddenEntryCount() {
|
||||
return customSelectStream(
|
||||
'SELECT COUNT(*) - 20 AS entries FROM todo_entries WHERE done',
|
||||
variables: [],
|
||||
readsFrom: {todoEntries})
|
||||
.map((rows) => rows.map(_rowToHiddenEntryCountResult).toList());
|
||||
}
|
||||
|
||||
@override
|
||||
List<TableInfo> get allTables => [todoEntries];
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
import 'package:example_web/widgets/home_screen.dart';
|
||||
import 'package:flutter_web/material.dart';
|
||||
|
||||
import 'database/database.dart';
|
||||
|
||||
void launchApp() {
|
||||
runApp(
|
||||
DatabaseProvider(
|
||||
db: Database(),
|
||||
child: MaterialApp(
|
||||
title: 'Moor web!',
|
||||
home: HomeScreen(),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
class DatabaseProvider extends InheritedWidget {
|
||||
final Database db;
|
||||
|
||||
DatabaseProvider({@required this.db, @required Widget child})
|
||||
: super(child: child);
|
||||
|
||||
@override
|
||||
bool updateShouldNotify(InheritedWidget oldWidget) => false;
|
||||
|
||||
static Database provide(BuildContext ctx) {
|
||||
return (ctx.inheritFromWidgetOfExactType(DatabaseProvider)
|
||||
as DatabaseProvider)
|
||||
?.db;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
import 'package:flutter_web/material.dart';
|
||||
|
||||
import '../main.dart';
|
||||
|
||||
class CreateEntryBar extends StatefulWidget {
|
||||
@override
|
||||
_CreateEntryBarState createState() => _CreateEntryBarState();
|
||||
}
|
||||
|
||||
class _CreateEntryBarState extends State<CreateEntryBar> {
|
||||
final TextEditingController _controller = TextEditingController();
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_controller.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: TextField(
|
||||
controller: _controller,
|
||||
decoration: InputDecoration(
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
icon: Icon(Icons.add),
|
||||
onPressed: () {
|
||||
final text = _controller.text;
|
||||
_controller.clear();
|
||||
|
||||
DatabaseProvider.provide(context).createTodoEntry(text);
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
import 'package:example_web/database/database.dart';
|
||||
import 'package:flutter_web/material.dart';
|
||||
|
||||
import '../main.dart';
|
||||
|
||||
class SliverEntryList extends StatelessWidget {
|
||||
final Stream<List<Entry>> entries;
|
||||
|
||||
const SliverEntryList({Key key, this.entries}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return StreamBuilder<List<Entry>>(
|
||||
stream: entries,
|
||||
builder: (context, snapshot) {
|
||||
final entries = snapshot.data ?? const [];
|
||||
|
||||
return SliverList(
|
||||
delegate: SliverChildBuilderDelegate(
|
||||
(context, index) {
|
||||
final entry = entries[index];
|
||||
|
||||
return _EntryCard(
|
||||
key: ObjectKey(entry.id),
|
||||
entry: entry,
|
||||
);
|
||||
},
|
||||
childCount: entries.length,
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _EntryCard extends StatelessWidget {
|
||||
final Entry entry;
|
||||
|
||||
const _EntryCard({Key key, this.entry}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Card(
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Text(entry.content),
|
||||
Spacer(),
|
||||
Checkbox(
|
||||
value: entry.done,
|
||||
onChanged: (checked) {
|
||||
DatabaseProvider.provide(context).setCompleted(entry, checked);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
import 'package:example_web/main.dart';
|
||||
import 'package:example_web/widgets/entry_list.dart';
|
||||
import 'package:flutter_web/material.dart';
|
||||
|
||||
import 'create_entry_bar.dart';
|
||||
|
||||
class HomeScreen extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final db = DatabaseProvider.provide(context);
|
||||
final headerTheme = Theme.of(context).textTheme.title;
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Moor Web'),
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16.0),
|
||||
child: Center(
|
||||
child: ConstrainedBox(
|
||||
constraints: const BoxConstraints(maxWidth: 800),
|
||||
child: CustomScrollView(
|
||||
slivers: <Widget>[
|
||||
SliverToBoxAdapter(
|
||||
child: CreateEntryBar(),
|
||||
),
|
||||
SliverToBoxAdapter(
|
||||
child: Text('In progress', style: headerTheme),
|
||||
),
|
||||
SliverEntryList(
|
||||
entries: db.incompleteEntries(),
|
||||
),
|
||||
SliverToBoxAdapter(
|
||||
child: Text('Complete', style: headerTheme),
|
||||
),
|
||||
SliverEntryList(
|
||||
entries: db.newestDoneEntries(),
|
||||
),
|
||||
SliverToBoxAdapter(
|
||||
child: StreamBuilder<List<int>>(
|
||||
builder: (context, snapshot) {
|
||||
final hiddenCount = snapshot?.data?.single ?? 0;
|
||||
|
||||
return Text('Not showing $hiddenCount older entries');
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -6,6 +6,7 @@ environment:
|
|||
|
||||
dependencies:
|
||||
moor: ^1.4.0
|
||||
flutter_web: any
|
||||
|
||||
dev_dependencies:
|
||||
moor_generator:
|
||||
|
@ -17,3 +18,12 @@ dependency_overrides:
|
|||
path: ../
|
||||
moor_generator:
|
||||
path: ../../moor_generator
|
||||
|
||||
flutter_web_ui:
|
||||
git:
|
||||
url: https://github.com/flutter/flutter_web.git
|
||||
path: packages/flutter_web_ui
|
||||
flutter_web:
|
||||
git:
|
||||
url: https://github.com/flutter/flutter_web.git
|
||||
path: packages/flutter_web
|
|
@ -0,0 +1,10 @@
|
|||
[
|
||||
{
|
||||
"family": "MaterialIcons",
|
||||
"fonts": [
|
||||
{
|
||||
"asset": "https://fonts.gstatic.com/s/materialicons/v42/flUhRq6tzZclQEJ-Vdg-IuiaDsNcIhQ8tQ.woff2"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
|
@ -1,28 +0,0 @@
|
|||
import 'package:moor/moor.dart';
|
||||
|
||||
part 'database.g.dart';
|
||||
|
||||
@DataClassName('TodoEntry')
|
||||
class TodoEntries extends Table {
|
||||
IntColumn get id => integer().autoIncrement()();
|
||||
|
||||
TextColumn get content => text()();
|
||||
DateTimeColumn get creationDate =>
|
||||
dateTime().withDefault(currentDateAndTime)();
|
||||
}
|
||||
|
||||
@UseMoor(tables: [TodoEntries])
|
||||
class Database extends _$Database {
|
||||
Database(QueryExecutor e) : super(e);
|
||||
|
||||
@override
|
||||
int get schemaVersion => 1;
|
||||
|
||||
Stream<List<TodoEntry>> watchEntries() {
|
||||
return select(todoEntries).watch();
|
||||
}
|
||||
|
||||
Future<int> insert(String text) {
|
||||
return into(todoEntries).insert(TodoEntriesCompanion(content: Value(text)));
|
||||
}
|
||||
}
|
|
@ -1,27 +1,11 @@
|
|||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="scaffolded-by" content="https://github.com/google/stagehand">
|
||||
<title>example_web</title>
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
<link rel="icon" href="favicon.ico">
|
||||
|
||||
<script defer src="main.dart.js"></script>
|
||||
<meta charset="UTF-8">
|
||||
<title></title>
|
||||
<script defer src="main.dart.js" type="application/javascript"></script>
|
||||
<script src="sql-wasm.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="output"></div>
|
||||
|
||||
<form id="add_todo_form">
|
||||
<input type="text" id="description" />
|
||||
<input type="submit">
|
||||
</form>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -1,18 +1,7 @@
|
|||
import 'dart:html';
|
||||
|
||||
import 'package:moor/moor_web.dart';
|
||||
|
||||
import 'database.dart';
|
||||
import 'package:example_web/main.dart';
|
||||
import 'package:flutter_web_ui/ui.dart' as ui;
|
||||
|
||||
void main() async {
|
||||
final db = Database(WebDatabase('database', logStatements: true));
|
||||
db.watchEntries().listen(print);
|
||||
|
||||
(querySelector('#add_todo_form') as FormElement).onSubmit.listen((e) {
|
||||
final content = querySelector('#description') as InputElement;
|
||||
e.preventDefault();
|
||||
|
||||
db.insert(content.value).then((insertId) => print('inserted #$insertId'));
|
||||
content.value = '';
|
||||
});
|
||||
await ui.webOnlyInitializePlatform();
|
||||
launchApp();
|
||||
}
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
@import url(https://fonts.googleapis.com/css?family=Roboto);
|
||||
|
||||
html, body {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: 'Roboto', sans-serif;
|
||||
}
|
||||
|
||||
#output {
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
}
|
|
@ -223,6 +223,11 @@ class WebDatabase extends _DatabaseUser {
|
|||
return databaseInfo.beforeOpenCallback(_BeforeOpenExecutor(_state),
|
||||
OpeningDetails(version, databaseInfo.schemaVersion));
|
||||
});
|
||||
|
||||
if (upgradeNeeded) {
|
||||
// assume that a schema version was written in an upgrade => save db
|
||||
_storeDb();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue