Messy code to store samples and test that out, better errors to come
This commit is contained in:
parent
7616cbd4ca
commit
0599148543
|
@ -0,0 +1,3 @@
|
||||||
|
DROP TABLE samples_tags;
|
||||||
|
DROP TABLE tags;
|
||||||
|
DROP TABLE samples;
|
|
@ -0,0 +1,20 @@
|
||||||
|
CREATE TABLE samples (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||||
|
name VARCHAR NOT NULL,
|
||||||
|
path VARCHAR NOT NULL,
|
||||||
|
bpm REAL,
|
||||||
|
key VARCHAR
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE tags (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||||
|
name VARCHAR NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE samples_tags (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||||
|
sample_id INTEGER NOT NULL,
|
||||||
|
tag_id INTEGER NOT NULL,
|
||||||
|
FOREIGN KEY (sample_id) REFERENCES samples (id),
|
||||||
|
FOREIGN KEY (tag_id) REFERENCES tags (id)
|
||||||
|
);
|
|
@ -0,0 +1,14 @@
|
||||||
|
use sample_amp::{tag_terms::TagSuggestions, *};
|
||||||
|
use std::{env, path::Path};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let suggestions =
|
||||||
|
TagSuggestions::read_from_file("tag_terms.txt").expect("expected tag file to load");
|
||||||
|
|
||||||
|
let connection = &mut establish_connection();
|
||||||
|
|
||||||
|
let file_str = env::args().nth(1).expect("Need just one argument.");
|
||||||
|
let tags = suggestions.get_suggestions(&file_str);
|
||||||
|
let sample = add_sample(connection, Path::new(&file_str), tags);
|
||||||
|
dbg!(sample);
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
fn main() {
|
||||||
|
let connection = &mut establish_connection();
|
||||||
|
println!(
|
||||||
|
"Found tags: {}",
|
||||||
|
list_tags(connection).iter().map(|t| &t.name).join(", ")
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
use itertools::Itertools;
|
||||||
|
use sample_amp::{establish_connection, list_tags};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let connection = &mut establish_connection();
|
||||||
|
println!(
|
||||||
|
"Found tags: {}",
|
||||||
|
list_tags(connection).iter().map(|t| &t.name).join(", ")
|
||||||
|
);
|
||||||
|
}
|
82
src/lib.rs
82
src/lib.rs
|
@ -1,8 +1,9 @@
|
||||||
use diesel::prelude::*;
|
use diesel::prelude::*;
|
||||||
use dotenvy::dotenv;
|
use dotenvy::dotenv;
|
||||||
use std::env;
|
use models::{NewSample, Sample, Tag};
|
||||||
|
use std::{env, path::Path};
|
||||||
|
|
||||||
use crate::models::{Library, NewLibrary};
|
use crate::models::{Library, NewLibrary, NewSampleTag, NewTag, SampleTag};
|
||||||
|
|
||||||
pub mod models;
|
pub mod models;
|
||||||
pub mod schema;
|
pub mod schema;
|
||||||
|
@ -27,3 +28,80 @@ pub fn create_library(conn: &mut SqliteConnection, name: &str) -> Library {
|
||||||
.get_result(conn)
|
.get_result(conn)
|
||||||
.expect("Error saving new post")
|
.expect("Error saving new post")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_tag<'a>(conn: &mut SqliteConnection, tag: &'a str) -> Option<Tag> {
|
||||||
|
use crate::schema::tags::dsl::*;
|
||||||
|
tags.filter(name.eq(&tag))
|
||||||
|
.select(Tag::as_select())
|
||||||
|
.first(conn)
|
||||||
|
.ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn list_tags(conn: &mut SqliteConnection) -> Vec<Tag> {
|
||||||
|
use crate::schema::tags::dsl::*;
|
||||||
|
tags.select(Tag::as_select())
|
||||||
|
.get_results(conn)
|
||||||
|
.expect("can't list tags")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn samples_with_tag<'a>(conn: &mut SqliteConnection, tag: &'a str) -> Vec<Sample> {
|
||||||
|
let tag = get_tag(conn, tag).expect("Expected tag to exist...");
|
||||||
|
|
||||||
|
let sample_ids = SampleTag::belonging_to(&tag).select(schema::samples_tags::sample_id);
|
||||||
|
schema::samples::table
|
||||||
|
.filter(schema::samples::id.eq_any(sample_ids))
|
||||||
|
.select(Sample::as_select())
|
||||||
|
.get_results(conn)
|
||||||
|
.expect("expected sample")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_sample<'a>(
|
||||||
|
conn: &mut SqliteConnection,
|
||||||
|
path: &Path,
|
||||||
|
tags: impl Iterator<Item = &'a String>,
|
||||||
|
) -> (Sample, Vec<Tag>) {
|
||||||
|
use crate::schema::{samples, samples_tags, tags};
|
||||||
|
|
||||||
|
let name = path.file_name().expect("expected file name");
|
||||||
|
let new_sample = NewSample {
|
||||||
|
name: &name.to_string_lossy(),
|
||||||
|
path: &path.to_string_lossy(),
|
||||||
|
bpm: None,
|
||||||
|
key: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
let sample = diesel::insert_into(samples::table)
|
||||||
|
.values(&new_sample)
|
||||||
|
.returning(Sample::as_returning())
|
||||||
|
.get_result(conn)
|
||||||
|
.expect("Error saving new sample");
|
||||||
|
|
||||||
|
let tags: Vec<Tag> = tags
|
||||||
|
.into_iter()
|
||||||
|
.map(|tag_name| {
|
||||||
|
let tag = get_tag(conn, tag_name).unwrap_or_else(|| {
|
||||||
|
let tag = NewTag { name: tag_name };
|
||||||
|
diesel::insert_into(tags::table)
|
||||||
|
.values(&tag)
|
||||||
|
.returning(Tag::as_returning())
|
||||||
|
.get_result(conn)
|
||||||
|
.expect("Error saving tag")
|
||||||
|
});
|
||||||
|
|
||||||
|
let sample_tag = NewSampleTag {
|
||||||
|
tag_id: tag.id,
|
||||||
|
sample_id: sample.id,
|
||||||
|
};
|
||||||
|
|
||||||
|
diesel::insert_into(samples_tags::table)
|
||||||
|
.values(&sample_tag)
|
||||||
|
.returning(SampleTag::as_returning())
|
||||||
|
.get_result(conn)
|
||||||
|
.expect("Error adding sample_tag");
|
||||||
|
|
||||||
|
tag
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
(sample, tags)
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use super::schema::libraries;
|
use super::schema::{libraries, samples, samples_tags, tags};
|
||||||
use diesel::prelude::*;
|
use diesel::prelude::*;
|
||||||
|
|
||||||
#[derive(Queryable, Selectable)]
|
#[derive(Debug, Queryable, Selectable)]
|
||||||
#[diesel(table_name = libraries)]
|
#[diesel(table_name = libraries)]
|
||||||
#[diesel(check_for_backend(diesel::sqlite::Sqlite))]
|
#[diesel(check_for_backend(diesel::sqlite::Sqlite))]
|
||||||
pub struct Library {
|
pub struct Library {
|
||||||
|
@ -9,8 +9,57 @@ pub struct Library {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Insertable)]
|
#[derive(Debug, Insertable)]
|
||||||
#[diesel(table_name = libraries)]
|
#[diesel(table_name = libraries)]
|
||||||
pub struct NewLibrary<'a> {
|
pub struct NewLibrary<'a> {
|
||||||
pub name: &'a str,
|
pub name: &'a str,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Identifiable, Queryable, Selectable)]
|
||||||
|
#[diesel(table_name = samples)]
|
||||||
|
pub struct Sample {
|
||||||
|
pub id: i32,
|
||||||
|
pub name: String,
|
||||||
|
pub path: String,
|
||||||
|
pub bpm: Option<f32>,
|
||||||
|
pub key: Option<String>, // For now this seems to be reasonable, instead of creating a giant enum.
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Insertable)]
|
||||||
|
#[diesel(table_name = samples)]
|
||||||
|
pub struct NewSample<'a> {
|
||||||
|
pub name: &'a str,
|
||||||
|
pub path: &'a str,
|
||||||
|
pub bpm: Option<f32>,
|
||||||
|
pub key: Option<&'a str>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Identifiable, Queryable, Selectable)]
|
||||||
|
#[diesel(table_name = tags)]
|
||||||
|
pub struct Tag {
|
||||||
|
pub id: i32,
|
||||||
|
pub name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Insertable)]
|
||||||
|
#[diesel(table_name = tags)]
|
||||||
|
pub struct NewTag<'a> {
|
||||||
|
pub name: &'a str,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Identifiable, Associations, Queryable, Selectable)]
|
||||||
|
#[diesel(belongs_to(Sample))]
|
||||||
|
#[diesel(belongs_to(Tag))]
|
||||||
|
#[diesel(table_name = samples_tags)]
|
||||||
|
pub struct SampleTag {
|
||||||
|
pub id: i32,
|
||||||
|
pub sample_id: i32,
|
||||||
|
pub tag_id: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Insertable)]
|
||||||
|
#[diesel(table_name = samples_tags)]
|
||||||
|
pub struct NewSampleTag {
|
||||||
|
pub sample_id: i32,
|
||||||
|
pub tag_id: i32,
|
||||||
|
}
|
||||||
|
|
|
@ -6,3 +6,33 @@ diesel::table! {
|
||||||
name -> Text,
|
name -> Text,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
diesel::table! {
|
||||||
|
samples (id) {
|
||||||
|
id -> Integer,
|
||||||
|
name -> Text,
|
||||||
|
path -> Text,
|
||||||
|
bpm -> Nullable<Float>,
|
||||||
|
key -> Nullable<Text>,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
diesel::table! {
|
||||||
|
samples_tags (id) {
|
||||||
|
id -> Integer,
|
||||||
|
sample_id -> Integer,
|
||||||
|
tag_id -> Integer,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
diesel::table! {
|
||||||
|
tags (id) {
|
||||||
|
id -> Integer,
|
||||||
|
name -> Text,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
diesel::joinable!(samples_tags -> samples (sample_id));
|
||||||
|
diesel::joinable!(samples_tags -> tags (tag_id));
|
||||||
|
|
||||||
|
diesel::allow_tables_to_appear_in_same_query!(libraries, samples, samples_tags, tags,);
|
||||||
|
|
|
@ -54,13 +54,10 @@ impl TagSuggestions {
|
||||||
self.map.get(input).unwrap_or(input)
|
self.map.get(input).unwrap_or(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_suggestions<'a>(
|
pub fn get_suggestions<'a>(&'a self, input: &'a str) -> impl Iterator<Item = &String> {
|
||||||
&'a self,
|
input
|
||||||
input_list: impl IntoIterator<Item = &'a str>,
|
.split([' ', std::path::MAIN_SEPARATOR, '_', '-', '.']) // todo: pascal case detection
|
||||||
) -> impl Iterator<Item = &String> {
|
.filter_map(|i| self.map.get(&i.to_lowercase()))
|
||||||
input_list
|
|
||||||
.into_iter()
|
|
||||||
.filter_map(|i| self.map.get(i))
|
|
||||||
.unique()
|
.unique()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue