use super::{builders::model_key_field, *};
#[doc(hidden)]
pub trait MorphTypeFieldInfo<Child>: Copy {
fn matches(self, child: &Child, morph_name: &'static str) -> bool;
fn contains_field(self, field: &'static str) -> bool;
fn filter_query(self, query: QueryOf<Child>, morph_name: &'static str) -> QueryOf<Child>
where
Child: FromRow;
fn assign(self, child: &mut Child, morph_name: &'static str);
fn visit_injected<'a>(self, morph_name: &'static str, visitor: &mut impl VisitParam<'a>);
fn dirty_field(self) -> DraftField<Child>;
}
trait RelationMorphTypeValue: RelationMorphType + quex::Encode {
fn matches_morph_type(&self, morph_name: &'static str) -> bool;
}
impl RelationMorphTypeValue for String {
fn matches_morph_type(&self, morph_name: &'static str) -> bool {
self == morph_name
}
}
impl RelationMorphTypeValue for Option<String> {
fn matches_morph_type(&self, morph_name: &'static str) -> bool {
self.as_deref() == Some(morph_name)
}
}
impl<Child, Value, Meta, Kind> MorphTypeFieldInfo<Child>
for PersistedField<Child, Value, Meta, Kind>
where
Child: Qrafting + FromRow,
Value: RelationMorphTypeValue,
Meta: Comparable + crate::Nullability,
crate::BinaryType<crate::NullOf<Meta>, crate::NullOf<Meta>>: crate::PredicateType,
&'static str: crate::LowerCompatible<Meta>,
{
fn matches(self, child: &Child, morph_name: &'static str) -> bool {
(self.getter())(child).matches_morph_type(morph_name)
}
fn contains_field(self, field: &'static str) -> bool {
self.column().name() == field
}
fn filter_query(self, query: QueryOf<Child>, morph_name: &'static str) -> QueryOf<Child>
where
Child: FromRow,
{
query.filter(self.column().eq(morph_name))
}
fn assign(self, child: &mut Child, morph_name: &'static str) {
(self.setter())(child, Value::from_relation_morph_type(morph_name));
}
fn visit_injected<'a>(self, morph_name: &'static str, visitor: &mut impl VisitParam<'a>) {
visitor.param(
self.column().name(),
Value::from_relation_morph_type(morph_name),
)
}
fn dirty_field(self) -> DraftField<Child> {
WritableField::dirty_field(self)
}
}
pub(super) struct MorphToTargetSpec<Child, ForeignField> {
pub(super) type_id: TypeId,
pub(super) morph_name: &'static str,
pub(super) query: Box<dyn Fn(ForeignField, &Child) -> Option<Query>>,
}
pub(super) struct MorphToMutTargetSpec<Child, ForeignField> {
pub(super) type_id: TypeId,
pub(super) morph_name: &'static str,
pub(super) query: Box<dyn Fn(ForeignField, &Child) -> Option<Query>>,
pub(super) assign: Box<dyn Fn(ForeignField, &mut Child, &dyn Any) -> Vec<DraftField<Child>>>,
}
struct SkipMorphRelationFieldVisitor<'a, V, Child, ForeignField, MorphField> {
inner: &'a mut V,
foreign_key: ForeignField,
morph_type: MorphField,
marker: std::marker::PhantomData<fn() -> Child>,
}
impl<'a, 'v, V, Child, ForeignField, MorphField> VisitParam<'v>
for SkipMorphRelationFieldVisitor<'a, V, Child, ForeignField, MorphField>
where
V: VisitParam<'v>,
ForeignField: ReadableFieldInfo<Child>
+ ReadableField<
Child,
<ForeignField as ReadableFieldInfo<Child>>::Value,
<ForeignField as ReadableFieldInfo<Child>>::Meta,
> + Copy,
MorphField: MorphTypeFieldInfo<Child>,
{
fn param(&mut self, field: &'static str, param: impl quex::Encode) {
if self.foreign_key.column().name() == field || self.morph_type.contains_field(field) {
return;
}
self.inner.param(field, param)
}
fn param_typed<T>(
&mut self,
field: &'static str,
value: &'v (impl crate::Compatible<T> + ?Sized),
) where
T: crate::TypeMeta,
{
if self.foreign_key.column().name() == field || self.morph_type.contains_field(field) {
return;
}
self.inner.param_typed::<T>(field, value)
}
}
pub(super) struct InjectMorphRelationValues<'a, Parent, V, ForeignField, LocalField, MorphField> {
pub(super) parent: &'a Parent,
pub(super) values: V,
pub(super) foreign_key: ForeignField,
pub(super) local_key: LocalField,
pub(super) morph_type: MorphField,
pub(super) morph_name: &'static str,
}
impl<'a, Parent, Child, V, ForeignField, LocalField, MorphField> Insertable<Child>
for InjectMorphRelationValues<'a, Parent, V, ForeignField, LocalField, MorphField>
where
Child: Qrafting + FromRow,
V: Insertable<Child>,
ForeignField: ReadableFieldInfo<Child>
+ ReadableField<
Child,
<ForeignField as ReadableFieldInfo<Child>>::Value,
<ForeignField as ReadableFieldInfo<Child>>::Meta,
> + Copy,
LocalField: ReadableFieldInfo<Parent>
+ ReadableField<
Parent,
<LocalField as ReadableFieldInfo<Parent>>::Value,
<LocalField as ReadableFieldInfo<Parent>>::Meta,
> + Copy,
MorphField: MorphTypeFieldInfo<Child>,
<LocalField as ReadableFieldInfo<Parent>>::Value:
crate::Compatible<<ForeignField as ReadableFieldInfo<Child>>::Meta>,
{
fn values<'v>(&'v self, visitor: &mut impl VisitParam<'v>) {
visitor.param_typed::<<ForeignField as ReadableFieldInfo<Child>>::Meta>(
self.foreign_key.column().name(),
(self.local_key.getter())(self.parent),
);
self.morph_type.visit_injected(self.morph_name, visitor);
let mut visitor = SkipMorphRelationFieldVisitor {
inner: visitor,
foreign_key: self.foreign_key,
morph_type: self.morph_type,
marker: std::marker::PhantomData,
};
self.values.values(&mut visitor)
}
}
impl<'a, Child, ForeignKey, ForeignMeta: crate::TypeMeta>
RequiredBelongsToBuilder<'a, Child, ForeignKey, ForeignMeta>
{
pub fn owner_key<Parent, OwnerKey, OwnerMeta: Comparable + crate::Nullability, OwnerField>(
self,
owner_key: OwnerField,
) -> BuiltBelongsTo<'a, Child, Parent, ForeignKey, ForeignMeta, OwnerKey, OwnerMeta, OwnerField>
where
Parent: Qrafting + FromRow,
OwnerField: ReadableField<Parent, OwnerKey, OwnerMeta>,
ForeignKey: crate::Compatible<OwnerMeta>,
{
BuiltBelongsTo {
child: self.child,
foreign_key: self.foreign_key,
owner_key,
_marker: PhantomData,
}
}
pub fn owner_model_key<Parent>(
self,
) -> BuiltBelongsTo<
'a,
Child,
Parent,
ForeignKey,
ForeignMeta,
<Parent as ModelKey>::Key,
<<Parent as ModelKey>::Key as crate::DefaultMeta>::Meta,
ModelField<
Parent,
<Parent as ModelKey>::Key,
<<Parent as ModelKey>::Key as crate::DefaultMeta>::Meta,
>,
>
where
Parent: Qrafting + FromRow + ModelKey,
<Parent as ModelKey>::Key: crate::DefaultMeta,
<<Parent as ModelKey>::Key as crate::DefaultMeta>::Meta: Comparable + crate::Nullability,
ForeignKey: crate::Compatible<<<Parent as ModelKey>::Key as crate::DefaultMeta>::Meta>,
{
self.owner_key(model_key_field::<Parent>())
}
}
impl<'a, Child, ForeignKey, ForeignMeta: crate::TypeMeta>
RequiredMorphToBuilder<'a, Child, ForeignKey, ForeignMeta>
{
pub fn morph_type<MorphField>(
self,
morph_type: MorphField,
) -> MorphToTypeBuilder<
'a,
Child,
PersistedField<Child, ForeignKey, ForeignMeta, RequiredField>,
MorphField,
> {
MorphToTypeBuilder {
child: self.child,
foreign_key: self.foreign_key,
morph_type,
}
}
}
impl<'a, Child, ForeignKey, ForeignMeta: crate::TypeMeta>
NullableMorphToBuilder<'a, Child, ForeignKey, ForeignMeta>
{
pub fn morph_type<MorphField>(
self,
morph_type: MorphField,
) -> MorphToTypeBuilder<
'a,
Child,
PersistedField<Child, Option<ForeignKey>, ForeignMeta, NullableField>,
MorphField,
> {
MorphToTypeBuilder {
child: self.child,
foreign_key: self.foreign_key,
morph_type,
}
}
}
impl<'a, Child: Draftable, ForeignKey, ForeignMeta: crate::TypeMeta>
RequiredMorphToMutBuilder<'a, Child, ForeignKey, ForeignMeta>
{
pub fn morph_type<MorphField>(
self,
morph_type: MorphField,
) -> MorphToMutTypeBuilder<
'a,
Child,
PersistedField<Child, ForeignKey, ForeignMeta, RequiredField>,
MorphField,
> {
MorphToMutTypeBuilder {
child: self.child,
foreign_key: self.foreign_key,
morph_type,
}
}
}
impl<'a, Child: Draftable, ForeignKey, ForeignMeta: crate::TypeMeta>
NullableMorphToMutBuilder<'a, Child, ForeignKey, ForeignMeta>
{
pub fn morph_type<MorphField>(
self,
morph_type: MorphField,
) -> MorphToMutTypeBuilder<
'a,
Child,
PersistedField<Child, Option<ForeignKey>, ForeignMeta, NullableField>,
MorphField,
> {
MorphToMutTypeBuilder {
child: self.child,
foreign_key: self.foreign_key,
morph_type,
}
}
}
impl<'a, Child, ForeignField, MorphField> MorphToTypeBuilder<'a, Child, ForeignField, MorphField> {
pub fn morph<Parent>(
self,
) -> MorphToTargetBuilder<
'a,
Child,
ForeignField,
MorphField,
Parent,
ModelField<
Parent,
<Parent as ModelKey>::Key,
<<Parent as ModelKey>::Key as crate::DefaultMeta>::Meta,
>,
>
where
Parent: Qrafting + FromRow + ModelKey + MorphName + 'static,
<Parent as ModelKey>::Key: crate::DefaultMeta,
{
MorphToTargetBuilder {
child: self.child,
foreign_key: self.foreign_key,
morph_type: self.morph_type,
targets: Vec::new(),
morph_name: <Parent as MorphName>::morph_name(),
owner_key: model_key_field::<Parent>(),
_marker: PhantomData,
}
}
}
impl<'a, Child: Draftable, ForeignField, MorphField>
MorphToMutTypeBuilder<'a, Child, ForeignField, MorphField>
{
pub fn morph<Parent>(
self,
) -> MorphToMutTargetBuilder<
'a,
Child,
ForeignField,
MorphField,
Parent,
ModelField<
Parent,
<Parent as ModelKey>::Key,
<<Parent as ModelKey>::Key as crate::DefaultMeta>::Meta,
>,
>
where
Parent: Qrafting + FromRow + ModelKey + MorphName + 'static,
<Parent as ModelKey>::Key: crate::DefaultMeta,
{
MorphToMutTargetBuilder {
child: self.child,
foreign_key: self.foreign_key,
morph_type: self.morph_type,
targets: Vec::new(),
morph_name: <Parent as MorphName>::morph_name(),
owner_key: model_key_field::<Parent>(),
_marker: PhantomData,
}
}
}
impl<'a, Child, ForeignField, MorphField, Parent, OwnerField>
MorphToTargetBuilder<'a, Child, ForeignField, MorphField, Parent, OwnerField>
{
pub fn owner_key<NewOwnerField>(
self,
owner_key: NewOwnerField,
) -> MorphToTargetBuilder<'a, Child, ForeignField, MorphField, Parent, NewOwnerField> {
MorphToTargetBuilder {
child: self.child,
foreign_key: self.foreign_key,
morph_type: self.morph_type,
targets: self.targets,
morph_name: self.morph_name,
owner_key,
_marker: PhantomData,
}
}
pub fn morph_name(self, morph_name: &'static str) -> Self {
Self { morph_name, ..self }
}
}
impl<'a, Child: Draftable, ForeignField, MorphField, Parent, OwnerField>
MorphToMutTargetBuilder<'a, Child, ForeignField, MorphField, Parent, OwnerField>
{
pub fn owner_key<NewOwnerField>(
self,
owner_key: NewOwnerField,
) -> MorphToMutTargetBuilder<'a, Child, ForeignField, MorphField, Parent, NewOwnerField> {
MorphToMutTargetBuilder {
child: self.child,
foreign_key: self.foreign_key,
morph_type: self.morph_type,
targets: self.targets,
morph_name: self.morph_name,
owner_key,
_marker: PhantomData,
}
}
pub fn morph_name(self, morph_name: &'static str) -> Self {
Self { morph_name, ..self }
}
}
impl<'a, Parent, Child, ForeignField> HasManyFieldsBuilder<'a, Parent, Child, ForeignField> {
pub fn local_key<LocalField>(
self,
local_key: LocalField,
) -> BuiltHasMany<'a, Parent, Child, ForeignField, LocalField> {
BuiltHasMany {
parent: self.parent,
foreign_key: self.foreign_key,
local_key,
_marker: PhantomData,
}
}
}
impl<'a, Parent, Child, ForeignField> HasOneFieldsBuilder<'a, Parent, Child, ForeignField> {
pub fn local_key<LocalField>(
self,
local_key: LocalField,
) -> BuiltHasOne<'a, Parent, Child, ForeignField, LocalField> {
BuiltHasOne {
parent: self.parent,
foreign_key: self.foreign_key,
local_key,
_marker: PhantomData,
}
}
}
impl<'a, Parent, Child, ForeignField> MorphManyFieldsBuilder<'a, Parent, Child, ForeignField> {
pub fn morph_type<MorphField>(
self,
morph_type: MorphField,
) -> MorphManyTypeBuilder<'a, Parent, Child, ForeignField, MorphField> {
MorphManyTypeBuilder {
parent: self.parent,
foreign_key: self.foreign_key,
morph_type,
_marker: PhantomData,
}
}
}
impl<'a, Parent, Child, ForeignField> MorphOneFieldsBuilder<'a, Parent, Child, ForeignField> {
pub fn morph_type<MorphField>(
self,
morph_type: MorphField,
) -> MorphOneTypeBuilder<'a, Parent, Child, ForeignField, MorphField> {
MorphOneTypeBuilder {
parent: self.parent,
foreign_key: self.foreign_key,
morph_type,
_marker: PhantomData,
}
}
}
impl<'a, Parent, Child, ForeignField, MorphField>
MorphManyTypeBuilder<'a, Parent, Child, ForeignField, MorphField>
{
pub fn local_key<LocalField>(
self,
local_key: LocalField,
) -> MorphManyLocalKeyBuilder<'a, Parent, Child, ForeignField, MorphField, LocalField> {
MorphManyLocalKeyBuilder {
parent: self.parent,
foreign_key: self.foreign_key,
morph_type: self.morph_type,
local_key,
_marker: PhantomData,
}
}
pub fn morph_name(
self,
morph_name: &'static str,
) -> BuiltMorphMany<
'a,
Parent,
Child,
ForeignField,
MorphField,
ModelField<
Parent,
<Parent as ModelKey>::Key,
<<Parent as ModelKey>::Key as crate::DefaultMeta>::Meta,
>,
>
where
Parent: ModelKey,
<Parent as ModelKey>::Key: crate::DefaultMeta,
{
BuiltMorphMany {
parent: self.parent,
foreign_key: self.foreign_key,
morph_type: self.morph_type,
local_key: model_key_field::<Parent>(),
morph_name,
_marker: PhantomData,
}
}
}
impl<'a, Parent, Child, ForeignField, MorphField>
MorphOneTypeBuilder<'a, Parent, Child, ForeignField, MorphField>
{
pub fn local_key<LocalField>(
self,
local_key: LocalField,
) -> MorphOneLocalKeyBuilder<'a, Parent, Child, ForeignField, MorphField, LocalField> {
MorphOneLocalKeyBuilder {
parent: self.parent,
foreign_key: self.foreign_key,
morph_type: self.morph_type,
local_key,
_marker: PhantomData,
}
}
pub fn morph_name(
self,
morph_name: &'static str,
) -> BuiltMorphOne<
'a,
Parent,
Child,
ForeignField,
MorphField,
ModelField<
Parent,
<Parent as ModelKey>::Key,
<<Parent as ModelKey>::Key as crate::DefaultMeta>::Meta,
>,
>
where
Parent: ModelKey,
<Parent as ModelKey>::Key: crate::DefaultMeta,
{
BuiltMorphOne {
parent: self.parent,
foreign_key: self.foreign_key,
morph_type: self.morph_type,
local_key: model_key_field::<Parent>(),
morph_name,
_marker: PhantomData,
}
}
}
impl<'a, Parent, Child, ForeignField, MorphField, LocalField>
MorphManyLocalKeyBuilder<'a, Parent, Child, ForeignField, MorphField, LocalField>
{
pub fn morph_name(
self,
morph_name: &'static str,
) -> BuiltMorphMany<'a, Parent, Child, ForeignField, MorphField, LocalField> {
BuiltMorphMany {
parent: self.parent,
foreign_key: self.foreign_key,
morph_type: self.morph_type,
local_key: self.local_key,
morph_name,
_marker: PhantomData,
}
}
}
impl<'a, Parent, Child, ForeignField, MorphField, LocalField>
MorphOneLocalKeyBuilder<'a, Parent, Child, ForeignField, MorphField, LocalField>
{
pub fn morph_name(
self,
morph_name: &'static str,
) -> BuiltMorphOne<'a, Parent, Child, ForeignField, MorphField, LocalField> {
BuiltMorphOne {
parent: self.parent,
foreign_key: self.foreign_key,
morph_type: self.morph_type,
local_key: self.local_key,
morph_name,
_marker: PhantomData,
}
}
}
impl<'a, Child, ForeignKey, ForeignMeta: crate::TypeMeta>
NullableBelongsToBuilderImpl<'a, Child, ForeignKey, ForeignMeta>
{
pub fn owner_key<Parent, OwnerKey, OwnerMeta: Comparable + crate::Nullability, OwnerField>(
self,
owner_key: OwnerField,
) -> BuiltNullableBelongsTo<
'a,
Child,
Parent,
ForeignKey,
ForeignMeta,
OwnerKey,
OwnerMeta,
OwnerField,
>
where
Parent: Qrafting + FromRow,
OwnerField: ReadableField<Parent, OwnerKey, OwnerMeta>,
ForeignKey: crate::Compatible<OwnerMeta>,
{
BuiltNullableBelongsTo {
child: self.child,
foreign_key: self.foreign_key,
owner_key,
_marker: PhantomData,
}
}
pub fn owner_model_key<Parent>(
self,
) -> BuiltNullableBelongsTo<
'a,
Child,
Parent,
ForeignKey,
ForeignMeta,
<Parent as ModelKey>::Key,
<<Parent as ModelKey>::Key as crate::DefaultMeta>::Meta,
ModelField<
Parent,
<Parent as ModelKey>::Key,
<<Parent as ModelKey>::Key as crate::DefaultMeta>::Meta,
>,
>
where
Parent: Qrafting + FromRow + ModelKey,
<Parent as ModelKey>::Key: crate::DefaultMeta,
<<Parent as ModelKey>::Key as crate::DefaultMeta>::Meta: Comparable + crate::Nullability,
ForeignKey: crate::Compatible<<<Parent as ModelKey>::Key as crate::DefaultMeta>::Meta>,
{
self.owner_key(model_key_field::<Parent>())
}
}
impl<'a, Child: Draftable, ForeignKey, ForeignMeta: crate::TypeMeta>
RequiredBelongsToMutBuilder<'a, Child, ForeignKey, ForeignMeta>
{
pub fn owner_key<Parent, OwnerKey, OwnerMeta: Comparable + crate::Nullability, OwnerField>(
self,
owner_key: OwnerField,
) -> BuiltBelongsToMut<
'a,
Child,
Parent,
ForeignKey,
ForeignMeta,
OwnerKey,
OwnerMeta,
OwnerField,
>
where
Parent: Qrafting + FromRow,
OwnerField: ReadableField<Parent, OwnerKey, OwnerMeta>,
ForeignKey: RelationForeignKeyRef<OwnerKey> + crate::Compatible<OwnerMeta>,
{
BuiltBelongsToMut {
child: self.child,
foreign_key: self.foreign_key,
owner_key,
_marker: PhantomData,
}
}
pub fn owner_model_key<Parent>(
self,
) -> BuiltBelongsToMut<
'a,
Child,
Parent,
ForeignKey,
ForeignMeta,
<Parent as ModelKey>::Key,
<<Parent as ModelKey>::Key as crate::DefaultMeta>::Meta,
ModelField<
Parent,
<Parent as ModelKey>::Key,
<<Parent as ModelKey>::Key as crate::DefaultMeta>::Meta,
>,
>
where
Parent: Qrafting + FromRow + ModelKey,
<Parent as ModelKey>::Key: crate::DefaultMeta,
ForeignKey: RelationForeignKeyRef<<Parent as ModelKey>::Key>
+ crate::Compatible<<<Parent as ModelKey>::Key as crate::DefaultMeta>::Meta>,
<<Parent as ModelKey>::Key as crate::DefaultMeta>::Meta: Comparable + crate::Nullability,
{
self.owner_key(model_key_field::<Parent>())
}
}
impl<'a, Child: Draftable, ForeignKey, ForeignMeta: crate::TypeMeta>
NullableBelongsToMutBuilderImpl<'a, Child, ForeignKey, ForeignMeta>
{
pub fn owner_key<Parent, OwnerKey, OwnerMeta: Comparable + crate::Nullability, OwnerField>(
self,
owner_key: OwnerField,
) -> BuiltNullableBelongsToMut<
'a,
Child,
Parent,
ForeignKey,
ForeignMeta,
OwnerKey,
OwnerMeta,
OwnerField,
>
where
Parent: Qrafting + FromRow,
OwnerField: ReadableField<Parent, OwnerKey, OwnerMeta>,
ForeignKey: RelationForeignKeyRef<OwnerKey> + crate::Compatible<OwnerMeta>,
{
BuiltNullableBelongsToMut {
child: self.child,
foreign_key: self.foreign_key,
owner_key,
_marker: PhantomData,
}
}
pub fn owner_model_key<Parent>(
self,
) -> BuiltNullableBelongsToMut<
'a,
Child,
Parent,
ForeignKey,
ForeignMeta,
<Parent as ModelKey>::Key,
<<Parent as ModelKey>::Key as crate::DefaultMeta>::Meta,
ModelField<
Parent,
<Parent as ModelKey>::Key,
<<Parent as ModelKey>::Key as crate::DefaultMeta>::Meta,
>,
>
where
Parent: Qrafting + FromRow + ModelKey,
<Parent as ModelKey>::Key: crate::DefaultMeta,
ForeignKey: RelationForeignKeyRef<<Parent as ModelKey>::Key>
+ crate::Compatible<<<Parent as ModelKey>::Key as crate::DefaultMeta>::Meta>,
<<Parent as ModelKey>::Key as crate::DefaultMeta>::Meta: Comparable + crate::Nullability,
{
self.owner_key(model_key_field::<Parent>())
}
}