sqlorm_core/traits.rs
1use crate::Driver;
2use crate::Pool;
3use crate::Row;
4use crate::TableInfo;
5use crate::selectable::Selectable;
6use async_trait::async_trait;
7use sqlx::Acquire;
8
9/// Describes a database table and its metadata used by the query builder.
10///
11/// Implement this trait for your entity types to enable type-safe query building.
12/// It provides static metadata such as table name, primary key, and available columns.
13pub trait Table {
14 /// The table name in the database.
15 const TABLE_NAME: &'static str;
16 /// The primary key column name.
17 const PK: &'static str;
18 /// The list of selectable columns for this table.
19 const COLUMNS: &'static [&'static str];
20 const SQL_NAME: &'static str;
21 const ALIASED_SQL_NAME: &'static str;
22
23 /// Returns a TableInfo instance used by the query builder.
24 fn table_info() -> TableInfo;
25}
26
27/// Constructs a value from a database row where columns were projected with aliases.
28///
29/// Implementations should read values from row using the composed alias+column format
30/// produced by the query builder's projections.
31pub trait FromAliasedRow {
32 /// Builds `Self` from an aliased row.
33 fn from_aliased_row(row: &Row) -> sqlx::Result<Self>
34 where
35 Self: Sized + Default;
36}
37
38/// Executes a built query and returns typed results.
39///
40/// This trait is implemented for the query builder type, allowing you to fetch typed
41/// rows directly into your domain structs that implement `sqlx::FromRow`.
42///
43/// # Examples
44///
45/// PostgreSQL
46///
47/// ```ignore
48/// use sqlorm_core::{qb::{QB, Column}, TableInfo, GenericExecutor, Pool};
49/// use std::marker::PhantomData;
50///
51/// # async fn run(pool: &Pool) -> sqlx::Result<()> {
52/// let base = TableInfo {
53/// name: "users",
54/// alias: "u".to_string(),
55/// columns: vec!["id", "name"],
56/// };
57///
58/// let qb1 = QB::<()>::new(base)
59/// .select::<(i32, String)>(vec!["id", "name"])
60/// .filter(Column::<i32> {
61/// name: "id",
62/// table_alias: "u",
63/// aliased_name: "u__id",
64/// _marker: PhantomData,
65/// }.eq(1));
66///
67/// let one: (i32, String) = qb1.fetch_one_as(pool).await?;
68///
69/// let qb2 = QB::<()>::new(TableInfo {
70/// name: "users",
71/// alias: "u".to_string(),
72/// columns: vec!["id", "name"],
73/// })
74/// .select::<(i32, String)>(vec!["id", "name"])
75/// .filter(Column::<i32> {
76/// name: "id",
77/// table_alias: "u",
78/// aliased_name: "u__id",
79/// _marker: PhantomData,
80/// }.gt(0));
81///
82/// let many: Vec<(i32, String)> = qb2.fetch_all_as(pool).await?;
83/// # Ok(())
84/// # }
85#[async_trait]
86pub trait GenericExecutor<T> {
87 /// Executes the query and returns a single row mapped as `T`.
88 async fn fetch_one_as<'a, A: Send + Acquire<'a, Database = Driver>>(
89 self,
90 pool: A,
91 ) -> sqlx::Result<T>;
92 /// Executes the query and returns all rows mapped as `T`.
93 async fn fetch_all_as<'a, A: Send + Acquire<'a, Database = Driver>>(
94 self,
95 pool: A,
96 ) -> sqlx::Result<Vec<T>>;
97}
98
99#[async_trait]
100pub trait StatementExecutor<T: Table> {
101 async fn execute<'a, E>(self, acquirer: E) -> sqlx::Result<T>
102 where
103 E: Send + crate::sqlx::Acquire<'a, Database = Driver>;
104}