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
18    /// Returns a TableInfo instance used by the query builder.
19    fn table_info() -> TableInfo;
20}
21
22/// Constructs a value from a database row where columns were projected with aliases.
23///
24/// Implementations should read values from row using the composed alias+column format
25/// produced by the query builder's projections.
26pub trait FromAliasedRow {
27    /// Builds `Self` from an aliased row.
28    fn from_aliased_row(row: &Row) -> sqlx::Result<Self>
29    where
30        Self: Sized + Default;
31}
32
33/// Executes a built query and returns typed results.
34///
35/// This trait is implemented for the query builder type, allowing you to fetch typed
36/// rows directly into your domain structs that implement `sqlx::FromRow`.
37///
38/// # Examples
39///
40/// PostgreSQL
41///
42/// ```ignore
43/// use sqlorm_core::{qb::{QB, Column}, TableInfo, Executor, Pool};
44/// use std::marker::PhantomData;
45///
46/// # async fn run(pool: &Pool) -> sqlx::Result<()> {
47/// let base = TableInfo { name: "users", alias: "u".to_string(), columns: vec!["id", "name"] };
48/// let qb1 = QB::<()>::new(base)
49///     .select::<(i32, String)>(vec!["id", "name"])
50///     .filter(Column::<i32> { name: "id", table_alias: "u", _marker: PhantomData }.eq(1));
51/// let one: (i32, String) = qb1.fetch_one_as(pool).await?;
52/// let qb2 = QB::<()>::new(TableInfo { name: "users", alias: "u".to_string(), columns: vec!["id", "name"] })
53///     .select::<(i32, String)>(vec!["id", "name"])
54///     .filter(Column::<i32> { name: "id", table_alias: "u", _marker: PhantomData }.gt(0));
55/// let many: Vec<(i32, String)> = qb2.fetch_all_as(pool).await?;
56/// # Ok(())
57/// # }
58/// ```
59///
60/// SQLite
61///
62/// ```no_run
63/// use sqlorm_core::{qb::{QB, Column}, TableInfo, Executor, Pool};
64/// use std::marker::PhantomData;
65///
66/// # async fn run(pool: &Pool) -> sqlx::Result<()> {
67/// let base = TableInfo { name: "users", alias: "u".to_string(), columns: vec!["id", "name"] };
68/// let qb1 = QB::<()>::new(base)
69///     .select::<(i32, String)>(vec!["id", "name"])
70///     .filter(Column::<i32> { name: "id", table_alias: "u", _marker: PhantomData }.eq(1));
71/// let one: (i32, String) = qb1.fetch_one_as(pool).await?;
72/// let qb2 = QB::<()>::new(TableInfo { name: "users", alias: "u".to_string(), columns: vec!["id", "name"] })
73///     .select::<(i32, String)>(vec!["id", "name"])
74///     .filter(Column::<i32> { name: "id", table_alias: "u", _marker: PhantomData }.gt(0));
75/// let many: Vec<(i32, String)> = qb2.fetch_all_as(pool).await?;
76/// # Ok(())
77/// # }
78/// ```
79#[async_trait]
80pub trait Executor<T> {
81    /// Executes the query and returns a single row mapped as `T`.
82    async fn fetch_one_as(self, pool: &Pool) -> sqlx::Result<T>;
83    /// Executes the query and returns all rows mapped as `T`.
84    async fn fetch_all_as(self, pool: &Pool) -> sqlx::Result<Vec<T>>;
85}