2020-09-28 14:15:59 +02:00
|
|
|
use super::models::*;
|
|
|
|
|
use super::schema::*;
|
|
|
|
|
use super::tables::*;
|
|
|
|
|
use diesel::prelude::*;
|
|
|
|
|
|
|
|
|
|
embed_migrations!();
|
|
|
|
|
|
|
|
|
|
pub struct Database {
|
|
|
|
|
c: SqliteConnection,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Database {
|
|
|
|
|
pub fn new(path: &str) -> Database {
|
|
|
|
|
let c = SqliteConnection::establish(path)
|
|
|
|
|
.expect(&format!("Failed to connect to database at \"{}\"!", path));
|
|
|
|
|
|
|
|
|
|
diesel::sql_query("PRAGMA foreign_keys = ON;")
|
|
|
|
|
.execute(&c)
|
|
|
|
|
.expect("Failed to activate foreign key support!");
|
|
|
|
|
|
|
|
|
|
embedded_migrations::run(&c).expect("Failed to run migrations!");
|
|
|
|
|
|
|
|
|
|
Database { c: c }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn update_person(&self, person: Person) {
|
2020-10-10 09:58:38 +02:00
|
|
|
self.defer_foreign_keys();
|
|
|
|
|
self.c
|
|
|
|
|
.transaction(|| {
|
|
|
|
|
diesel::replace_into(persons::table)
|
|
|
|
|
.values(person)
|
|
|
|
|
.execute(&self.c)
|
|
|
|
|
})
|
2020-09-28 14:15:59 +02:00
|
|
|
.expect("Failed to insert person!");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn get_person(&self, id: i64) -> Option<Person> {
|
|
|
|
|
persons::table
|
|
|
|
|
.filter(persons::id.eq(id))
|
|
|
|
|
.load::<Person>(&self.c)
|
|
|
|
|
.expect("Error loading person!")
|
|
|
|
|
.first()
|
|
|
|
|
.cloned()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn delete_person(&self, id: i64) {
|
|
|
|
|
diesel::delete(persons::table.filter(persons::id.eq(id)))
|
|
|
|
|
.execute(&self.c)
|
|
|
|
|
.expect("Failed to delete person!");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn get_persons(&self) -> Vec<Person> {
|
|
|
|
|
persons::table
|
|
|
|
|
.load::<Person>(&self.c)
|
|
|
|
|
.expect("Error loading persons!")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn update_instrument(&self, instrument: Instrument) {
|
2020-10-10 09:58:38 +02:00
|
|
|
self.defer_foreign_keys();
|
|
|
|
|
self.c
|
|
|
|
|
.transaction(|| {
|
|
|
|
|
diesel::replace_into(instruments::table)
|
|
|
|
|
.values(instrument)
|
|
|
|
|
.execute(&self.c)
|
|
|
|
|
})
|
2020-09-28 14:15:59 +02:00
|
|
|
.expect("Failed to insert instrument!");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn get_instrument(&self, id: i64) -> Option<Instrument> {
|
|
|
|
|
instruments::table
|
|
|
|
|
.filter(instruments::id.eq(id))
|
|
|
|
|
.load::<Instrument>(&self.c)
|
|
|
|
|
.expect("Error loading instrument!")
|
|
|
|
|
.first()
|
|
|
|
|
.cloned()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn delete_instrument(&self, id: i64) {
|
|
|
|
|
diesel::delete(instruments::table.filter(instruments::id.eq(id)))
|
|
|
|
|
.execute(&self.c)
|
|
|
|
|
.expect("Failed to delete instrument!");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn get_instruments(&self) -> Vec<Instrument> {
|
|
|
|
|
instruments::table
|
|
|
|
|
.load::<Instrument>(&self.c)
|
|
|
|
|
.expect("Error loading instruments!")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn update_work(&self, work_insertion: WorkInsertion) {
|
|
|
|
|
let id = work_insertion.work.id;
|
|
|
|
|
|
2020-10-10 09:58:38 +02:00
|
|
|
self.defer_foreign_keys();
|
|
|
|
|
self.c
|
|
|
|
|
.transaction(|| {
|
|
|
|
|
self.delete_work(id);
|
|
|
|
|
|
|
|
|
|
diesel::insert_into(works::table)
|
|
|
|
|
.values(work_insertion.work)
|
|
|
|
|
.execute(&self.c)?;
|
|
|
|
|
|
|
|
|
|
for instrument_id in work_insertion.instrument_ids {
|
|
|
|
|
diesel::insert_into(instrumentations::table)
|
|
|
|
|
.values(Instrumentation {
|
|
|
|
|
id: rand::random(),
|
|
|
|
|
work: id,
|
|
|
|
|
instrument: instrument_id,
|
|
|
|
|
})
|
|
|
|
|
.execute(&self.c)?;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for part_insertion in work_insertion.parts {
|
|
|
|
|
let part_id = part_insertion.part.id;
|
|
|
|
|
|
|
|
|
|
diesel::insert_into(work_parts::table)
|
|
|
|
|
.values(part_insertion.part)
|
|
|
|
|
.execute(&self.c)?;
|
|
|
|
|
|
|
|
|
|
for instrument_id in part_insertion.instrument_ids {
|
|
|
|
|
diesel::insert_into(part_instrumentations::table)
|
|
|
|
|
.values(PartInstrumentation {
|
|
|
|
|
id: rand::random(),
|
|
|
|
|
work_part: part_id,
|
|
|
|
|
instrument: instrument_id,
|
|
|
|
|
})
|
|
|
|
|
.execute(&self.c)?;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for section in work_insertion.sections {
|
|
|
|
|
diesel::insert_into(work_sections::table)
|
|
|
|
|
.values(section)
|
|
|
|
|
.execute(&self.c)?;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
diesel::result::QueryResult::Ok(())
|
|
|
|
|
})
|
|
|
|
|
.expect("Failed to update work!");
|
2020-09-28 14:15:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn get_work(&self, id: i64) -> Option<Work> {
|
|
|
|
|
works::table
|
|
|
|
|
.filter(works::id.eq(id))
|
|
|
|
|
.load::<Work>(&self.c)
|
|
|
|
|
.expect("Error loading work!")
|
|
|
|
|
.first()
|
|
|
|
|
.cloned()
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-28 20:09:49 +02:00
|
|
|
pub fn get_work_description_for_work(&self, work: &Work) -> WorkDescription {
|
2020-09-28 14:15:59 +02:00
|
|
|
WorkDescription {
|
|
|
|
|
id: work.id,
|
|
|
|
|
composer: self
|
|
|
|
|
.get_person(work.composer)
|
|
|
|
|
.expect("Could not find composer for work!"),
|
2020-09-28 20:09:49 +02:00
|
|
|
title: work.title.clone(),
|
2020-09-28 14:15:59 +02:00
|
|
|
instruments: instrumentations::table
|
|
|
|
|
.filter(instrumentations::work.eq(work.id))
|
|
|
|
|
.load::<Instrumentation>(&self.c)
|
|
|
|
|
.expect("Failed to load instrumentations!")
|
|
|
|
|
.iter()
|
|
|
|
|
.map(|instrumentation| {
|
2020-10-09 20:23:54 +02:00
|
|
|
self.get_instrument(instrumentation.instrument)
|
2020-09-28 14:15:59 +02:00
|
|
|
.expect("Could not find instrument for instrumentation!")
|
|
|
|
|
})
|
|
|
|
|
.collect(),
|
|
|
|
|
parts: work_parts::table
|
|
|
|
|
.filter(work_parts::work.eq(work.id))
|
|
|
|
|
.load::<WorkPart>(&self.c)
|
|
|
|
|
.expect("Failed to load work parts!")
|
|
|
|
|
.iter()
|
|
|
|
|
.map(|work_part| WorkPartDescription {
|
|
|
|
|
composer: match work_part.composer {
|
|
|
|
|
Some(composer) => Some(
|
|
|
|
|
self.get_person(composer)
|
|
|
|
|
.expect("Could not find composer for work part!"),
|
|
|
|
|
),
|
|
|
|
|
None => None,
|
|
|
|
|
},
|
|
|
|
|
title: work_part.title.clone(),
|
|
|
|
|
instruments: part_instrumentations::table
|
|
|
|
|
.filter(part_instrumentations::work_part.eq(work_part.id))
|
|
|
|
|
.load::<PartInstrumentation>(&self.c)
|
|
|
|
|
.expect("Failed to load part instrumentations!")
|
|
|
|
|
.iter()
|
|
|
|
|
.map(|part_instrumentation| {
|
2020-10-09 20:23:54 +02:00
|
|
|
self.get_instrument(part_instrumentation.instrument)
|
2020-09-28 14:15:59 +02:00
|
|
|
.expect("Could not find instrument for part instrumentation!")
|
|
|
|
|
})
|
|
|
|
|
.collect(),
|
|
|
|
|
})
|
|
|
|
|
.collect(),
|
|
|
|
|
sections: work_sections::table
|
|
|
|
|
.filter(work_sections::work.eq(work.id))
|
|
|
|
|
.load::<WorkSection>(&self.c)
|
|
|
|
|
.expect("Failed to load work sections!")
|
|
|
|
|
.iter()
|
|
|
|
|
.map(|section| WorkSectionDescription {
|
|
|
|
|
title: section.title.clone(),
|
|
|
|
|
before_index: section.before_index,
|
|
|
|
|
})
|
|
|
|
|
.collect(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn get_work_description(&self, id: i64) -> Option<WorkDescription> {
|
|
|
|
|
match self.get_work(id) {
|
2020-09-28 20:09:49 +02:00
|
|
|
Some(work) => Some(self.get_work_description_for_work(&work)),
|
2020-09-28 14:15:59 +02:00
|
|
|
None => None,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn delete_work(&self, id: i64) {
|
|
|
|
|
diesel::delete(works::table.filter(works::id.eq(id)))
|
|
|
|
|
.execute(&self.c)
|
|
|
|
|
.expect("Failed to delete work!");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn get_works(&self, composer_id: i64) -> Vec<Work> {
|
|
|
|
|
works::table
|
|
|
|
|
.filter(works::composer.eq(composer_id))
|
|
|
|
|
.load::<Work>(&self.c)
|
|
|
|
|
.expect("Error loading works!")
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-28 20:09:49 +02:00
|
|
|
pub fn get_work_descriptions(&self, composer_id: i64) -> Vec<WorkDescription> {
|
|
|
|
|
self.get_works(composer_id)
|
|
|
|
|
.iter()
|
|
|
|
|
.map(|work| self.get_work_description_for_work(work))
|
|
|
|
|
.collect()
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-28 14:15:59 +02:00
|
|
|
pub fn update_ensemble(&self, ensemble: Ensemble) {
|
2020-10-10 09:58:38 +02:00
|
|
|
self.defer_foreign_keys();
|
|
|
|
|
self.c
|
|
|
|
|
.transaction(|| {
|
|
|
|
|
diesel::replace_into(ensembles::table)
|
|
|
|
|
.values(ensemble)
|
|
|
|
|
.execute(&self.c)
|
|
|
|
|
})
|
2020-09-28 14:15:59 +02:00
|
|
|
.expect("Failed to insert ensemble!");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn get_ensemble(&self, id: i64) -> Option<Ensemble> {
|
|
|
|
|
ensembles::table
|
|
|
|
|
.filter(ensembles::id.eq(id))
|
|
|
|
|
.load::<Ensemble>(&self.c)
|
|
|
|
|
.expect("Error loading ensemble!")
|
|
|
|
|
.first()
|
|
|
|
|
.cloned()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn delete_ensemble(&self, id: i64) {
|
|
|
|
|
diesel::delete(ensembles::table.filter(ensembles::id.eq(id)))
|
|
|
|
|
.execute(&self.c)
|
|
|
|
|
.expect("Failed to delete ensemble!");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn get_ensembles(&self) -> Vec<Ensemble> {
|
|
|
|
|
ensembles::table
|
|
|
|
|
.load::<Ensemble>(&self.c)
|
|
|
|
|
.expect("Error loading ensembles!")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn update_recording(&self, recording_insertion: RecordingInsertion) {
|
|
|
|
|
let id = recording_insertion.recording.id;
|
|
|
|
|
|
2020-10-10 09:58:38 +02:00
|
|
|
self.defer_foreign_keys();
|
|
|
|
|
self.c
|
|
|
|
|
.transaction(|| {
|
|
|
|
|
self.delete_recording(id);
|
2020-09-28 14:15:59 +02:00
|
|
|
|
2020-10-10 09:58:38 +02:00
|
|
|
diesel::insert_into(recordings::table)
|
|
|
|
|
.values(recording_insertion.recording)
|
|
|
|
|
.execute(&self.c)?;
|
2020-09-28 14:15:59 +02:00
|
|
|
|
2020-10-10 09:58:38 +02:00
|
|
|
for performance in recording_insertion.performances {
|
|
|
|
|
diesel::insert_into(performances::table)
|
|
|
|
|
.values(performance)
|
|
|
|
|
.execute(&self.c)?;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
diesel::result::QueryResult::Ok(())
|
|
|
|
|
})
|
|
|
|
|
.expect("Failed to insert performance!");
|
2020-09-28 14:15:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn get_recording(&self, id: i64) -> Option<Recording> {
|
|
|
|
|
recordings::table
|
|
|
|
|
.filter(recordings::id.eq(id))
|
|
|
|
|
.load::<Recording>(&self.c)
|
|
|
|
|
.expect("Error loading recording!")
|
|
|
|
|
.first()
|
|
|
|
|
.cloned()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn get_recording_description_for_recording(
|
|
|
|
|
&self,
|
|
|
|
|
recording: Recording,
|
|
|
|
|
) -> RecordingDescription {
|
|
|
|
|
RecordingDescription {
|
|
|
|
|
id: recording.id,
|
|
|
|
|
work: self
|
|
|
|
|
.get_work_description(recording.work)
|
|
|
|
|
.expect("Could not find work for recording!"),
|
|
|
|
|
comment: recording.comment,
|
|
|
|
|
performances: performances::table
|
|
|
|
|
.filter(performances::recording.eq(recording.id))
|
|
|
|
|
.load::<Performance>(&self.c)
|
|
|
|
|
.expect("Failed to load performances!")
|
|
|
|
|
.iter()
|
|
|
|
|
.map(|performance| PerformanceDescription {
|
|
|
|
|
person: performance.person.map(|id| {
|
|
|
|
|
self.get_person(id)
|
|
|
|
|
.expect("Could not find person for performance!")
|
|
|
|
|
}),
|
|
|
|
|
ensemble: performance.ensemble.map(|id| {
|
|
|
|
|
self.get_ensemble(id)
|
|
|
|
|
.expect("Could not find ensemble for performance!")
|
|
|
|
|
}),
|
|
|
|
|
role: performance.role.map(|id| {
|
|
|
|
|
self.get_instrument(id)
|
|
|
|
|
.expect("Could not find role for performance!")
|
|
|
|
|
}),
|
|
|
|
|
})
|
|
|
|
|
.collect(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn get_recording_description(&self, id: i64) -> Option<RecordingDescription> {
|
|
|
|
|
match self.get_recording(id) {
|
|
|
|
|
Some(recording) => Some(self.get_recording_description_for_recording(recording)),
|
|
|
|
|
None => None,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-10 00:22:45 +02:00
|
|
|
pub fn get_recordings_for_person(&self, id: i64) -> Vec<RecordingDescription> {
|
|
|
|
|
let recordings = recordings::table
|
|
|
|
|
.inner_join(performances::table.on(performances::recording.eq(recordings::id)))
|
|
|
|
|
.inner_join(persons::table.on(persons::id.nullable().eq(performances::person)))
|
|
|
|
|
.filter(persons::id.eq(id))
|
|
|
|
|
.select(recordings::table::all_columns())
|
|
|
|
|
.load::<Recording>(&self.c)
|
|
|
|
|
.expect("Error loading recordings for person!");
|
|
|
|
|
|
|
|
|
|
recordings
|
|
|
|
|
.iter()
|
|
|
|
|
.map(|recording| self.get_recording_description_for_recording(recording.clone()))
|
|
|
|
|
.collect()
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-10 12:01:22 +02:00
|
|
|
pub fn get_recordings_for_ensemble(&self, id: i64) -> Vec<RecordingDescription> {
|
|
|
|
|
let recordings = recordings::table
|
|
|
|
|
.inner_join(performances::table.on(performances::recording.eq(recordings::id)))
|
|
|
|
|
.inner_join(ensembles::table.on(ensembles::id.nullable().eq(performances::ensemble)))
|
|
|
|
|
.filter(ensembles::id.eq(id))
|
|
|
|
|
.select(recordings::table::all_columns())
|
|
|
|
|
.load::<Recording>(&self.c)
|
|
|
|
|
.expect("Error loading recordings for ensemble!");
|
|
|
|
|
|
|
|
|
|
recordings
|
|
|
|
|
.iter()
|
|
|
|
|
.map(|recording| self.get_recording_description_for_recording(recording.clone()))
|
|
|
|
|
.collect()
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-28 14:15:59 +02:00
|
|
|
pub fn delete_recording(&self, id: i64) {
|
|
|
|
|
diesel::delete(recordings::table.filter(recordings::id.eq(id)))
|
|
|
|
|
.execute(&self.c)
|
|
|
|
|
.expect("Failed to delete recording!");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn get_recordings(&self, work_id: i64) -> Vec<Recording> {
|
|
|
|
|
recordings::table
|
|
|
|
|
.filter(recordings::work.eq(work_id))
|
|
|
|
|
.load::<Recording>(&self.c)
|
|
|
|
|
.expect("Error loading recordings!")
|
|
|
|
|
}
|
2020-10-10 09:58:38 +02:00
|
|
|
|
|
|
|
|
fn defer_foreign_keys(&self) {
|
|
|
|
|
diesel::sql_query("PRAGMA defer_foreign_keys = ON;")
|
|
|
|
|
.execute(&self.c)
|
|
|
|
|
.expect("Failed to enable defer_foreign_keys_pragma!");
|
|
|
|
|
}
|
2020-09-28 14:15:59 +02:00
|
|
|
}
|