use vantage_core::Result;
use vantage_expressions::traits::selectable::Selectable;
use vantage_expressions::{Expression, Expressive, SelectableDataSource, expr_any};
use vantage_types::Entity;
use crate::{
column::core::ColumnType, table::Table, traits::column_like::ColumnLike,
traits::table_source::TableSource,
};
impl<T, E> Table<T, E>
where
T: SelectableDataSource<T::Value, T::Condition> + TableSource,
T::Value: From<String>, E: Entity<T::Value>,
{
pub fn select_empty(&self) -> T::Select {
let mut select = self.data_source.select();
select.add_source(self.table_name(), None);
for condition in self.conditions.values() {
select.add_where_condition(condition.clone());
}
for (expr, direction) in self.order_by.values() {
let order = match direction {
crate::sorting::SortDirection::Ascending => vantage_expressions::Order::Asc,
crate::sorting::SortDirection::Descending => vantage_expressions::Order::Desc,
};
select.add_order_by(expr.clone(), order);
}
if let Some(pagination) = &self.pagination {
select.set_limit(Some(pagination.limit()), Some(pagination.skip()));
}
select
}
pub fn select(&self) -> T::Select {
let mut select = self.select_empty();
for column in self.columns.values() {
if let Some(expr_fn) = self.expressions.get(column.name()) {
let expr = expr_fn(self);
self.data_source.add_select_column(
&mut select,
expr_any!("({})", (expr)),
Some(column.name()),
);
} else if let Some(alias) = column.alias() {
let expr = self.data_source.expr(column.name(), vec![]);
self.data_source
.add_select_column(&mut select, expr, Some(alias));
} else {
select.add_field(column.name());
}
}
for (name, expr_fn) in &self.expressions {
if !self.columns.contains_key(name) {
let expr = expr_fn(self);
self.data_source.add_select_column(
&mut select,
expr_any!("({})", (expr)),
Some(name),
);
}
}
select
}
pub async fn get_count(&self) -> Result<i64> {
self.data_source.get_table_count(self).await
}
pub async fn get_sum(&self, column: &T::Column<T::AnyType>) -> Result<T::Value> {
self.data_source.get_table_sum(self, column).await
}
pub async fn get_max(&self, column: &T::Column<T::AnyType>) -> Result<T::Value> {
self.data_source.get_table_max(self, column).await
}
pub async fn get_min(&self, column: &T::Column<T::AnyType>) -> Result<T::Value> {
self.data_source.get_table_min(self, column).await
}
pub fn get_count_query(&self) -> Expression<T::Value> {
expr_any!("({})", (self.select_empty().as_count()))
}
pub fn get_sum_query<Type>(&self, column: &T::Column<Type>) -> Expression<T::Value>
where
Type: ColumnType,
T::Column<Type>: Expressive<T::Value>,
{
expr_any!("({})", (self.select_empty().as_sum(column.expr())))
}
pub fn select_column(&self, field: &str) -> Expression<T::Value>
where
T::Column<T::AnyType>: Expressive<T::Value>,
T::Select: Expressive<T::Value>,
{
let expr = self.get_column_expr(field).unwrap();
let mut select = self.select_empty();
select.clear_fields();
select.clear_order_by();
select.add_expression(expr);
select.expr()
}
}
impl<T, E> Table<T, E>
where
T: SelectableDataSource<serde_json::Value, T::Condition>
+ TableSource<Value = serde_json::Value>
+ vantage_expressions::traits::datasource::ExprDataSource<serde_json::Value>,
T::Value: From<String>,
E: Entity<serde_json::Value>,
{
pub async fn get_count_via_query(&self) -> Result<i64> {
let count_query = self.get_count_query();
let result = self.data_source.execute(&count_query).await?;
if let Some(count) = result.get("count").and_then(|v| v.as_i64()) {
Ok(count)
} else if let Some(count) = result.as_i64() {
Ok(count)
} else {
Ok(0)
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::mocks::mock_table_source::MockTableSource;
use serde_json::json;
use vantage_expressions::mocks::datasource::MockSelectableDataSource;
use vantage_expressions::traits::datasource::ExprDataSource;
#[tokio::test]
async fn test_selectable_functionality() {
let mock_select_source = MockSelectableDataSource::new(json!([
{"id": "1", "name": "Alice", "age": 30},
{"id": "2", "name": "Bob", "age": 25}
]));
let mock_query_source = vantage_expressions::mocks::mock_builder::new()
.on_exact_select("(SELECT COUNT(*) FROM \"users\")", json!(42));
let table = MockTableSource::new()
.with_data(
"users",
vec![
json!({"id": "1", "name": "Alice", "age": 30}),
json!({"id": "2", "name": "Bob", "age": 25}),
],
)
.await
.with_select_source(mock_select_source)
.with_query_source(mock_query_source);
let table = Table::<_, vantage_types::EmptyEntity>::new("users", table);
let select = table.select();
assert_eq!(select.source(), Some("users"));
let query_expr: vantage_expressions::Expression<serde_json::Value> = select.into();
assert_eq!(query_expr.preview(), "SELECT * FROM users");
let count_query = table.get_count_query();
assert_eq!(count_query.preview(), "(SELECT COUNT(*) FROM \"users\")");
let count = table.get_count_via_query().await.unwrap();
assert_eq!(count, 42);
}
#[tokio::test]
#[should_panic(expected = "MockTableSource select source not set")]
async fn test_panics_without_select_source() {
let table = Table::<_, vantage_types::EmptyEntity>::new("users", MockTableSource::new());
let _select = table.select();
}
#[tokio::test]
#[should_panic(expected = "MockTableSource query source not set")]
async fn test_panics_without_query_source() {
let table = Table::<_, vantage_types::EmptyEntity>::new("users", MockTableSource::new());
let query = table.data_source().expr("SELECT COUNT(*)", vec![]);
let _result = table.data_source().execute(&query).await;
}
}