Skip to main content

karbon_framework/db/
mod.rs

1mod database;
2mod builder;
3mod pagination;
4mod query;
5mod repository;
6mod paginated_query;
7#[cfg(test)]
8mod pagination_test;
9pub mod filter_value;
10pub mod seeder;
11
12pub use database::Database;
13pub use builder::{InsertBuilder, UpdateBuilder, DeleteBuilder, CountBuilder};
14pub use pagination::{Paginated, PaginationParams};
15pub use query::QueryBuilder;
16pub use repository::{CrudRepository, WhereValue};
17pub use paginated_query::PaginatedQuery;
18
19// ─── Database driver type aliases ───
20
21#[cfg(feature = "mysql")]
22pub type Db = sqlx::MySql;
23#[cfg(feature = "mysql")]
24pub type DbPool = sqlx::MySqlPool;
25#[cfg(feature = "mysql")]
26pub type DbPoolOptions = sqlx::mysql::MySqlPoolOptions;
27#[cfg(feature = "mysql")]
28pub type DbRow = sqlx::mysql::MySqlRow;
29#[cfg(feature = "mysql")]
30pub type DbArguments = sqlx::mysql::MySqlArguments;
31
32#[cfg(feature = "postgres")]
33pub type Db = sqlx::Postgres;
34#[cfg(feature = "postgres")]
35pub type DbPool = sqlx::PgPool;
36#[cfg(feature = "postgres")]
37pub type DbPoolOptions = sqlx::postgres::PgPoolOptions;
38#[cfg(feature = "postgres")]
39pub type DbRow = sqlx::postgres::PgRow;
40#[cfg(feature = "postgres")]
41pub type DbArguments = sqlx::postgres::PgArguments;
42
43// ─── SQL dialect helpers ───
44
45/// Returns a SQL placeholder for the given 1-based parameter index.
46/// MySQL: always `?`. PostgreSQL: `$1`, `$2`, etc.
47#[cfg(feature = "mysql")]
48pub fn placeholder(_n: usize) -> String {
49    "?".to_string()
50}
51
52#[cfg(feature = "postgres")]
53pub fn placeholder(n: usize) -> String {
54    format!("${}", n)
55}
56
57/// Generates an INSERT SQL string with the correct placeholder syntax.
58/// For PostgreSQL, appends `RETURNING id`.
59pub fn insert_sql(table: &str, columns: &[&str]) -> String {
60    let placeholders: Vec<String> = (1..=columns.len())
61        .map(placeholder)
62        .collect();
63
64    let base = format!(
65        "INSERT INTO {} ({}) VALUES ({})",
66        table,
67        columns.join(", "),
68        placeholders.join(", ")
69    );
70
71    #[cfg(feature = "mysql")]
72    { return base; }
73
74    #[cfg(feature = "postgres")]
75    { return format!("{} RETURNING id", base); }
76}
77
78/// Executes an INSERT query and returns the new row's ID.
79/// MySQL: uses `last_insert_id()`. PostgreSQL: uses `RETURNING id`.
80pub async fn execute_insert<'q, E>(
81    query: sqlx::query::Query<'q, Db, DbArguments>,
82    executor: E,
83) -> crate::error::AppResult<u64>
84where
85    E: sqlx::Executor<'q, Database = Db>,
86{
87    #[cfg(feature = "mysql")]
88    {
89        let result: <Db as sqlx::Database>::QueryResult = query.execute(executor).await?;
90        Ok(result.last_insert_id())
91    }
92
93    #[cfg(feature = "postgres")]
94    {
95        use sqlx::Row;
96        let row: DbRow = query.fetch_one(executor).await?;
97        let id: i64 = row.get(0);
98        Ok(id as u64)
99    }
100}