Skip to main content

rullst_orm/
lib.rs

1pub use sqlx;
2
3/// The `chrono` crate whose `DateTime<Utc>`, `NaiveDateTime`, `NaiveDate` and
4/// `NaiveTime` model fields and [`RullstValue`] variants the ORM binds and
5/// decodes (with a strict driver feature; see `Blueprint::timestamp_tz`).
6pub use chrono;
7
8/// Auto-Healing Database Migrations & SQL Interceptor (Milestone 21).
9pub mod auto_healing;
10
11#[cfg(not(any(
12    feature = "strict-postgres",
13    feature = "strict-mysql",
14    feature = "strict-sqlite"
15)))]
16pub use sqlx::AnyPool as RullstPool;
17
18#[cfg(not(any(
19    feature = "strict-postgres",
20    feature = "strict-mysql",
21    feature = "strict-sqlite"
22)))]
23pub use sqlx::any::AnyPoolOptions as RullstPoolOptions;
24
25#[cfg(feature = "strict-postgres")]
26pub use sqlx::PgPool as RullstPool;
27
28#[cfg(feature = "strict-postgres")]
29pub use sqlx::postgres::PgPoolOptions as RullstPoolOptions;
30
31#[cfg(all(feature = "strict-mysql", not(feature = "strict-postgres")))]
32pub use sqlx::MySqlPool as RullstPool;
33
34#[cfg(all(feature = "strict-mysql", not(feature = "strict-postgres")))]
35pub use sqlx::mysql::MySqlPoolOptions as RullstPoolOptions;
36
37#[cfg(all(
38    feature = "strict-sqlite",
39    not(feature = "strict-postgres"),
40    not(feature = "strict-mysql")
41))]
42pub use sqlx::SqlitePool as RullstPool;
43
44#[cfg(all(
45    feature = "strict-sqlite",
46    not(feature = "strict-postgres"),
47    not(feature = "strict-mysql")
48))]
49pub use sqlx::sqlite::SqlitePoolOptions as RullstPoolOptions;
50
51// Hide underlying libraries for macro usage while keeping the public API clean
52#[doc(hidden)]
53pub use async_stream as _async_stream;
54#[doc(hidden)]
55pub use futures as _futures;
56#[doc(hidden)]
57pub use serde as _serde;
58#[doc(hidden)]
59pub use serde_json as _serde_json;
60#[doc(hidden)]
61pub use sqlx as _sqlx;
62#[doc(hidden)]
63pub use tracing as _tracing;
64
65#[cfg(feature = "pgvector")]
66#[doc(hidden)]
67pub use pgvector as _pgvector;
68
69#[cfg(feature = "redis")]
70#[doc(hidden)]
71pub use redis as _redis;
72
73pub mod admin;
74pub mod audit;
75pub mod collection;
76pub mod database;
77pub mod db;
78mod enum_codecs;
79pub mod error;
80pub mod intent;
81#[cfg(any(
82    feature = "redis",
83    feature = "turso",
84    feature = "scout-http",
85    feature = "qdrant",
86    feature = "surrealdb"
87))]
88mod loopback;
89pub mod outbox;
90pub mod policy;
91pub mod polyglot;
92pub mod pool;
93pub mod post_commit;
94pub mod privacy;
95#[cfg(feature = "redis")]
96#[doc(hidden)]
97pub mod query_cache;
98pub mod raw;
99#[cfg(feature = "redis")]
100pub mod redis_data;
101pub mod replica;
102pub mod repository;
103pub mod resource;
104pub mod schema;
105pub mod schema_diff;
106pub mod scout;
107#[doc(hidden)]
108pub mod telemetry;
109pub mod tenant;
110pub mod types;
111pub mod value;
112
113#[cfg(test)]
114mod tests;
115
116// Re-exports
117pub use _sqlx::FromRow;
118pub use admin::dashboard_html;
119pub use async_trait::async_trait;
120pub use collection::RullstCollection;
121pub use database::RullstDatabase;
122pub use error::RullstError as Error;
123pub use intent::IntentAnalyzer;
124pub use outbox::{ClaimedOutboxEvent, EnqueuedOutboxEvent, Outbox, OutboxMigration};
125#[cfg(feature = "pgvector")]
126pub use pgvector::Vector;
127pub use policy::Policy;
128pub use polyglot::{
129    Backend, BackendCapabilities, Capability, CollectionName, DocumentEntry, DocumentId,
130    DocumentInventory, DocumentPage, DocumentRecoveryBinding, DocumentRecoveryError,
131    DocumentRecoveryKey, DocumentRecoveryPolicy, DocumentRecoveryReport, DocumentRepository,
132    EncryptedDocumentSnapshot, MockDocumentStore, PolyglotError, export_document_snapshot,
133    restore_document_snapshot,
134};
135#[cfg(feature = "qdrant")]
136pub use polyglot::{
137    QdrantConfig, QdrantStore, VectorCollectionName, VectorDimensions, VectorMatch, VectorPoint,
138    VectorQueryLimit, VectorRepository,
139};
140#[doc(hidden)]
141pub use pool::portable_subquery;
142#[doc(hidden)]
143pub use pool::raw_fragment;
144pub use pool::{
145    Orm, PaginationResult, RagContext, RullstModel, Seeder, is_lazy_loading_prevented,
146    prevent_lazy_loading, replace_placeholders,
147};
148pub use post_commit::{ModelCommittedEvent, ModelOperation, after_commit};
149pub use privacy::{ComplianceModel, PrivacyReport, SecretString};
150#[cfg(feature = "redis")]
151pub use redis_data::{
152    RedisDataConfig, RedisDataKey, RedisDataStore, RedisField, RedisMember, RedisScanLimit,
153    RedisStructure, RedisStructuresRepository, RedisValue, ScoredRedisMember,
154};
155pub use replica::ReplicaPool;
156pub use repository::{GenericRepository, Repository};
157pub use resource::{ApiResource, JsonResource, ResourceCollection};
158pub use rullst_orm_macros::{Enum, Nexus, Orm, PersonalData, TursoModel, test};
159pub use schema::{DatabaseEnum, JoinClause, SubqueryBuilder};
160#[cfg(feature = "scout-http")]
161pub use scout::{AlgoliaEngine, ElasticsearchEngine, MeilisearchEngine};
162pub use scout::{MockSearchEngine, SearchEngine, get_search_engine, set_search_engine};
163pub use tenant::{get_tenant_id, with_tenant};
164pub use types::Json;
165pub use value::RullstValue;
166
167#[doc(hidden)]
168#[path = "transaction_access.rs"]
169pub mod __transaction_access;
170
171#[doc(hidden)]
172#[path = "eager_limit.rs"]
173pub mod __eager_limit;
174
175#[doc(hidden)]
176#[path = "relation_key.rs"]
177pub mod __relation_key;
178
179tokio::task_local! {
180    pub static CURRENT_TX: std::sync::Arc<tokio::sync::Mutex<Option<crate::db::Transaction<'static>>>>;
181}
182
183/// Serializes SQLite tests generated by `#[rullst_orm::test]` within one test
184/// process. SQLite schema changes can otherwise race with another sandbox
185/// transaction and fail nondeterministically with `SQLITE_LOCKED`.
186#[doc(hidden)]
187pub static TEST_SANDBOX_LOCK: tokio::sync::Mutex<()> = tokio::sync::Mutex::const_new(());
188
189#[macro_export]
190macro_rules! execute_query {
191    ($query:expr, $method:ident, $pool_fn:ident) => {{
192        $crate::__transaction_access::ensure_allowed()?;
193        if let Ok(tx_arc) = $crate::CURRENT_TX.try_with(|tx| tx.clone()) {
194            let mut tx_guard = tx_arc.lock().await;
195            if let Some(tx) = tx_guard.as_mut() {
196                $query.$method(&mut **tx).await
197            } else {
198                let pool = $crate::Orm::$pool_fn()?;
199                $query.$method(pool).await
200            }
201        } else {
202            let pool = $crate::Orm::$pool_fn()?;
203            $query.$method(pool).await
204        }
205    }};
206}
207
208#[macro_export]
209macro_rules! dispatch_executor {
210    ($pool_fn:ident, |$executor:ident| $e:expr) => {{
211        $crate::__transaction_access::ensure_allowed()?;
212        if let Ok(tx_arc) = $crate::CURRENT_TX.try_with(|tx| tx.clone()) {
213            let mut tx_guard = tx_arc.lock().await;
214            if let Some(tx) = tx_guard.as_mut() {
215                let $executor = &mut **tx;
216                $e
217            } else {
218                let $executor = $crate::Orm::$pool_fn()?;
219                $e
220            }
221        } else {
222            let $executor = $crate::Orm::$pool_fn()?;
223            $e
224        }
225    }};
226}