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}