Skip to main content

prax_query/relations/
meta.rs

1//! Metadata describing a relation between two models.
2//!
3//! Every relation emitted by codegen materializes as a zero-sized type
4//! implementing [`RelationMeta`]. The meta trait carries enough type-level
5//! and const-level information for the runtime relation executor
6//! ([`super::executor`]) to build the secondary SELECT statement for
7//! an `.include()` call without reflection.
8//!
9//! # Kinds
10//!
11//! - [`RelationKind::BelongsTo`] — the owner holds a FK to the target's PK.
12//!   `LOCAL_KEY` is the owner's column pointing at the target.
13//! - [`RelationKind::HasMany`] — the target holds a FK to the owner's PK.
14//!   `FOREIGN_KEY` is the target's column pointing back at the owner.
15//! - [`RelationKind::HasOne`] — like `HasMany` but with a uniqueness
16//!   constraint on the target's FK column.
17//!
18//! The trait itself is deliberately inert — it is consulted by the
19//! executor and never implements any actual loading logic. That keeps
20//! the per-model impl emitted by the derive macro trivial.
21
22use crate::traits::Model;
23
24/// Classification of a relation between two models.
25#[derive(Debug, Clone, Copy, PartialEq, Eq)]
26pub enum RelationKind {
27    /// Owner holds a foreign key to the target's primary key.
28    BelongsTo,
29    /// Target holds a foreign key to the owner's primary key (1-to-N).
30    HasMany,
31    /// Target holds a unique foreign key to the owner's primary key (1-to-1).
32    HasOne,
33}
34
35/// Each relation emitted by codegen materializes as a zero-sized type
36/// implementing this trait. `Owner` is the model declaring the relation;
37/// `Target` is the related model. `LOCAL_KEY` is the column on `Owner`
38/// that references `Target` (for `BelongsTo`); `FOREIGN_KEY` is the
39/// column on `Target` that references `Owner`'s PK (for `HasMany` /
40/// `HasOne`).
41pub trait RelationMeta {
42    /// The model declaring the relation.
43    type Owner: Model;
44    /// The related model.
45    type Target: Model;
46    /// Field name on `Owner` (also the string key of the matching
47    /// [`super::IncludeSpec`]).
48    const NAME: &'static str;
49    /// Classification of this relation (see [`RelationKind`]).
50    const KIND: RelationKind;
51    /// Column on `Owner` that references `Target` (used for
52    /// `BelongsTo`). For `HasMany` / `HasOne` this is conventionally
53    /// `"id"`.
54    const LOCAL_KEY: &'static str;
55    /// Column on `Target` that references `Owner`'s PK (used for
56    /// `HasMany` / `HasOne`). For `BelongsTo` this is conventionally
57    /// `"id"`.
58    const FOREIGN_KEY: &'static str;
59}