use rorm_db::database::ColumnSelector;
use rorm_db::{Error, Row};
use crate::aggregate::{AggregatedColumn, AggregationFunc};
use crate::const_concat;
use crate::internal::field::as_db_type::AsDbType;
use crate::internal::field::{Field, FieldProxy};
use crate::internal::query_context::QueryContextBuilder;
use crate::internal::relation_path::Path;
use crate::model::Model;
pub trait Selectable {
type Result;
type Table: Model;
const COLUMNS: usize = 1;
const SELECT_ALIAS: &'static str;
const SQL: ColumnSelector<'static>;
fn prepare(builder: &mut QueryContextBuilder);
fn decode(row: &Row) -> Result<Self::Result, Error>;
}
impl<F: Field, P: Path> Selectable for FieldProxy<F, P> {
type Result = F::Type;
type Table = P::Origin;
const SELECT_ALIAS: &'static str = const_concat!(&[P::ALIAS, "__", F::NAME]);
const SQL: ColumnSelector<'static> = ColumnSelector {
table_name: Some(P::ALIAS),
column_name: F::NAME,
select_alias: Some(Self::SELECT_ALIAS),
aggregation: None,
};
fn prepare(builder: &mut QueryContextBuilder) {
builder.add_field_proxy::<F, P>()
}
fn decode(row: &Row) -> Result<Self::Result, Error> {
let primitive: <F::Type as AsDbType>::Primitive = row.get(Self::SELECT_ALIAS)?;
Ok(F::Type::from_primitive(primitive))
}
}
impl<A, F, P> Selectable for AggregatedColumn<A, F, P>
where
A: AggregationFunc,
F: Field,
P: Path,
{
type Result = A::Result<F::Type>;
type Table = P::Origin;
const SELECT_ALIAS: &'static str = const_concat!(&[P::ALIAS, "__", F::NAME, "___", A::NAME]);
const SQL: ColumnSelector<'static> = ColumnSelector {
table_name: Some(P::ALIAS),
column_name: F::NAME,
select_alias: Some(Self::SELECT_ALIAS),
aggregation: Some(A::SQL),
};
fn prepare(builder: &mut QueryContextBuilder) {
builder.add_field_proxy::<F, P>()
}
fn decode(row: &Row) -> Result<Self::Result, Error> {
row.get(Self::SELECT_ALIAS)
}
}