From 437e30933ae93e8b1e8a6a67395228154c93cbb9 Mon Sep 17 00:00:00 2001 From: Elias Projahn Date: Tue, 3 Dec 2019 12:03:39 +0100 Subject: [PATCH] Add basic database for works and composers This includes tables for persons, instruments and works as well as some queries and functions to work with them. The generated code should be ignored by Git for now. I also added a section to README.md explaining how to handle code generation. --- .gitignore | 1 + README.md | 7 ++++++ lib/database.dart | 40 +++++++++++++++++++++++++++++++++++ lib/database.moor | 54 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 102 insertions(+) create mode 100644 lib/database.dart create mode 100644 lib/database.moor diff --git a/.gitignore b/.gitignore index b8c2bac..1ab8bb9 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,7 @@ .vscode/ # Flutter/Dart/Pub related +**/*.g.dart **/doc/api/ .dart_tool/ pubspec.lock diff --git a/README.md b/README.md index a6030b3..170139d 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,13 @@ The classical music player and organizer. https://musicus.org +## Hacking + +You can use the following command to automatically update generated code while +working on Musicus: + +`flutter pub run build_runner watch` + ## License Musicus is free and open source software: you can redistribute it and/or modify diff --git a/lib/database.dart b/lib/database.dart new file mode 100644 index 0000000..9101386 --- /dev/null +++ b/lib/database.dart @@ -0,0 +1,40 @@ +import 'package:moor_flutter/moor_flutter.dart'; + +part 'database.g.dart'; + +@UseMoor( + include: { + 'database.moor', + }, +) +class Database extends _$Database { + Database(String fileName) + : super(FlutterQueryExecutor.inDatabaseFolder(path: fileName)); + + @override + int get schemaVersion => 0; + + Future updatePerson(Person person) async { + await into(persons).insert(person); + } + + Future updateInstrument(Instrument instrument) async { + await into(instruments).insert(instrument); + } + + Future updateWork(Work work, List instrumentIds) async { + await transaction(() async { + await into(works).insert(work); + + await (delete(instrumentations)..where((i) => i.work.equals(work.id))) + .go(); + + await into(instrumentations).insertAll(instrumentIds + .map((id) => Instrumentation( + work: work.id, + instrument: id, + )) + .toList()); + }); + } +} diff --git a/lib/database.moor b/lib/database.moor new file mode 100644 index 0000000..256e89d --- /dev/null +++ b/lib/database.moor @@ -0,0 +1,54 @@ +CREATE TABLE persons ( + id INTEGER NOT NULL PRIMARY KEY, + first_name TEXT NOT NULL, + last_name TEXT NOT NULL +); + +CREATE TABLE instruments ( + id INTEGER NOT NULL PRIMARY KEY, + name TEXT NOT NULL +); + +CREATE TABLE works ( + id INTEGER NOT NULL PRIMARY KEY, + composer INTEGER REFERENCES persons(id), + title TEXT NOT NULL, + part_of INTEGER REFERENCES works(id) ON DELETE CASCADE, + part_index INTEGER +); + +CREATE TABLE instrumentations ( + work INTEGER NOT NULL REFERENCES works(id) ON DELETE CASCADE, + instrument INTEGER NOT NULL REFERENCES instruments(id) ON DELETE CASCADE +); + +allPersons: +SELECT * FROM persons ORDER BY last_name; + +personById: +SELECT * FROM persons WHERE id = :id LIMIT 1; + +allInstruments: +SELECT * FROM instruments ORDER BY name; + +instrumentById: +SELECT * FROM instruments WHERE id = :id LIMIT 1; + +workById: +SELECT * FROM works WHERE id = :id LIMIT 1; + +worksByComposer: +WITH RECURSIVE work_parts(id, part_of) AS ( + SELECT id, part_of FROM works WHERE composer = :composerId + UNION ALL + SELECT works.id, works.part_of FROM works + JOIN work_parts ON works.id = work_parts.part_of +) +SELECT works.* FROM works + JOIN work_parts ON works.id = work_parts.id + WHERE work_parts.part_of IS NULL; + +instrumentsByWork: +SELECT instruments.* FROM instrumentations + JOIN instruments ON instrumentations.instrument=instruments.id + WHERE instrumentations.work = :workId;