pub struct Pivot<L = i64, R = i64> { /* private fields */ }Expand description
A many-to-many relation through a pivot table with two id columns, e.g.
Pivot::new("product_tags", "product_id", "tag_id"). Give the table a
unique index on both columns. The table may have more columns (a role, a
quantity): set them with Pivot::attach_with and
Pivot::update_pivot, read them with Pivot::load_with_pivot.
L and R are the key types of the two sides, i64 unless given:
const TAGS: Pivot<Ulid, i64> = Pivot::new("invoice_tags", "invoice_id", "tag_id");
Implementations§
Source§impl<L, R> Pivot<L, R>
impl<L, R> Pivot<L, R>
Sourcepub const fn new(
table: &'static str,
left: &'static str,
right: &'static str,
) -> Self
pub const fn new( table: &'static str, left: &'static str, right: &'static str, ) -> Self
A pivot table joining the left key column to the right key column.
Sourcepub const fn with_timestamps(self) -> Self
pub const fn with_timestamps(self) -> Self
The pivot table has created_at and updated_at columns, which
attaching and Pivot::update_pivot fill.
Source§impl<L: ModelKey, R: ModelKey> Pivot<L, R>
impl<L: ModelKey, R: ModelKey> Pivot<L, R>
Sourcepub async fn ids<'c>(&self, db: impl Executor<'c>, left: L) -> Result<Vec<R>>
pub async fn ids<'c>(&self, db: impl Executor<'c>, left: L) -> Result<Vec<R>>
The right-hand ids linked to left.
Sourcepub async fn attach<'c>(
&self,
db: impl Executor<'c>,
left: L,
rights: impl IntoIterator<Item = R>,
) -> Result<u64>
pub async fn attach<'c>( &self, db: impl Executor<'c>, left: L, rights: impl IntoIterator<Item = R>, ) -> Result<u64>
Links left to each of rights that isn’t linked yet; returns how
many links were added.
Sourcepub async fn attach_with<'c>(
&self,
db: impl Executor<'c>,
left: L,
right: R,
data: PivotData<'_>,
) -> Result<bool>
pub async fn attach_with<'c>( &self, db: impl Executor<'c>, left: L, right: R, data: PivotData<'_>, ) -> Result<bool>
Links left to right with extra pivot columns, unless they’re
linked already (change those with Pivot::update_pivot); returns
whether a link was added.
const MEMBERS: Pivot = Pivot::new("team_user", "team_id", "user_id").with_timestamps();
MEMBERS.attach_with(&db, 1, 7, &[("role", &"admin")]).await?;
MEMBERS.update_pivot(&db, 1, 7, &[("role", &"member")]).await?;Sourcepub async fn update_pivot<'c>(
&self,
db: impl Executor<'c>,
left: L,
right: R,
data: PivotData<'_>,
) -> Result<bool>
pub async fn update_pivot<'c>( &self, db: impl Executor<'c>, left: L, right: R, data: PivotData<'_>, ) -> Result<bool>
Changes extra columns of the link between left and right (and
updated_at with timestamps); returns whether they were linked.
Sourcepub async fn toggle(
&self,
db: &Db,
left: L,
rights: impl IntoIterator<Item = R>,
) -> Result<(Vec<R>, Vec<R>)>
pub async fn toggle( &self, db: &Db, left: L, rights: impl IntoIterator<Item = R>, ) -> Result<(Vec<R>, Vec<R>)>
Links each of rights that isn’t linked to left and unlinks each
that is, in one transaction; returns (attached, detached).
Sourcepub async fn detach<'c>(
&self,
db: impl Executor<'c>,
left: L,
rights: impl IntoIterator<Item = R>,
) -> Result<u64>
pub async fn detach<'c>( &self, db: impl Executor<'c>, left: L, rights: impl IntoIterator<Item = R>, ) -> Result<u64>
Unlinks left from rights; returns how many links were removed.
Sourcepub async fn sync(
&self,
db: &Db,
left: L,
rights: impl IntoIterator<Item = R>,
) -> Result
pub async fn sync( &self, db: &Db, left: L, rights: impl IntoIterator<Item = R>, ) -> Result
Makes left linked to exactly rights (e.g. the checked boxes of a
form), in one transaction.
Sourcepub fn load<'a, T: Model<Key = R> + Clone>(
&'a self,
db: &'a Db,
lefts: impl IntoIterator<Item = L>,
) -> impl Future<Output = Result<HashMap<L, Vec<T>>>> + Send + 'a
pub fn load<'a, T: Model<Key = R> + Clone>( &'a self, db: &'a Db, lefts: impl IntoIterator<Item = L>, ) -> impl Future<Output = Result<HashMap<L, Vec<T>>>> + Send + 'a
The right-hand models linked to each left id, in one query per table.
Sourcepub fn load_with_pivot<'a, T: Model<Key = R> + Clone, D: FromRow + Send + 'a>(
&'a self,
db: &'a Db,
lefts: impl IntoIterator<Item = L>,
) -> impl Future<Output = Result<HashMap<L, Vec<(T, D)>>>> + Send + 'a
pub fn load_with_pivot<'a, T: Model<Key = R> + Clone, D: FromRow + Send + 'a>( &'a self, db: &'a Db, lefts: impl IntoIterator<Item = L>, ) -> impl Future<Output = Result<HashMap<L, Vec<(T, D)>>>> + Send + 'a
Like Pivot::load, with each model’s pivot row decoded as D
(a #[derive(FromRow)] struct naming the pivot columns it wants).
#[derive(FromRow)]
struct Membership { role: String }
let members = MEMBERS.load_with_pivot::<User, Membership>(&db, [1]).await?;
for (user, membership) in members.get(&1).map_or(&[][..], Vec::as_slice) {
println!("{} is {}", user.name, membership.role);
}Trait Implementations§
Auto Trait Implementations§
impl<L, R> Freeze for Pivot<L, R>
impl<L, R> RefUnwindSafe for Pivot<L, R>
impl<L, R> Send for Pivot<L, R>
impl<L, R> Sync for Pivot<L, R>
impl<L, R> Unpin for Pivot<L, R>
impl<L, R> UnsafeUnpin for Pivot<L, R>
impl<L, R> UnwindSafe for Pivot<L, R>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<A, B, T> HttpServerConnExec<A, B> for Twhere
B: Body,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more