use std::marker::PhantomData;
use crate::{BindValue, Meta, Param};
use super::{BoolExpr, ValueExpr};
#[derive(Debug, PartialEq, Eq)]
#[must_use]
pub struct Field<T> {
pub meta: &'static Meta,
_ty: PhantomData<T>,
}
#[derive(Debug, PartialEq, Eq)]
#[must_use]
pub struct FieldRef<T> {
pub meta: &'static Meta,
pub qualifier: Option<String>,
_ty: PhantomData<T>,
}
impl<T> Clone for Field<T> {
fn clone(&self) -> Self {
*self
}
}
impl<T> Copy for Field<T> {}
impl<T> Clone for FieldRef<T> {
fn clone(&self) -> Self {
Self {
meta: self.meta,
qualifier: self.qualifier.clone(),
_ty: PhantomData,
}
}
}
#[doc(hidden)]
pub trait IntoFieldRef<T> {
fn into_field_ref(self) -> FieldRef<T>;
}
impl<T> Field<T> {
pub const fn new(meta: &'static Meta) -> Self {
Self {
meta,
_ty: PhantomData,
}
}
pub fn at(self, qualifier: impl Into<String>) -> FieldRef<T> {
FieldRef {
meta: self.meta,
qualifier: Some(qualifier.into()),
_ty: PhantomData,
}
}
#[inline]
pub(super) fn reference(self) -> FieldRef<T> {
FieldRef {
meta: self.meta,
qualifier: None,
_ty: PhantomData,
}
}
#[inline]
pub fn expr(self) -> ValueExpr {
self.reference().expr()
}
#[inline]
pub fn old_value(self) -> FieldRef<T> {
self.at("old")
}
#[inline]
pub fn new_value(self) -> FieldRef<T> {
self.at("new")
}
pub fn op(self, op: &'static str, right: impl Into<ValueExpr>) -> ValueExpr {
self.reference().op(op, right)
}
pub fn predicate(self, op: &'static str, right: impl Into<ValueExpr>) -> BoolExpr {
self.reference().predicate(op, right)
}
pub fn not_predicate(self, op: &'static str, right: impl Into<ValueExpr>) -> BoolExpr {
self.reference().not_predicate(op, right)
}
#[inline]
pub fn excluded(self) -> ValueExpr {
ValueExpr::Excluded(*self.meta)
}
pub fn set_expr(self, value: impl Into<ValueExpr>) -> crate::Assignment {
crate::Assignment {
field: *self.meta,
value: crate::AssignmentValue::Expr(value.into()),
}
}
#[inline]
pub fn set_null(self) -> crate::Assignment {
self.set_expr(ValueExpr::Null)
}
#[inline]
pub fn set_default(self) -> crate::Assignment {
crate::Assignment {
field: *self.meta,
value: crate::AssignmentValue::Default,
}
}
pub fn set_from(self, alias: impl Into<String>) -> crate::Assignment {
crate::Assignment {
field: *self.meta,
value: crate::AssignmentValue::Expr(self.at(alias).expr()),
}
}
#[inline]
pub fn set_excluded(self) -> crate::Assignment {
crate::Assignment {
field: *self.meta,
value: crate::AssignmentValue::Expr(self.excluded()),
}
}
#[inline]
pub fn is_null(self) -> BoolExpr {
self.reference().is_null()
}
#[inline]
pub fn is_not_null(self) -> BoolExpr {
self.reference().is_not_null()
}
pub fn in_subquery(self, query: impl Into<crate::Stmt>) -> BoolExpr {
self.reference().in_subquery(query)
}
pub fn not_in_subquery(self, query: impl Into<crate::Stmt>) -> BoolExpr {
self.reference().not_in_subquery(query)
}
pub fn eq_field<R>(self, right: R) -> BoolExpr
where
R: IntoFieldRef<T>,
{
self.reference().eq_field(right)
}
pub fn ne_field<R>(self, right: R) -> BoolExpr
where
R: IntoFieldRef<T>,
{
self.reference().ne_field(right)
}
pub fn gt_field<R>(self, right: R) -> BoolExpr
where
R: IntoFieldRef<T>,
{
self.reference().gt_field(right)
}
pub fn gte_field<R>(self, right: R) -> BoolExpr
where
R: IntoFieldRef<T>,
{
self.reference().gte_field(right)
}
pub fn lt_field<R>(self, right: R) -> BoolExpr
where
R: IntoFieldRef<T>,
{
self.reference().lt_field(right)
}
pub fn lte_field<R>(self, right: R) -> BoolExpr
where
R: IntoFieldRef<T>,
{
self.reference().lte_field(right)
}
pub fn is_distinct_from_field<R>(self, right: R) -> BoolExpr
where
R: IntoFieldRef<T>,
{
self.reference().is_distinct_from_field(right)
}
pub fn is_not_distinct_from_field<R>(self, right: R) -> BoolExpr
where
R: IntoFieldRef<T>,
{
self.reference().is_not_distinct_from_field(right)
}
}
impl<T: BindValue> Field<T> {
pub fn set(self, value: impl Into<T>) -> crate::Assignment {
self.set_expr(ValueExpr::Param(Param::typed(value.into())))
}
pub fn set_ref<V>(self, value: &V) -> crate::Assignment
where
V: Clone + Into<T>,
{
self.set(value.clone())
}
pub fn eq(self, value: impl Into<T>) -> BoolExpr {
self.reference().eq(value)
}
pub fn ne(self, value: impl Into<T>) -> BoolExpr {
self.reference().ne(value)
}
pub fn gt(self, value: impl Into<T>) -> BoolExpr {
self.reference().gt(value)
}
pub fn gte(self, value: impl Into<T>) -> BoolExpr {
self.reference().gte(value)
}
pub fn lt(self, value: impl Into<T>) -> BoolExpr {
self.reference().lt(value)
}
pub fn lte(self, value: impl Into<T>) -> BoolExpr {
self.reference().lte(value)
}
pub fn is_distinct_from(self, value: impl Into<T>) -> BoolExpr {
self.reference().is_distinct_from(value)
}
pub fn is_not_distinct_from(self, value: impl Into<T>) -> BoolExpr {
self.reference().is_not_distinct_from(value)
}
pub fn in_list(self, values: impl IntoIterator<Item = impl Into<T>>) -> BoolExpr {
self.reference().in_list(values)
}
pub fn not_in(self, values: impl IntoIterator<Item = impl Into<T>>) -> BoolExpr {
self.reference().not_in(values)
}
pub fn between(self, low: impl Into<T>, high: impl Into<T>) -> BoolExpr {
self.reference().between(low, high)
}
pub fn not_between(self, low: impl Into<T>, high: impl Into<T>) -> BoolExpr {
self.reference().not_between(low, high)
}
}
impl<T> IntoFieldRef<T> for Field<T> {
fn into_field_ref(self) -> FieldRef<T> {
self.reference()
}
}
impl<T> IntoFieldRef<T> for &Field<T> {
fn into_field_ref(self) -> FieldRef<T> {
self.reference()
}
}
impl<T> IntoFieldRef<T> for FieldRef<T> {
fn into_field_ref(self) -> FieldRef<T> {
self
}
}
impl<T> IntoFieldRef<T> for &FieldRef<T> {
fn into_field_ref(self) -> FieldRef<T> {
self.clone()
}
}
impl<T> From<Field<T>> for ValueExpr {
fn from(field: Field<T>) -> Self {
field.expr()
}
}
impl<T> From<&Field<T>> for ValueExpr {
fn from(field: &Field<T>) -> Self {
field.expr()
}
}
impl<T> From<FieldRef<T>> for ValueExpr {
fn from(field: FieldRef<T>) -> Self {
field.expr()
}
}
impl<T> From<&FieldRef<T>> for ValueExpr {
fn from(field: &FieldRef<T>) -> Self {
field.clone().expr()
}
}