use crate::deserialize::SqlTypeLikeMarker;
use crate::expression::subselect::SubselectGroupBy;
use crate::expression::{
AppearsOnTable, Expression, QueryMetadata, SelectableExpression, TypedExpressionType,
ValidGrouping, is_aggregate,
};
use crate::mariadb::Mariadb;
use crate::query_builder::returning::{OldIdent, ReturningQuerySource, UpdateStmt};
use crate::query_builder::{AstPass, QueryFragment, QueryId};
use crate::query_dsl::load_dsl::CompatibleType;
use crate::query_source::{AppearsInFromClause, Column};
use crate::result::QueryResult;
use crate::sql_types::{IntoNotNullable, IntoNullable, SingleValue};
use crate::util::TupleSize;
use core::marker::PhantomData;
#[derive(Debug, Clone, Copy, QueryId)]
pub struct OldValue<C> {
_column: C,
}
impl<C> OldValue<C> {
pub(crate) fn new(c: C) -> Self {
OldValue { _column: c }
}
}
pub fn old_value<C: Column>(col: C) -> old_value<C> {
OldValue::new(col)
}
impl<C> Expression for OldValue<C>
where
C: Column + Expression,
C::SqlType: SingleValue,
{
type SqlType = OldValueOf<C::SqlType>;
}
#[derive(Debug, Clone, Copy, Default, QueryId)]
pub struct OldValueOf<ST>(PhantomData<ST>);
#[diagnostic::do_not_recommend]
impl<U, ST> CompatibleType<U, Mariadb> for OldValueOf<ST>
where
ST: CompatibleType<U, Mariadb>,
{
type SqlType = ST;
}
impl<ST> TypedExpressionType for OldValueOf<ST> {}
impl<ST> SqlTypeLikeMarker for OldValueOf<ST> {
type SqlType = ST;
}
impl<ST: TupleSize> TupleSize for OldValueOf<ST> {
const SIZE: usize = ST::SIZE;
}
impl<C> ValidGrouping<()> for OldValue<C>
where
C: Column,
{
type IsAggregate = is_aggregate::No;
}
impl<C, GB, From> ValidGrouping<SubselectGroupBy<GB, From>> for OldValue<C>
where
C: Column,
Self: ValidGrouping<GB>,
{
type IsAggregate = <Self as ValidGrouping<GB>>::IsAggregate;
}
impl<ST: IntoNullable> IntoNullable for OldValueOf<ST> {
type Nullable = OldValueOf<ST::Nullable>;
}
impl<ST: IntoNotNullable> IntoNotNullable for OldValueOf<ST> {
type NotNullable = OldValueOf<ST::NotNullable>;
}
impl<ST> QueryMetadata<OldValueOf<ST>> for Mariadb
where
Self: QueryMetadata<ST>,
{
fn row_metadata(lookup: &mut Self::MetadataLookup, out: &mut Vec<Option<Self::TypeMetadata>>) {
<Self as QueryMetadata<ST>>::row_metadata(lookup, out);
}
}
impl<C, QS> AppearsOnTable<ReturningQuerySource<UpdateStmt, QS>> for OldValue<C>
where
C: Column,
Self: Expression,
ReturningQuerySource<UpdateStmt, QS>:
AppearsInFromClause<OldIdent, Count = crate::query_source::Once>,
ReturningQuerySource<UpdateStmt, QS>: AppearsInFromClause<
ReturningQuerySource<OldIdent, C::Table>,
Count = crate::query_source::Once,
>,
{
}
impl<C> SelectableExpression<ReturningQuerySource<UpdateStmt, C::Table>> for OldValue<C>
where
C: Column,
Self: AppearsOnTable<ReturningQuerySource<UpdateStmt, C::Table>>,
{
}
impl<C> QueryFragment<Mariadb> for OldValue<C>
where
C: Column,
{
fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, Mariadb>) -> QueryResult<()> {
out.push_sql("OLD_VALUE(");
out.push_identifier(C::NAME)?;
out.push_sql(")");
Ok(())
}
}
pub use return_type_helpers_reexported::*;
pub(crate) mod return_type_helpers_reexported {
use super::OldValue;
#[allow(non_camel_case_types)]
pub type old_value<C> = OldValue<C>;
}