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}