1use async_trait::async_trait;
8use sqlx::database::Database;
9use sqlx::{Executor, IntoArguments};
10
11use crate::bind::Bind;
12use crate::query::{Query, QueryError};
13use crate::runtime::sql;
14use crate::schema::Table;
15use crate::{Error, ForeignKey, Result};
16
17#[async_trait]
22pub trait RefersTo<Other>
23where
24 Self: Table + Bind,
25 Other: Table + Bind + Unpin + Sync,
26{
27 const FOREIGN_KEY: ForeignKey<Self>;
28
29 async fn resolve<'e, E>(&self, executor: E) -> Result<Other>
32 where
33 E: Executor<'e, Database = crate::Driver>,
34 for<'q> <crate::Driver as Database>::Arguments<'q>: IntoArguments<'q, crate::Driver> + Send,
35 {
36 let Query { builder, .. } = sql::select::<Other>();
37
38 let mut query = sqlx::query_as(builder.sql());
39
40 let fk = Self::FOREIGN_KEY.as_col();
41 query = self.bind(&fk, query).unwrap();
42
43 query
44 .persistent(false)
45 .fetch_one(executor)
46 .await
47 .map_err(QueryError::from)
48 .map_err(Error::Query)
49 }
50}
51
52#[async_trait]
58pub trait ReferredBy<Other>
59where
60 Self: Table + Bind + Unpin + Sync,
61 Other: Table + Bind + RefersTo<Self> + Unpin + Sync,
62{
63 async fn resolve<'e, E>(&self, executor: E) -> Result<Vec<Other>>
65 where
66 E: Executor<'e, Database = crate::Driver>,
67 for<'q> <crate::Driver as Database>::Arguments<'q>: IntoArguments<'q, crate::Driver> + Send,
68 {
69 let Query { builder, .. } = sql::select_by::<Other>(Other::FOREIGN_KEY.as_col());
70
71 let mut query = sqlx::query_as(builder.sql());
72
73 let pk = Self::PRIMARY_KEY.as_col();
74 query = self.bind(&pk, query).unwrap();
75
76 query
77 .persistent(false)
78 .fetch_all(executor)
79 .await
80 .map_err(QueryError::from)
81 .map_err(Error::Query)
82 }
83
84 async fn resolve_by<'e, E>(executor: E, pk: &Self::PrimaryKey) -> Result<Vec<Other>>
86 where
87 E: Executor<'e, Database = crate::Driver>,
88 for<'q> <crate::Driver as Database>::Arguments<'q>: IntoArguments<'q, crate::Driver> + Send,
89 {
90 let Query { builder, .. } = sql::select_by::<Other>(Other::FOREIGN_KEY.as_col());
91
92 sqlx::query_as(builder.sql())
93 .bind(pk)
94 .persistent(false)
95 .fetch_all(executor)
96 .await
97 .map_err(QueryError::from)
98 .map_err(Error::Query)
99 }
100
101 async fn delete_all<'e, E>(
103 &self,
104 executor: E,
105 ) -> Result<<crate::Driver as sqlx::Database>::QueryResult>
106 where
107 E: Executor<'e, Database = crate::Driver>,
108 for<'q> <crate::Driver as Database>::Arguments<'q>: IntoArguments<'q, crate::Driver> + Send,
109 {
110 let Query { builder, .. } = sql::delete_by::<Other>(Other::FOREIGN_KEY.as_col());
111
112 let mut query = sqlx::query(builder.sql());
113
114 let pk = Self::PRIMARY_KEY.as_col();
115 query = self.bind(&pk, query).unwrap();
116
117 query
118 .persistent(false)
119 .execute(executor)
120 .await
121 .map_err(QueryError::from)
122 .map_err(Error::Query)
123 }
124}