use crate::db::query::{
builder::AggregateExpr,
expr::{FilterExpr, OrderTerm},
};
#[derive(Clone, Debug)]
pub struct DynamicQuery {
entity: String,
filter: Option<FilterExpr>,
order: Vec<OrderTerm>,
fields: Vec<String>,
limit: Option<u32>,
group_fields: Vec<String>,
aggregates: Vec<AggregateExpr>,
grouped_limits: Option<(u32, u32)>,
cursor: Option<String>,
}
impl DynamicQuery {
#[must_use]
pub fn new(entity: impl Into<String>) -> Self {
Self {
entity: entity.into(),
filter: None,
order: Vec::new(),
fields: Vec::new(),
limit: None,
group_fields: Vec::new(),
aggregates: Vec::new(),
grouped_limits: None,
cursor: None,
}
}
#[must_use]
pub fn filter(mut self, filter: impl Into<FilterExpr>) -> Self {
self.filter = Some(filter.into());
self
}
#[must_use]
pub fn order_by(mut self, order: OrderTerm) -> Self {
self.order.push(order);
self
}
#[must_use]
pub fn select<I, S>(mut self, fields: I) -> Self
where
I: IntoIterator<Item = S>,
S: Into<String>,
{
self.fields = fields.into_iter().map(Into::into).collect();
self
}
#[must_use]
pub const fn limit(mut self, limit: u32) -> Self {
self.limit = Some(limit);
self
}
#[must_use]
pub fn group_by(mut self, field: impl Into<String>) -> Self {
self.group_fields.push(field.into());
self
}
#[must_use]
pub fn aggregate(mut self, aggregate: AggregateExpr) -> Self {
self.aggregates.push(aggregate);
self
}
#[must_use]
pub const fn grouped_limits(mut self, max_groups: u32, max_group_bytes: u32) -> Self {
self.grouped_limits = Some((max_groups, max_group_bytes));
self
}
#[must_use]
pub fn cursor(mut self, cursor: impl Into<String>) -> Self {
self.cursor = Some(cursor.into());
self
}
pub(in crate::db) const fn entity(&self) -> &str {
self.entity.as_str()
}
pub(in crate::db) const fn filter_expr(&self) -> Option<&FilterExpr> {
self.filter.as_ref()
}
pub(in crate::db) const fn order_terms(&self) -> &[OrderTerm] {
self.order.as_slice()
}
pub(in crate::db) const fn selected_fields(&self) -> &[String] {
self.fields.as_slice()
}
pub(in crate::db) const fn row_limit(&self) -> Option<u32> {
self.limit
}
pub(in crate::db) const fn has_grouping(&self) -> bool {
!self.group_fields.is_empty() || !self.aggregates.is_empty()
}
pub(in crate::db) const fn group_fields(&self) -> &[String] {
self.group_fields.as_slice()
}
pub(in crate::db) const fn aggregates(&self) -> &[AggregateExpr] {
self.aggregates.as_slice()
}
pub(in crate::db) const fn grouped_execution_limits(&self) -> Option<(u32, u32)> {
self.grouped_limits
}
pub(in crate::db) fn continuation_cursor(&self) -> Option<&str> {
self.cursor.as_deref()
}
}