Remove OpGetter from sql context functionality
This commit is contained in:
parent
70950e0bc7
commit
9ea25c27de
5 changed files with 74 additions and 137 deletions
|
@ -63,7 +63,7 @@ pub trait MpsLanguageError: Display + Debug {
|
||||||
}
|
}
|
||||||
|
|
||||||
// RuntimeError builder components
|
// RuntimeError builder components
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
pub struct RuntimeMsg(pub String);
|
pub struct RuntimeMsg(pub String);
|
||||||
|
|
||||||
impl RuntimeMsg {
|
impl RuntimeMsg {
|
||||||
|
@ -76,6 +76,7 @@ impl RuntimeMsg {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
pub struct RuntimeOp(pub PseudoOp);
|
pub struct RuntimeOp(pub PseudoOp);
|
||||||
|
|
||||||
impl RuntimeOp {
|
impl RuntimeOp {
|
||||||
|
|
|
@ -9,8 +9,8 @@ use crate::MpsContext;
|
||||||
use crate::lang::repeated_tokens;
|
use crate::lang::repeated_tokens;
|
||||||
use crate::lang::utility::{assert_token, assert_token_raw};
|
use crate::lang::utility::{assert_token, assert_token_raw};
|
||||||
use crate::lang::MpsLanguageDictionary;
|
use crate::lang::MpsLanguageDictionary;
|
||||||
use crate::lang::SyntaxError;
|
|
||||||
use crate::lang::{MpsFunctionFactory, MpsFunctionStatementFactory, MpsIteratorItem, MpsOp};
|
use crate::lang::{MpsFunctionFactory, MpsFunctionStatementFactory, MpsIteratorItem, MpsOp};
|
||||||
|
use crate::lang::{PseudoOp, RuntimeOp, SyntaxError};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct SqlInitStatement {
|
pub struct SqlInitStatement {
|
||||||
|
@ -41,18 +41,16 @@ impl Iterator for SqlInitStatement {
|
||||||
type Item = MpsIteratorItem;
|
type Item = MpsIteratorItem;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
let pseudo_clone = self.clone();
|
|
||||||
// execute
|
// execute
|
||||||
match self
|
match self
|
||||||
.context
|
.context
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.database
|
.database
|
||||||
.init_with_params(&self.params, &mut move || {
|
.init_with_params(&self.params)
|
||||||
(Box::new(pseudo_clone.clone()) as Box<dyn MpsOp>).into()
|
{
|
||||||
}) {
|
|
||||||
Ok(_) => None,
|
Ok(_) => None,
|
||||||
Err(e) => Some(Err(e)),
|
Err(e) => Some(Err(e.with(RuntimeOp(PseudoOp::from_printable(self))))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,9 @@ use std::iter::Iterator;
|
||||||
use crate::lang::utility::assert_token;
|
use crate::lang::utility::assert_token;
|
||||||
use crate::lang::{
|
use crate::lang::{
|
||||||
MpsFunctionFactory, MpsFunctionStatementFactory, MpsIteratorItem, MpsLanguageDictionary, MpsOp,
|
MpsFunctionFactory, MpsFunctionStatementFactory, MpsIteratorItem, MpsLanguageDictionary, MpsOp,
|
||||||
|
PseudoOp,
|
||||||
};
|
};
|
||||||
use crate::lang::{RuntimeError, SyntaxError};
|
use crate::lang::{RuntimeError, RuntimeMsg, RuntimeOp, SyntaxError};
|
||||||
use crate::tokens::MpsToken;
|
use crate::tokens::MpsToken;
|
||||||
use crate::MpsContext;
|
use crate::MpsContext;
|
||||||
use crate::MpsItem;
|
use crate::MpsItem;
|
||||||
|
@ -16,12 +17,13 @@ use crate::MpsItem;
|
||||||
pub struct SqlStatement {
|
pub struct SqlStatement {
|
||||||
query: String,
|
query: String,
|
||||||
context: Option<MpsContext>,
|
context: Option<MpsContext>,
|
||||||
rows: Option<Vec<Result<MpsItem, RuntimeError>>>,
|
rows: Option<Vec<Result<MpsItem, RuntimeMsg>>>,
|
||||||
current: usize,
|
current: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SqlStatement {
|
impl SqlStatement {
|
||||||
fn get_item(&mut self, increment: bool) -> Option<MpsIteratorItem> {
|
fn get_item(&mut self, increment: bool) -> Option<MpsIteratorItem> {
|
||||||
|
let fake = PseudoOp::from_printable(self);
|
||||||
if let Some(rows) = &self.rows {
|
if let Some(rows) = &self.rows {
|
||||||
if increment {
|
if increment {
|
||||||
if self.current == rows.len() {
|
if self.current == rows.len() {
|
||||||
|
@ -33,19 +35,15 @@ impl SqlStatement {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
//Some(rows[self.current].clone())
|
//Some(rows[self.current].clone())
|
||||||
match &rows[self.current] {
|
match rows[self.current].clone() {
|
||||||
Ok(item) => Some(Ok(item.clone())),
|
Ok(item) => Some(Ok(item)),
|
||||||
Err(e) => Some(Err(RuntimeError {
|
Err(e) => Some(Err(e.with(RuntimeOp(fake)))),
|
||||||
line: e.line,
|
|
||||||
op: (Box::new(self.clone()) as Box<dyn MpsOp>).into(),
|
|
||||||
msg: e.msg.clone(),
|
|
||||||
})),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Some(Err(RuntimeError {
|
Some(Err(RuntimeError {
|
||||||
line: 0,
|
line: 0,
|
||||||
op: (Box::new(self.clone()) as Box<dyn MpsOp>).into(),
|
op: fake,
|
||||||
msg: "Context error: rows is None".to_string(),
|
msg: "Context error: rows is None".to_string(),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
@ -91,15 +89,13 @@ impl Iterator for SqlStatement {
|
||||||
// query has executed, return another result
|
// query has executed, return another result
|
||||||
self.get_item(true)
|
self.get_item(true)
|
||||||
} else {
|
} else {
|
||||||
let self_clone = self.clone();
|
let fake = PseudoOp::from_printable(self);
|
||||||
let ctx = self.context.as_mut().unwrap();
|
let ctx = self.context.as_mut().unwrap();
|
||||||
// query has not been executed yet
|
// query has not been executed yet
|
||||||
match ctx.database.raw(&self.query, &mut move || {
|
match ctx.database.raw(&self.query) {
|
||||||
(Box::new(self_clone.clone()) as Box<dyn MpsOp>).into()
|
|
||||||
}) {
|
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
self.rows = Some(Vec::with_capacity(0));
|
self.rows = Some(Vec::with_capacity(0));
|
||||||
Some(Err(e))
|
Some(Err(e.with(RuntimeOp(fake))))
|
||||||
}
|
}
|
||||||
Ok(rows) => {
|
Ok(rows) => {
|
||||||
self.rows = Some(rows);
|
self.rows = Some(rows);
|
||||||
|
|
|
@ -5,8 +5,9 @@ use std::iter::Iterator;
|
||||||
use crate::lang::utility::assert_token;
|
use crate::lang::utility::assert_token;
|
||||||
use crate::lang::{
|
use crate::lang::{
|
||||||
MpsFunctionFactory, MpsFunctionStatementFactory, MpsIteratorItem, MpsLanguageDictionary, MpsOp,
|
MpsFunctionFactory, MpsFunctionStatementFactory, MpsIteratorItem, MpsLanguageDictionary, MpsOp,
|
||||||
|
PseudoOp,
|
||||||
};
|
};
|
||||||
use crate::lang::{RuntimeError, SyntaxError};
|
use crate::lang::{RuntimeError, RuntimeMsg, RuntimeOp, SyntaxError};
|
||||||
use crate::tokens::MpsToken;
|
use crate::tokens::MpsToken;
|
||||||
use crate::MpsContext;
|
use crate::MpsContext;
|
||||||
use crate::MpsItem;
|
use crate::MpsItem;
|
||||||
|
@ -65,12 +66,13 @@ pub struct SimpleSqlStatement {
|
||||||
query: String,
|
query: String,
|
||||||
mode: QueryMode,
|
mode: QueryMode,
|
||||||
context: Option<MpsContext>,
|
context: Option<MpsContext>,
|
||||||
rows: Option<Vec<Result<MpsItem, RuntimeError>>>,
|
rows: Option<Vec<Result<MpsItem, RuntimeMsg>>>,
|
||||||
current: usize,
|
current: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SimpleSqlStatement {
|
impl SimpleSqlStatement {
|
||||||
fn get_item(&mut self, increment: bool) -> Option<MpsIteratorItem> {
|
fn get_item(&mut self, increment: bool) -> Option<MpsIteratorItem> {
|
||||||
|
let fake = PseudoOp::from_printable(self);
|
||||||
if let Some(rows) = &self.rows {
|
if let Some(rows) = &self.rows {
|
||||||
if increment {
|
if increment {
|
||||||
if self.current == rows.len() {
|
if self.current == rows.len() {
|
||||||
|
@ -82,19 +84,15 @@ impl SimpleSqlStatement {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
//Some(rows[self.current].clone())
|
//Some(rows[self.current].clone())
|
||||||
match &rows[self.current] {
|
match rows[self.current].clone() {
|
||||||
Ok(item) => Some(Ok(item.clone())),
|
Ok(item) => Some(Ok(item)),
|
||||||
Err(e) => Some(Err(RuntimeError {
|
Err(e) => Some(Err(e.with(RuntimeOp(fake)))),
|
||||||
line: e.line,
|
|
||||||
op: (Box::new(self.clone()) as Box<dyn MpsOp>).into(),
|
|
||||||
msg: e.msg.clone(),
|
|
||||||
})),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Some(Err(RuntimeError {
|
Some(Err(RuntimeError {
|
||||||
line: 0,
|
line: 0,
|
||||||
op: (Box::new(self.clone()) as Box<dyn MpsOp>).into(),
|
op: fake,
|
||||||
msg: "Context error: rows is None".to_string(),
|
msg: "Context error: rows is None".to_string(),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
@ -141,27 +139,19 @@ impl Iterator for SimpleSqlStatement {
|
||||||
// query has executed, return another result
|
// query has executed, return another result
|
||||||
self.get_item(true)
|
self.get_item(true)
|
||||||
} else {
|
} else {
|
||||||
let self_clone = self.clone();
|
let fake = PseudoOp::from_printable(self);
|
||||||
let ctx = self.context.as_mut().unwrap();
|
let ctx = self.context.as_mut().unwrap();
|
||||||
// query has not been executed yet
|
// query has not been executed yet
|
||||||
let query_result = match self.mode {
|
let query_result = match self.mode {
|
||||||
QueryMode::Artist => ctx.database.artist_like(&self.query, &mut move || {
|
QueryMode::Artist => ctx.database.artist_like(&self.query),
|
||||||
(Box::new(self_clone.clone()) as Box<dyn MpsOp>).into()
|
QueryMode::Album => ctx.database.album_like(&self.query),
|
||||||
}),
|
QueryMode::Song => ctx.database.song_like(&self.query),
|
||||||
QueryMode::Album => ctx.database.album_like(&self.query, &mut move || {
|
QueryMode::Genre => ctx.database.genre_like(&self.query),
|
||||||
(Box::new(self_clone.clone()) as Box<dyn MpsOp>).into()
|
|
||||||
}),
|
|
||||||
QueryMode::Song => ctx.database.song_like(&self.query, &mut move || {
|
|
||||||
(Box::new(self_clone.clone()) as Box<dyn MpsOp>).into()
|
|
||||||
}),
|
|
||||||
QueryMode::Genre => ctx.database.genre_like(&self.query, &mut move || {
|
|
||||||
(Box::new(self_clone.clone()) as Box<dyn MpsOp>).into()
|
|
||||||
}),
|
|
||||||
};
|
};
|
||||||
match query_result {
|
match query_result {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
self.rows = Some(Vec::with_capacity(0));
|
self.rows = Some(Vec::with_capacity(0));
|
||||||
Some(Err(e))
|
Some(Err(e.with(RuntimeOp(fake))))
|
||||||
}
|
}
|
||||||
Ok(rows) => {
|
Ok(rows) => {
|
||||||
self.rows = Some(rows);
|
self.rows = Some(rows);
|
||||||
|
|
|
@ -2,39 +2,33 @@ use core::fmt::Debug;
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
|
|
||||||
use crate::lang::db::*;
|
use crate::lang::db::*;
|
||||||
use crate::lang::RuntimeError;
|
use crate::lang::RuntimeMsg;
|
||||||
use crate::MpsItem;
|
use crate::MpsItem;
|
||||||
|
|
||||||
use super::OpGetter as QueryOp;
|
pub type QueryResult = Result<Vec<Result<MpsItem, RuntimeMsg>>, RuntimeMsg>;
|
||||||
|
|
||||||
pub type QueryResult = Result<Vec<Result<MpsItem, RuntimeError>>, RuntimeError>;
|
|
||||||
|
|
||||||
/// SQL querying functionality, loosely de-coupled from any specific SQL dialect (excluding raw call)
|
/// SQL querying functionality, loosely de-coupled from any specific SQL dialect (excluding raw call)
|
||||||
pub trait MpsDatabaseQuerier: Debug {
|
pub trait MpsDatabaseQuerier: Debug {
|
||||||
/// raw SQL call, assumed (but not guaranteed) to retrieved music items
|
/// raw SQL call, assumed (but not guaranteed) to retrieved music items
|
||||||
fn raw(&mut self, query: &str, op: &mut QueryOp) -> QueryResult;
|
fn raw(&mut self, query: &str) -> QueryResult;
|
||||||
|
|
||||||
/// get music, searching by artist name like `query`
|
/// get music, searching by artist name like `query`
|
||||||
fn artist_like(&mut self, query: &str, op: &mut QueryOp) -> QueryResult;
|
fn artist_like(&mut self, query: &str) -> QueryResult;
|
||||||
|
|
||||||
/// get music, searching by album title like `query`
|
/// get music, searching by album title like `query`
|
||||||
fn album_like(&mut self, query: &str, op: &mut QueryOp) -> QueryResult;
|
fn album_like(&mut self, query: &str) -> QueryResult;
|
||||||
|
|
||||||
/// get music, searching by song title like `query`
|
/// get music, searching by song title like `query`
|
||||||
fn song_like(&mut self, query: &str, op: &mut QueryOp) -> QueryResult;
|
fn song_like(&mut self, query: &str) -> QueryResult;
|
||||||
|
|
||||||
/// get music, searching by genre title like `query`
|
/// get music, searching by genre title like `query`
|
||||||
fn genre_like(&mut self, query: &str, op: &mut QueryOp) -> QueryResult;
|
fn genre_like(&mut self, query: &str) -> QueryResult;
|
||||||
|
|
||||||
/// connect to the SQL database with (optional) settings such as:
|
/// connect to the SQL database with (optional) settings such as:
|
||||||
/// `"folder" = "path"` - path to root music directory
|
/// `"folder" = "path"` - path to root music directory
|
||||||
/// `"database" = "uri"` - connection URI for database (for SQLite this is just a filepath)
|
/// `"database" = "uri"` - connection URI for database (for SQLite this is just a filepath)
|
||||||
/// `"generate" = "true"|"yes"|"false"|"no"` - whether to populate the database using the music directory
|
/// `"generate" = "true"|"yes"|"false"|"no"` - whether to populate the database using the music directory
|
||||||
fn init_with_params(
|
fn init_with_params(&mut self, params: &HashMap<String, String>) -> Result<(), RuntimeMsg>;
|
||||||
&mut self,
|
|
||||||
params: &HashMap<String, String>,
|
|
||||||
op: &mut QueryOp,
|
|
||||||
) -> Result<(), RuntimeError>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Debug)]
|
#[derive(Default, Debug)]
|
||||||
|
@ -44,124 +38,87 @@ pub struct MpsSQLiteExecutor {
|
||||||
|
|
||||||
impl MpsSQLiteExecutor {
|
impl MpsSQLiteExecutor {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn gen_db_maybe(&mut self, op: &mut QueryOp) -> Result<(), RuntimeError> {
|
fn gen_db_maybe(&mut self) -> Result<(), RuntimeMsg> {
|
||||||
if self.sqlite_connection.is_none() {
|
if self.sqlite_connection.is_none() {
|
||||||
// connection needs to be created
|
// connection needs to be created
|
||||||
match generate_default_db() {
|
match generate_default_db() {
|
||||||
Ok(conn) => {
|
Ok(conn) => {
|
||||||
self.sqlite_connection = Some(conn);
|
self.sqlite_connection = Some(conn);
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => return Err(RuntimeMsg(format!("SQL connection error: {}", e))),
|
||||||
return Err(RuntimeError {
|
|
||||||
line: 0,
|
|
||||||
op: op(),
|
|
||||||
msg: format!("SQL connection error: {}", e),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn music_query_single_param(
|
fn music_query_single_param(&mut self, query: &str, param: &str) -> QueryResult {
|
||||||
&mut self,
|
self.gen_db_maybe()?;
|
||||||
query: &str,
|
|
||||||
param: &str,
|
|
||||||
op: &mut QueryOp,
|
|
||||||
) -> QueryResult {
|
|
||||||
self.gen_db_maybe(op)?;
|
|
||||||
let conn = self.sqlite_connection.as_mut().unwrap();
|
let conn = self.sqlite_connection.as_mut().unwrap();
|
||||||
match perform_single_param_query(conn, query, param) {
|
match perform_single_param_query(conn, query, param) {
|
||||||
Ok(items) => Ok(items
|
Ok(items) => Ok(items
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|item| {
|
.map(|item| item.map_err(|e| RuntimeMsg(format!("SQL item mapping error: {}", e))))
|
||||||
item.map_err(|e| RuntimeError {
|
|
||||||
line: 0,
|
|
||||||
op: op(),
|
|
||||||
msg: format!("SQL item mapping error: {}", e),
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.collect()),
|
.collect()),
|
||||||
Err(e) => Err(RuntimeError {
|
Err(e) => Err(RuntimeMsg(e)),
|
||||||
line: 0,
|
|
||||||
op: op(),
|
|
||||||
msg: e,
|
|
||||||
}),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MpsDatabaseQuerier for MpsSQLiteExecutor {
|
impl MpsDatabaseQuerier for MpsSQLiteExecutor {
|
||||||
fn raw(&mut self, query: &str, op: &mut QueryOp) -> QueryResult {
|
fn raw(&mut self, query: &str) -> QueryResult {
|
||||||
self.gen_db_maybe(op)?;
|
self.gen_db_maybe()?;
|
||||||
let conn = self.sqlite_connection.as_mut().unwrap();
|
let conn = self.sqlite_connection.as_mut().unwrap();
|
||||||
// execute query
|
// execute query
|
||||||
match perform_query(conn, query) {
|
match perform_query(conn, query) {
|
||||||
Ok(items) => Ok(items
|
Ok(items) => Ok(items
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|item| {
|
.map(|item| item.map_err(|e| RuntimeMsg(format!("SQL item mapping error: {}", e))))
|
||||||
item.map_err(|e| RuntimeError {
|
|
||||||
line: 0,
|
|
||||||
op: op(),
|
|
||||||
msg: format!("SQL item mapping error: {}", e),
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.collect()),
|
.collect()),
|
||||||
Err(e) => Err(RuntimeError {
|
Err(e) => Err(RuntimeMsg(e)),
|
||||||
line: 0,
|
|
||||||
op: op(),
|
|
||||||
msg: e,
|
|
||||||
}),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn artist_like(&mut self, query: &str, op: &mut QueryOp) -> QueryResult {
|
fn artist_like(&mut self, query: &str) -> QueryResult {
|
||||||
let param = &format!("%{}%", query);
|
let param = &format!("%{}%", query);
|
||||||
let query_stmt = "SELECT songs.* FROM songs
|
let query_stmt = "SELECT songs.* FROM songs
|
||||||
JOIN artists ON songs.artist = artists.artist_id
|
JOIN artists ON songs.artist = artists.artist_id
|
||||||
JOIN metadata ON songs.metadata = metadata.meta_id
|
JOIN metadata ON songs.metadata = metadata.meta_id
|
||||||
WHERE artists.name like ? ORDER BY songs.album, metadata.track";
|
WHERE artists.name like ? ORDER BY songs.album, metadata.track";
|
||||||
self.music_query_single_param(query_stmt, param, op)
|
self.music_query_single_param(query_stmt, param)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn album_like(&mut self, query: &str, op: &mut QueryOp) -> QueryResult {
|
fn album_like(&mut self, query: &str) -> QueryResult {
|
||||||
let param = &format!("%{}%", query);
|
let param = &format!("%{}%", query);
|
||||||
let query_stmt = "SELECT songs.* FROM songs
|
let query_stmt = "SELECT songs.* FROM songs
|
||||||
JOIN albums ON songs.album = artists.album_id
|
JOIN albums ON songs.album = artists.album_id
|
||||||
JOIN metadata ON songs.metadata = metadata.meta_id
|
JOIN metadata ON songs.metadata = metadata.meta_id
|
||||||
WHERE albums.title like ? ORDER BY songs.album, metadata.track";
|
WHERE albums.title like ? ORDER BY songs.album, metadata.track";
|
||||||
self.music_query_single_param(query_stmt, param, op)
|
self.music_query_single_param(query_stmt, param)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn song_like(&mut self, query: &str, op: &mut QueryOp) -> QueryResult {
|
fn song_like(&mut self, query: &str) -> QueryResult {
|
||||||
let param = &format!("%{}%", query);
|
let param = &format!("%{}%", query);
|
||||||
let query_stmt = "SELECT songs.* FROM songs
|
let query_stmt = "SELECT songs.* FROM songs
|
||||||
JOIN metadata ON songs.metadata = metadata.meta_id
|
JOIN metadata ON songs.metadata = metadata.meta_id
|
||||||
WHERE songs.title like ? ORDER BY songs.album, metadata.track";
|
WHERE songs.title like ? ORDER BY songs.album, metadata.track";
|
||||||
self.music_query_single_param(query_stmt, param, op)
|
self.music_query_single_param(query_stmt, param)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn genre_like(&mut self, query: &str, op: &mut QueryOp) -> QueryResult {
|
fn genre_like(&mut self, query: &str) -> QueryResult {
|
||||||
let param = &format!("%{}%", query);
|
let param = &format!("%{}%", query);
|
||||||
let query_stmt = "SELECT songs.* FROM songs
|
let query_stmt = "SELECT songs.* FROM songs
|
||||||
JOIN genres ON songs.genre = genres.genre_id
|
JOIN genres ON songs.genre = genres.genre_id
|
||||||
JOIN metadata ON songs.metadata = metadata.meta_id
|
JOIN metadata ON songs.metadata = metadata.meta_id
|
||||||
WHERE genres.title like ? ORDER BY songs.album, metadata.track";
|
WHERE genres.title like ? ORDER BY songs.album, metadata.track";
|
||||||
self.music_query_single_param(query_stmt, param, op)
|
self.music_query_single_param(query_stmt, param)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init_with_params(
|
fn init_with_params(&mut self, params: &HashMap<String, String>) -> Result<(), RuntimeMsg> {
|
||||||
&mut self,
|
|
||||||
params: &HashMap<String, String>,
|
|
||||||
op: &mut QueryOp,
|
|
||||||
) -> Result<(), RuntimeError> {
|
|
||||||
// must be executed before connection is created
|
// must be executed before connection is created
|
||||||
if self.sqlite_connection.is_some() {
|
if self.sqlite_connection.is_some() {
|
||||||
Err(RuntimeError {
|
Err(RuntimeMsg(
|
||||||
line: 0,
|
"Cannot init SQLite connection: Already connected".to_string(),
|
||||||
op: op(),
|
))
|
||||||
msg: "Cannot init SQLite connection: Already connected".into(),
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
// process params
|
// process params
|
||||||
// init connection
|
// init connection
|
||||||
|
@ -183,14 +140,10 @@ impl MpsDatabaseQuerier for MpsSQLiteExecutor {
|
||||||
settings.auto_generate = match val as &str {
|
settings.auto_generate = match val as &str {
|
||||||
"true" => Ok(true),
|
"true" => Ok(true),
|
||||||
"false" => Ok(false),
|
"false" => Ok(false),
|
||||||
x => Err(RuntimeError {
|
x => Err(RuntimeMsg(format!(
|
||||||
line: 0,
|
|
||||||
op: op(),
|
|
||||||
msg: format!(
|
|
||||||
"Unrecognised right hand side of param \"{}\" = \"{}\"",
|
"Unrecognised right hand side of param \"{}\" = \"{}\"",
|
||||||
key, x
|
key, x
|
||||||
),
|
))),
|
||||||
}),
|
|
||||||
}?;
|
}?;
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
@ -211,17 +164,16 @@ impl MpsDatabaseQuerier for MpsSQLiteExecutor {
|
||||||
concat_keys += &format!("{}, ", key);
|
concat_keys += &format!("{}, ", key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Err(RuntimeError {
|
return Err(RuntimeMsg(format!(
|
||||||
line: 0,
|
"Unrecognised sql init parameter(s): {}",
|
||||||
op: op(),
|
concat_keys
|
||||||
msg: format!("Unrecognised sql init parameter(s): {}", concat_keys),
|
)));
|
||||||
});
|
|
||||||
}
|
}
|
||||||
self.sqlite_connection = Some(settings.try_into().map_err(|e| RuntimeError {
|
self.sqlite_connection = Some(
|
||||||
line: 0,
|
settings
|
||||||
op: op(),
|
.try_into()
|
||||||
msg: format!("SQL connection error: {}", e),
|
.map_err(|e| RuntimeMsg(format!("SQL connection error: {}", e)))?,
|
||||||
})?);
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue