database: Update schema

This commit is contained in:
Elias Projahn 2022-05-06 15:12:10 +02:00
parent 25b0a9f436
commit 9e485eac11
3 changed files with 157 additions and 136 deletions

View file

@ -37,7 +37,6 @@ class MusicusClientDatabase extends _$MusicusClientDatabase {
@required DatabaseConnection connection, @required DatabaseConnection connection,
}) : super.connect(connection); }) : super.connect(connection);
/// Get all available persons. /// Get all available persons.
/// ///
/// This will return a list of [pageSize] persons. You can get another page /// This will return a list of [pageSize] persons. You can get another page
@ -78,37 +77,20 @@ class MusicusClientDatabase extends _$MusicusClientDatabase {
Future<WorkInfo> getWorkInfo(Work work) async { Future<WorkInfo> getWorkInfo(Work work) async {
final id = work.id; final id = work.id;
final composers = await partComposersByWork(id).get(); final composer = await personById(work.composer).getSingle();
composers.insert(0, await personById(work.composer).getSingle());
final instruments = await instrumentsByWork(id).get(); final instruments = await instrumentsByWork(id).get();
final parts = await partsByWork(id).get();
final List<PartInfo> parts = [];
for (final part in await partsByWork(id).get()) {
parts.add(PartInfo(
part: part,
composer: part.composer != null
? await personById(part.composer).getSingle()
: null,
instruments: await instrumentsByWorkPart(part.id).get(),
));
}
final List<WorkSection> sections = [];
for (final section in await sectionsByWork(id).get()) {
sections.add(section);
}
return WorkInfo( return WorkInfo(
work: work, work: work,
composer: composer,
instruments: instruments, instruments: instruments,
composers: composers,
parts: parts, parts: parts,
sections: sections,
); );
} }
/// Get all available information on a work. /// Get all available information on a work.
Future<WorkInfo> getWork(int id) async { Future<WorkInfo> getWork(String id) async {
final work = await workById(id).getSingle(); final work = await workById(id).getSingle();
return await getWorkInfo(work); return await getWorkInfo(work);
} }
@ -118,7 +100,7 @@ class MusicusClientDatabase extends _$MusicusClientDatabase {
/// This will return a list of [pageSize] results. You can get another page /// This will return a list of [pageSize] results. You can get another page
/// using the [page] parameter. If a non empty [search] string is provided, /// using the [page] parameter. If a non empty [search] string is provided,
/// the works will be filtered using that string. /// the works will be filtered using that string.
Future<List<WorkInfo>> getWorks(int personId, Future<List<WorkInfo>> getWorks(String personId,
[int page, String search]) async { [int page, String search]) async {
final offset = page != null ? page * pageSize : 0; final offset = page != null ? page * pageSize : 0;
List<Work> works; List<Work> works;
@ -183,7 +165,7 @@ class MusicusClientDatabase extends _$MusicusClientDatabase {
} }
/// Get all available information on a recording. /// Get all available information on a recording.
Future<RecordingInfo> getRecording(int id) async { Future<RecordingInfo> getRecording(String id) async {
final recording = await recordingById(id).getSingle(); final recording = await recordingById(id).getSingle();
return await getRecordingInfo(recording); return await getRecordingInfo(recording);
} }
@ -192,7 +174,7 @@ class MusicusClientDatabase extends _$MusicusClientDatabase {
/// ///
/// This will return a list of [pageSize] recordings. You can get the other /// This will return a list of [pageSize] recordings. You can get the other
/// pages using the [page] parameter. /// pages using the [page] parameter.
Future<List<RecordingInfo>> getRecordings(int workId, [int page]) async { Future<List<RecordingInfo>> getRecordings(String workId, [int page]) async {
final offset = page != null ? page * pageSize : 0; final offset = page != null ? page * pageSize : 0;
final recordings = await recordingsByWork(workId, pageSize, offset).get(); final recordings = await recordingsByWork(workId, pageSize, offset).get();

View file

@ -1,139 +1,200 @@
CREATE TABLE persons ( CREATE TABLE IF NOT EXISTS "persons" (
id INTEGER NOT NULL PRIMARY KEY, "id" TEXT NOT NULL PRIMARY KEY,
first_name TEXT NOT NULL, "first_name" TEXT NOT NULL,
last_name TEXT NOT NULL "last_name" TEXT NOT NULL,
"last_used" BIGINT,
"last_played" BIGINT
); );
-- This represents real instruments as well as other roles that can be played CREATE TABLE IF NOT EXISTS "instruments" (
-- in a recording. "id" TEXT NOT NULL PRIMARY KEY,
CREATE TABLE instruments ( "name" TEXT NOT NULL,
id INTEGER NOT NULL PRIMARY KEY, "last_used" BIGINT,
name TEXT NOT NULL "last_played" BIGINT
); );
CREATE TABLE works ( CREATE TABLE IF NOT EXISTS "works" (
id INTEGER NOT NULL PRIMARY KEY, "id" TEXT NOT NULL PRIMARY KEY,
composer INTEGER REFERENCES persons(id) ON DELETE SET NULL, "composer" TEXT NOT NULL REFERENCES "persons"("id"),
title TEXT NOT NULL "title" TEXT NOT NULL,
"last_used" BIGINT,
"last_played" BIGINT
); );
CREATE TABLE instrumentations ( CREATE TABLE IF NOT EXISTS "instrumentations" (
work INTEGER NOT NULL REFERENCES works(id) ON DELETE CASCADE, "id" BIGINT NOT NULL PRIMARY KEY,
instrument INTEGER NOT NULL REFERENCES instruments(id) ON DELETE CASCADE "work" TEXT NOT NULL REFERENCES "works"("id") ON DELETE CASCADE,
"instrument" TEXT NOT NULL REFERENCES "instruments"("id") ON DELETE CASCADE
); );
CREATE TABLE work_parts ( CREATE TABLE IF NOT EXISTS "work_parts" (
id INTEGER NOT NULL PRIMARY KEY, "id" BIGINT NOT NULL PRIMARY KEY,
composer INTEGER REFERENCES persons(id) ON DELETE SET NULL, "work" TEXT NOT NULL REFERENCES "works"("id") ON DELETE CASCADE,
title TEXT NOT NULL, "part_index" BIGINT NOT NULL,
part_of INTEGER NOT NULL REFERENCES works(id) ON DELETE CASCADE, "title" TEXT NOT NULL
part_index INTEGER NOT NULL
); );
CREATE TABLE part_instrumentations ( CREATE TABLE IF NOT EXISTS "work_sections" (
work_part INTEGER NOT NULL REFERENCES works(id) ON DELETE CASCADE, "id" BIGINT NOT NULL PRIMARY KEY,
instrument INTEGER NOT NULL REFERENCES instruments(id) ON DELETE CASCADE "work" TEXT NOT NULL REFERENCES "works"("id") ON DELETE CASCADE,
"title" TEXT NOT NULL,
"before_index" BIGINT NOT NULL
); );
CREATE TABLE work_sections ( CREATE TABLE IF NOT EXISTS "ensembles" (
id INTEGER NOT NULL PRIMARY KEY, "id" TEXT NOT NULL PRIMARY KEY,
work INTEGER NOT NULL REFERENCES works(id) ON DELETE CASCADE, "name" TEXT NOT NULL,
title TEXT NOT NULL, "last_used" BIGINT,
before_part_index INTEGER NOT NULL "last_played" BIGINT
); );
CREATE TABLE ensembles ( CREATE TABLE IF NOT EXISTS "recordings" (
id INTEGER NOT NULL PRIMARY KEY, "id" TEXT NOT NULL PRIMARY KEY,
name TEXT NOT NULL "work" TEXT NOT NULL REFERENCES "works"("id"),
"comment" TEXT NOT NULL,
"last_used" BIGINT,
"last_played" BIGINT
); );
CREATE TABLE recordings ( CREATE TABLE IF NOT EXISTS "performances" (
id INTEGER NOT NULL PRIMARY KEY, "id" BIGINT NOT NULL PRIMARY KEY,
work INTEGER REFERENCES works(id) ON DELETE SET NULL, "recording" TEXT NOT NULL REFERENCES "recordings"("id") ON DELETE CASCADE,
comment TEXT NOT NULL "person" TEXT REFERENCES "persons"("id"),
"ensemble" TEXT REFERENCES "ensembles"("id"),
"role" TEXT REFERENCES "instruments"("id")
); );
CREATE TABLE performances ( CREATE TABLE IF NOT EXISTS "mediums" (
recording INTEGER NOT NULL REFERENCES recordings(id) ON DELETE CASCADE, "id" TEXT NOT NULL PRIMARY KEY,
person INTEGER REFERENCES persons(id) ON DELETE CASCADE, "name" TEXT NOT NULL,
ensemble INTEGER REFERENCES ensembles(id) ON DELETE CASCADE, "discid" TEXT,
role INTEGER REFERENCES instruments(id) ON DELETE SET NULL "last_used" BIGINT,
"last_played" BIGINT
);
CREATE TABLE IF NOT EXISTS "tracks" (
"id" TEXT NOT NULL PRIMARY KEY,
"medium" TEXT NOT NULL REFERENCES "mediums"("id") ON DELETE CASCADE,
"index" INTEGER NOT NULL,
"recording" TEXT NOT NULL REFERENCES "recordings"("id"),
"work_parts" TEXT NOT NULL,
"source_index" INTEGER NOT NULL,
"path" TEXT NOT NULL,
"last_used" BIGINT,
"last_played" BIGINT
); );
allPersons: allPersons:
SELECT * FROM persons ORDER BY last_name, first_name SELECT *
LIMIT :limit OFFSET :offset; FROM persons
ORDER BY last_name,
first_name
LIMIT :limit OFFSET :offset;
searchPersons: searchPersons:
SELECT * FROM persons WHERE last_name LIKE :search SELECT *
ORDER BY last_name, first_name LIMIT :limit OFFSET :offset; FROM persons
WHERE last_name LIKE :search
ORDER BY last_name,
first_name
LIMIT :limit OFFSET :offset;
personById: personById:
SELECT * FROM persons WHERE id = :id LIMIT 1; SELECT *
FROM persons
WHERE id = :id
LIMIT 1;
allInstruments: allInstruments:
SELECT * FROM instruments ORDER BY name LIMIT :limit OFFSET :offset; SELECT *
FROM instruments
ORDER BY name
LIMIT :limit OFFSET :offset;
searchInstruments: searchInstruments:
SELECT * FROM instruments WHERE name LIKE :search ORDER BY name SELECT *
LIMIT :limit OFFSET :offset; FROM instruments
WHERE name LIKE :search
ORDER BY name
LIMIT :limit OFFSET :offset;
instrumentById: instrumentById:
SELECT * FROM instruments WHERE id = :id LIMIT 1; SELECT *
FROM instruments
WHERE id = :id
LIMIT 1;
workById: workById:
SELECT * FROM works WHERE id = :id LIMIT 1; SELECT *
FROM works
WHERE id = :id
LIMIT 1;
partsByWork: partsByWork:
SELECT * FROM work_parts WHERE part_of = :id ORDER BY part_index; SELECT *
FROM work_parts
sectionsByWork: WHERE work = :id
SELECT * FROM work_sections WHERE work = :id ORDER BY before_part_index; ORDER BY part_index;
worksByComposer: worksByComposer:
SELECT DISTINCT works.* FROM works SELECT *
JOIN work_parts ON work_parts.part_of = works.id FROM works
WHERE works.composer = :id OR work_parts.composer = :id WHERE composer = :id
ORDER BY works.title LIMIT :limit OFFSET :offset; ORDER BY title
LIMIT :limit OFFSET :offset;
searchWorksByComposer: searchWorksByComposer:
SELECT DISTINCT works.* FROM works SELECT *
JOIN work_parts ON work_parts.part_of = works.id FROM works
WHERE (works.composer = :id OR work_parts.composer = :id) WHERE composer = :id
AND works.title LIKE :search AND title LIKE :search
ORDER BY works.title LIMIT :limit OFFSET :offset; ORDER BY title
LIMIT :limit OFFSET :offset;
partComposersByWork:
SELECT DISTINCT persons.* FROM persons
JOIN work_parts ON work_parts.composer = persons.id
WHERE work_parts.part_of = :id;
instrumentsByWork: instrumentsByWork:
SELECT instruments.* FROM instrumentations SELECT instruments.*
FROM instrumentations
JOIN instruments ON instrumentations.instrument = instruments.id JOIN instruments ON instrumentations.instrument = instruments.id
WHERE instrumentations.work = :workId; WHERE instrumentations.work = :workId;
instrumentsByWorkPart:
SELECT instruments.* FROM part_instrumentations
JOIN instruments ON part_instrumentations.instrument = instruments.id
WHERE part_instrumentations.work_part = :id;
allEnsembles: allEnsembles:
SELECT * FROM ensembles ORDER BY name LIMIT :limit OFFSET :offset; SELECT *
FROM ensembles
ORDER BY name
LIMIT :limit OFFSET :offset;
searchEnsembles: searchEnsembles:
SELECT * FROM ensembles WHERE name LIKE :search ORDER BY name SELECT *
LIMIT :limit OFFSET :offset; FROM ensembles
WHERE name LIKE :search
ORDER BY name
LIMIT :limit OFFSET :offset;
ensembleById: ensembleById:
SELECT * FROM ensembles WHERE id = :id LIMIT 1; SELECT *
FROM ensembles
WHERE id = :id
LIMIT 1;
recordingById: recordingById:
SELECT * FROM recordings WHERE id = :id; SELECT *
FROM recordings
WHERE id = :id;
recordingsByWork: recordingsByWork:
SELECT * FROM recordings WHERE work = :id ORDER BY id SELECT *
LIMIT :limit OFFSET :offset; FROM recordings
WHERE work = :id
ORDER BY id
LIMIT :limit OFFSET :offset;
performancesByRecording: performancesByRecording:
SELECT * FROM performances WHERE recording = :id; SELECT *
FROM performances
WHERE recording = :id;
tracksByRecording:
SELECT *
FROM tracks
WHERE recording = :id
ORDER BY "index";

View file

@ -1,27 +1,5 @@
import 'database.dart'; import 'database.dart';
/// A bundle of all available information on a work part.
class PartInfo {
/// The work part itself.
final WorkPart part;
/// A list of instruments.
///
/// This will include the instruments, that are specific to this part.
final List<Instrument> instruments;
/// The composer of this part.
///
/// This is null, if this part doesn't have a specific composer.
final Person composer;
PartInfo({
this.part,
this.instruments,
this.composer,
});
}
/// A bundle information on a work. /// A bundle information on a work.
/// ///
/// This includes all available information except for recordings of this work. /// This includes all available information except for recordings of this work.
@ -35,11 +13,11 @@ class WorkInfo {
/// parts. /// parts.
final List<Instrument> instruments; final List<Instrument> instruments;
/// A list of persons, which will include all part composers. /// The work's composer.
final List<Person> composers; final Person composer;
/// All available information on the work parts. /// All available information on the work parts.
final List<PartInfo> parts; final List<WorkPart> parts;
/// The sections of this work. /// The sections of this work.
final List<WorkSection> sections; final List<WorkSection> sections;
@ -47,7 +25,7 @@ class WorkInfo {
WorkInfo({ WorkInfo({
this.work, this.work,
this.instruments, this.instruments,
this.composers, this.composer,
this.parts, this.parts,
this.sections, this.sections,
}); });