use crate::rusqlite::AssembleRusqliteQuery;
use crate::rusqlite::AssemblyContext;
use crate::rusqlite::InvertableRusqliteQuery;
use crate::rusqlite::RusqliteQuery;
use crate::rusqlite::TryAssembleRusqliteQuery;
use crate::sql::Field;
use crate::CriteriumChain;
impl<T, F, C> TryAssembleRusqliteQuery<F, C> for CriteriumChain<T>
where
T: TryAssembleRusqliteQuery<F, C>,
F: Field,
{
type Error = T::Error;
fn try_assemble_rusqlite_query(
&self,
assembly_context: &AssemblyContext,
context: &C,
) -> Result<InvertableRusqliteQuery<F>, T::Error> {
match self {
Self::And(list) => try_chain_assembled_criterium_chains(
&list.criteria,
&assembly_context.in_and_block(),
" AND ",
list.fallback,
context,
),
Self::Or(list) => try_chain_assembled_criterium_chains(
&list.criteria,
&assembly_context.in_or_block(),
" OR ",
list.fallback,
context,
),
Self::NotChain(c) => Ok(c
.try_assemble_rusqlite_query(&assembly_context.in_invert_block(), context)?
.invert()),
Self::Not(c) => Ok(c
.try_assemble_rusqlite_query(&assembly_context.in_invert_block(), context)?
.invert()),
Self::Match(c) => c.try_assemble_rusqlite_query(assembly_context, context),
Self::MatchAlways =>
{
Ok(
RusqliteQuery::static_bool(!assembly_context.is_branch_inverted())
.as_invertable()
.invert_if(assembly_context.is_branch_inverted()),
)
}
Self::MatchNever =>
{
Ok(
RusqliteQuery::static_bool(assembly_context.is_branch_inverted())
.as_invertable()
.invert_if(assembly_context.is_branch_inverted()),
)
}
Self::WithLikelihood {
matcher,
likelihood,
} => Ok(matcher
.try_assemble_rusqlite_query(assembly_context, context)?
.get_corrected_query()
.with_likelihood(*likelihood)
.as_invertable()),
}
}
}
impl<T, F, C> AssembleRusqliteQuery<F, C> for CriteriumChain<T>
where
T: AssembleRusqliteQuery<F, C>,
F: Field,
{
fn assemble_rusqlite_query(
&self,
assembly_context: &AssemblyContext,
context: &C,
) -> InvertableRusqliteQuery<F> {
match self {
Self::And(list) => chain_assembled_criterium_chains(
&list.criteria,
&assembly_context.in_and_block(),
" AND ",
list.fallback,
context,
),
Self::Or(list) => chain_assembled_criterium_chains(
&list.criteria,
&assembly_context.in_or_block(),
" OR ",
list.fallback,
context,
),
Self::NotChain(c) => c
.assemble_rusqlite_query(&assembly_context.in_invert_block(), context)
.invert(),
Self::Not(c) => c
.assemble_rusqlite_query(&assembly_context.in_invert_block(), context)
.invert(),
Self::Match(c) => c.assemble_rusqlite_query(assembly_context, context),
Self::MatchAlways =>
{
RusqliteQuery::static_bool(!assembly_context.is_branch_inverted())
.as_invertable()
.invert_if(assembly_context.is_branch_inverted())
}
Self::MatchNever =>
{
RusqliteQuery::static_bool(assembly_context.is_branch_inverted())
.as_invertable()
.invert_if(assembly_context.is_branch_inverted())
}
Self::WithLikelihood {
matcher,
likelihood,
} => matcher
.assemble_rusqlite_query(assembly_context, context)
.get_corrected_query()
.with_likelihood(*likelihood)
.as_invertable(),
}
}
}
fn try_chain_assembled_criterium_chains<T, F, C>(
cs: &Vec<CriteriumChain<T>>,
assembly_context: &AssemblyContext,
joiner: &str,
fallback: bool,
context: &C,
) -> Result<InvertableRusqliteQuery<F>, T::Error>
where
T: TryAssembleRusqliteQuery<F, C>,
F: Field,
{
let mut assembly: Option<RusqliteQuery<F>> = None;
for c in cs {
let a = c.try_assemble_finished_rusqlite_query(assembly_context, context)?;
if let Some(old_assembly) = assembly {
assembly = Some(old_assembly.concat(a, joiner));
} else {
assembly = Some(a);
}
}
if let Some(assembly) = assembly {
Ok(assembly.parenthesise_where_clause().as_invertable())
} else {
Ok(get_fallback_value(assembly_context, fallback))
}
}
fn chain_assembled_criterium_chains<T, F, C>(
cs: &Vec<CriteriumChain<T>>,
assembly_context: &AssemblyContext,
joiner: &str,
fallback: bool,
context: &C,
) -> InvertableRusqliteQuery<F>
where
T: AssembleRusqliteQuery<F, C>,
F: Field,
{
let mut assembly: Option<RusqliteQuery<F>> = None;
for c in cs {
let a = c.assemble_finished_rusqlite_query(assembly_context, context);
if let Some(old_assembly) = assembly {
assembly = Some(old_assembly.concat(a, joiner));
} else {
assembly = Some(a);
}
}
if let Some(assembly) = assembly {
assembly.parenthesise_where_clause().as_invertable()
} else {
get_fallback_value(assembly_context, fallback)
}
}
fn get_fallback_value<F>(
assembly_context: &AssemblyContext,
fallback: bool,
) -> InvertableRusqliteQuery<F>
where
F: Field,
{
if fallback != assembly_context.is_branch_inverted() {
RusqliteQuery::static_bool(true)
.as_invertable()
.invert_if(assembly_context.is_branch_inverted())
} else {
RusqliteQuery::static_bool(false)
.as_invertable()
.invert_if(assembly_context.is_branch_inverted())
}
}