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