Skip to main content

sqlmodel_query/
lib.rs

1//! Type-safe SQL query builder for SQLModel Rust.
2//!
3//! `sqlmodel-query` is the **query construction layer**. It provides the fluent builder
4//! API and expression DSL that turn `Model` metadata into executable SQL plus parameters.
5//!
6//! # Role In The Architecture
7//!
8//! - **Query macros**: `select!`, `insert!`, `update!`, `delete!` build typed queries.
9//! - **Expression DSL**: `Expr` and operators build WHERE/HAVING clauses safely.
10//! - **Dialect support**: generates SQL for Postgres, MySQL, and SQLite.
11//!
12//! The resulting queries execute through the `Connection` trait from `sqlmodel-core`.
13//! Most users access these builders via the `sqlmodel` facade crate.
14
15pub mod builder;
16pub mod cache;
17pub mod clause;
18pub mod cte;
19pub mod eager;
20pub mod expr;
21pub mod join;
22pub mod select;
23pub mod set_ops;
24
25pub use builder::{
26    DeleteBuilder, InsertBuilder, InsertManyBuilder, OnConflict, QueryBuilder, SetClause,
27    UpdateBuilder,
28};
29pub use cache::{StatementCache, cache_key};
30pub use clause::{Limit, Offset, OrderBy, Where};
31pub use cte::{Cte, CteRef, WithQuery};
32pub use eager::{EagerLoader, IncludePath};
33pub use expr::{
34    BinaryOp, Dialect, Expr, UnaryOp, WindowBuilder, WindowFrame, WindowFrameBound, WindowFrameType,
35};
36pub use join::{Join, JoinType};
37pub use select::Select;
38pub use set_ops::{
39    SetOpType, SetOperation, except, except_all, intersect, intersect_all, union, union_all,
40};
41
42use asupersync::{Cx, Outcome};
43use sqlmodel_core::{Connection, Row, Value};
44
45/// Create a SELECT query for a model.
46///
47/// # Example
48///
49/// ```ignore
50/// let heroes = select!(Hero)
51///     .filter(Hero::age.gt(18))
52///     .order_by(Hero::name.asc())
53///     .all(cx, &conn)
54///     .await?;
55/// ```
56#[macro_export]
57macro_rules! select {
58    ($model:ty) => {
59        $crate::Select::<$model>::new()
60    };
61}
62
63/// Create an INSERT query for a model.
64///
65/// # Example
66///
67/// ```ignore
68/// let id = insert!(hero)
69///     .execute(cx, &conn)
70///     .await?;
71/// ```
72#[macro_export]
73macro_rules! insert {
74    ($model:expr) => {
75        $crate::builder::InsertBuilder::new($model)
76    };
77}
78
79/// Create a bulk INSERT query for multiple models.
80///
81/// # Example
82///
83/// ```ignore
84/// let heroes = vec![hero1, hero2, hero3];
85/// let count = insert_many!(heroes)
86///     .execute(cx, &conn)
87///     .await?;
88///
89/// // With UPSERT
90/// insert_many!(heroes)
91///     .on_conflict_do_update(&["name", "age"])
92///     .execute(cx, &conn)
93///     .await?;
94/// ```
95#[macro_export]
96macro_rules! insert_many {
97    ($models:expr) => {
98        $crate::builder::InsertManyBuilder::new($models)
99    };
100}
101
102/// Create an UPDATE query for a model.
103///
104/// # Example
105///
106/// ```ignore
107/// update!(hero)
108///     .execute(cx, &conn)
109///     .await?;
110/// ```
111#[macro_export]
112macro_rules! update {
113    ($model:expr) => {
114        $crate::builder::UpdateBuilder::new($model)
115    };
116}
117
118/// Create a DELETE query for a model.
119///
120/// # Example
121///
122/// ```ignore
123/// delete!(Hero)
124///     .filter(Hero::age.lt(18))
125///     .execute(cx, &conn)
126///     .await?;
127/// ```
128#[macro_export]
129macro_rules! delete {
130    ($model:ty) => {
131        $crate::builder::DeleteBuilder::<$model>::new()
132    };
133}
134
135/// Raw SQL query execution.
136///
137/// For queries that can't be expressed with the type-safe builder.
138pub async fn raw_query<C: Connection>(
139    cx: &Cx,
140    conn: &C,
141    sql: &str,
142    params: &[Value],
143) -> Outcome<Vec<Row>, sqlmodel_core::Error> {
144    conn.query(cx, sql, params).await
145}
146
147/// Raw SQL statement execution.
148pub async fn raw_execute<C: Connection>(
149    cx: &Cx,
150    conn: &C,
151    sql: &str,
152    params: &[Value],
153) -> Outcome<u64, sqlmodel_core::Error> {
154    conn.execute(cx, sql, params).await
155}