use std::marker::PhantomData;
use crate::query::ast::{Join, JoinKind, OrderTerm};
use crate::query::expr::Expr;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum RelationKind {
HasMany,
BelongsTo,
}
pub struct Relation<P, C> {
kind: RelationKind,
from_table: &'static str,
from_column: &'static str,
to_table: &'static str,
to_column: &'static str,
filters: Vec<Expr>,
order_by: Vec<OrderTerm>,
limit: Option<u64>,
_marker: PhantomData<fn() -> (P, C)>,
}
impl<P, C> Relation<P, C> {
pub fn has_many(
parent_table: &'static str,
parent_key: &'static str,
child_table: &'static str,
child_key: &'static str,
) -> Self {
Self {
kind: RelationKind::HasMany,
from_table: parent_table,
from_column: parent_key,
to_table: child_table,
to_column: child_key,
filters: Vec::new(),
order_by: Vec::new(),
limit: None,
_marker: PhantomData,
}
}
pub fn belongs_to(
local_table: &'static str,
local_key: &'static str,
parent_table: &'static str,
parent_key: &'static str,
) -> Self {
Self {
kind: RelationKind::BelongsTo,
from_table: local_table,
from_column: local_key,
to_table: parent_table,
to_column: parent_key,
filters: Vec::new(),
order_by: Vec::new(),
limit: None,
_marker: PhantomData,
}
}
pub fn filter(mut self, predicate: Expr) -> Self {
self.filters.push(predicate);
self
}
pub fn order_by(mut self, term: OrderTerm) -> Self {
self.order_by.push(term);
self
}
pub fn limit(mut self, limit: u64) -> Self {
self.limit = Some(limit);
self
}
pub fn kind(&self) -> RelationKind {
self.kind
}
pub fn target_table(&self) -> &'static str {
self.to_table
}
pub fn from_column(&self) -> &'static str {
self.from_column
}
pub fn to_column(&self) -> &'static str {
self.to_column
}
pub fn preload_filters(&self) -> &[Expr] {
&self.filters
}
pub fn preload_order_by(&self) -> &[OrderTerm] {
&self.order_by
}
pub fn preload_limit(&self) -> Option<u64> {
self.limit
}
pub fn join_node(&self) -> Join {
self.join_node_with_kind(JoinKind::Inner)
}
pub fn join_node_with_kind(&self, kind: JoinKind) -> Join {
Join {
kind,
table: self.to_table,
alias: None,
left_table: self.from_table,
left_column: self.from_column,
right_table: self.to_table,
right_column: self.to_column,
}
}
}