sz_orm_core/lib.rs
1//! # SZ-ORM — Xianshida ORM
2//!
3//! Rust asynchronous ORM workspace (production-ready), ThinkORM-style compatible.
4//!
5//! **Production evidence**: 67 packages published to crates.io · 321 references in sz-pay production · 5159+ tests pass.
6//!
7//! ## Architecture Overview
8//!
9//! The SZ-ORM workspace consists of **71 members** (69 sz-orm-* libs + cli + examples):
10//!
11//! ### Core Engine (sz-orm-core)
12//! | Module | Function |
13//! |------|------|
14//! | `model` | `Model` trait — defines table name, primary key, timestamps, soft delete, relations |
15//! | `query` | `QueryBuilder<M>` — chainable API, supports SELECT/INSERT/UPDATE/DELETE/aggregation/pagination/JOIN |
16//! | `dialect` | Multi-database dialects — MySQL (backtick), PostgreSQL (double quote), SQLite, Oracle 23ai |
17//! | `pool` | Asynchronous connection pool — configurable size, timeout, idle reaping, health checks, max lifetime |
18//! | `transaction` | ACID transactions — isolation levels, savepoints, `TransactionManager` for multi-transaction management |
19//! | `migration` | File-based migration system — up/down/rollback/reset/refresh, with `SchemaBuilder` |
20//! | `cache` | Multi-level cache — `MemoryCache`, `MultiLevelCache`, with TTL support |
21//! | `value` | Unified value type — 20 variants (integer/float/string/bytes/UUID/date/JSON/array) |
22//! | `db_type` | Database type enum — MySQL, PostgreSQL, SQLite, Oracle, Redis, MongoDB and 11 total |
23//! | `error` | Error type system — `DbError` (20 variants), `PoolError`, `CacheError`, `TxError` |
24//!
25//! ### Database Adapters
26//! - **sz-orm-sqlx** — sqlx adapter, connects to real MySQL/PostgreSQL/SQLite/Oracle
27//! - **sz-orm-sql-validator** — SQL validation and injection detection
28//!
29//! ### Extension Ecosystem Packages (18)
30//! | Package | Function |
31//! |------|------|
32//! | sz-orm-crypto | Crypto primitives (AES-256-GCM, PBKDF2, HMAC-SHA256) |
33//! | sz-orm-auth | JWT authentication (HS256) |
34//! | sz-orm-scheduler | Cron scheduled task dispatch |
35//! | sz-orm-mqtt | MQTT client (rumqttc) |
36//! | sz-orm-websocket | WebSocket server (tokio-tungstenite) |
37//! | sz-orm-queue | Message queue (RabbitMQ/lapin, Kafka, NATS, ActiveMQ, RocketMQ, Pulsar) |
38//! | sz-orm-storage | Object storage (S3/Alibaba Cloud/Tencent Cloud/Huawei Cloud/Qiniu/Upyun/Local) |
39//! | sz-orm-ai | AI integration (Embedding, RAG, Vector) |
40//! | sz-orm-grpc | gRPC server/client |
41//! | sz-orm-graphql | GraphQL query support |
42//! | sz-orm-es | Elasticsearch integration |
43//! | sz-orm-tracing | Distributed tracing |
44//! | sz-orm-logger | Logging system |
45//! | sz-orm-swagger | API documentation generation |
46//! | sz-orm-masking | Data masking |
47//! | sz-orm-health | Health checks |
48//! | sz-orm-audit | Audit log |
49//! | sz-orm-batch | Batch operations |
50//!
51//! ### Advanced Feature Packages (6)
52//! | Package | Function |
53//! |------|------|
54//! | sz-orm-dtx | Distributed transactions |
55//! | sz-orm-rw | Read-write splitting |
56//! | sz-orm-sharding | Sharding |
57//! | sz-orm-limit | Rate limiting |
58//! | sz-orm-config | Configuration management |
59//! | sz-orm-mig | Enhanced migration management |
60//!
61//! ### Platform Support
62//! - **sz-orm-wasm** — WebAssembly compile target
63//! - **sz-orm-lc** — Local/edge computing
64//! - **sz-orm-back** — Backup and restore
65//!
66//! ## Quick Start
67//!
68//! ```rust,ignore
69//! use sz_orm_core::*;
70//!
71//! // 1. Define the model
72//! #[derive(Clone)]
73//! struct User {
74//! id: i64,
75//! name: String,
76//! email: String,
77//! }
78//!
79//! impl Model for User {
80//! type PrimaryKey = i64;
81//! fn table_name() -> &'static str { "users" }
82//! fn pk(&self) -> Self::PrimaryKey { self.id }
83//! fn set_pk(&mut self, pk: Self::PrimaryKey) { self.id = pk; }
84//! }
85//!
86//! // 2. Build a query
87//! let dialect = get_dialect(DbType::MySQL).unwrap();
88//! let sql = QueryBuilder::<User>::new(dialect)
89//! .table("users")
90//! .select(vec!["id", "name", "email"])
91//! .where_eq("status", Value::String("active".to_string()))
92//! .order_by("created_at")
93//! .order_desc("id")
94//! .limit(10)
95//! .build_select();
96//!
97//! // 3. Validate before execution
98//! QueryBuilder::<User>::new(get_dialect(DbType::MySQL).unwrap())
99//! .table("users")
100//! .select(vec!["id", "name"])
101//! .validate()?; // Validate SQL syntax, injection, parenthesis balance
102//!
103//! // 4. Other operations
104//! let mut data = std::collections::HashMap::new();
105//! data.insert("name".to_string(), Value::String("Alice".to_string()));
106//! data.insert("age".to_string(), Value::I64(25));
107//!
108//! let insert_sql = QueryBuilder::<User>::new(dialect)
109//! .table("users")
110//! .build_insert(&data);
111//!
112//! let update_sql = QueryBuilder::<User>::new(get_dialect(DbType::MySQL).unwrap())
113//! .table("users")
114//! .where_eq("id", Value::I64(1))
115//! .build_update(&data);
116//!
117//! let delete_sql = QueryBuilder::<User>::new(get_dialect(DbType::MySQL).unwrap())
118//! .table("users")
119//! .where_eq("id", Value::I64(1))
120//! .build_delete();
121//! ```
122//!
123//! ## Supported Databases
124//!
125//! | Database | Dialect Implementation | Real Connection | Quoting |
126//! |--------|---------|---------|---------|
127//! | MySQL | `MySqlDialect` (`` ` `` backtick) | sz-orm-sqlx | ✅ |
128//! | PostgreSQL | `PostgreSqlDialect` (`"` double quote) | sz-orm-sqlx | ✅ |
129//! | SQLite 3.35+ | `SqliteDialect` (`"` double quote) | sz-orm-sqlx | ✅ |
130//! | Oracle 23ai | `OracleDialect` (automatic type mapping) | sz-orm-sqlx | ✅ |
131//!
132//! Obtain a dialect instance via `get_dialect(DbType::MySQL)`. Each dialect handles:
133//! - Identifier quoting style
134//! - String escaping rules
135//! - Pagination syntax (LIMIT/OFFSET vs OFFSET/FETCH)
136//! - JSON extraction functions (JSON_EXTRACT vs #>> vs json_extract vs JSON_VALUE)
137//! - Full-text search (MATCH AGAINST vs to_tsvector vs CONTAINS)
138//! - Boolean-to-integer conversion (IF/CASE)
139//! - Auto-increment keyword (AUTO_INCREMENT/GENERATED BY DEFAULT AS IDENTITY)
140//!
141//! ## Core Features in Detail
142//!
143//! ### QueryBuilder API
144//!
145//! Most query methods return `Self`, enabling chainable calls; validation methods like `select`/`having`
146//! return `Result<Self>` (after audit M-5/M-6, column names/aggregate expressions go through identifier validation):
147//!
148//! ```rust,ignore
149//! // Basic query
150//! QueryBuilder::<M>::new(dialect)
151//! .table("users")
152//! .select(vec!["id", "name"])? // Column validation + quote
153//! .where_eq("status", Value::String("active".to_string())) // AND
154//! .or_where_eq("role", Value::String("admin".to_string())) // OR
155//! .where_in("id", vec![Value::I64(1), Value::I64(2)])
156//! .where_between("age", Value::I64(18), Value::I64(30))
157//! .where_null("deleted_at")
158//! .order_by("created_at")
159//! .order_desc("id")
160//! .group_by("status")
161//! .having(AggExpr::CountStar, HavingOp::Gt, Value::I64(5))? // Parameterized HAVING
162//! .limit(20)
163//! .offset(40)
164//! .page(3, 20) // page=3, page_size=20
165//! .join_inner("posts", "users.id", "posts.user_id")
166//! .join_left("profiles", "users.id", "profiles.user_id")
167//! .build_select();
168//!
169//! // Aggregate functions
170//! builder.build_count(); // SELECT COUNT(*)
171//! builder.build_exists(); // SELECT EXISTS(...)
172//! builder.build_max("score");
173//! builder.build_min("price");
174//! builder.build_sum("amount");
175//! builder.build_avg("value");
176//! ```
177//!
178//! ### SQL Validation
179//!
180//! ```rust,ignore
181//! // Compile-time + runtime dual validation
182//! builder.validate()?; // Validate SELECT
183//! builder.validate_insert(&data)?; // Validate INSERT (including empty data check)
184//! builder.validate_update(&data)?; // Validate UPDATE (including empty data check)
185//! builder.validate_delete()?; // Validate DELETE
186//!
187//! // Validation covers: SQL syntax, injection detection, parenthesis balance,
188//! // table/column name legitimacy, JOIN column validation
189//! ```
190//!
191//! ### Model Trait
192//!
193//! ```rust,ignore
194//! pub trait Model: Send + Sync + Sized + 'static {
195//! type PrimaryKey: Send + Sync + Debug + Display + Clone + Default;
196//!
197//! fn table_name() -> &'static str; // Table name (required)
198//! fn pk_name() -> &'static str { "id" } // Primary key column name
199//! fn pk(&self) -> Self::PrimaryKey; // Get primary key value
200//! fn set_pk(&mut self, pk: Self::PrimaryKey); // Set primary key value
201//! fn foreign_key(relation: &str) -> String; // Foreign key naming "user_id"
202//! fn timestamp_fields() -> Option<TimestampFields>; // Automatic timestamps
203//! fn soft_delete_field() -> Option<&'static str>; // Soft delete field
204//! }
205//!
206//! // ModelExt extension
207//! pub trait ModelExt: Model {
208//! fn columns() -> Vec<&'static str>; // All columns
209//! fn fillable() -> Vec<&'static str>; // Fillable columns
210//! fn guarded() -> Vec<&'static str>; // Guarded columns (includes primary key by default)
211//! fn hidden() -> Vec<&'static str>; // Hidden columns (not serialized)
212//! fn relations() -> HashMap<&str, Relation>; // Relations
213//! fn fill(&mut self, data: HashMap<String, Value>); // Mass assignment
214//! fn to_json(&self) -> serde_json::Value; // Serialize
215//! }
216//!
217//! // Four relation types
218//! // BelongsTo — many-to-one (Order → User)
219//! // HasMany — one-to-many (User → Orders)
220//! // HasOne — one-to-one (User → Profile)
221//! // BelongsToMany — many-to-many (User ↔ Role, through junction table)
222//! ```
223//!
224//! ### Connection Pool
225//!
226//! ```rust,ignore
227//! // Configure via Builder
228//! let config = PoolConfigBuilder::new()
229//! .max_size(100) // Maximum connections
230//! .min_idle(10) // Minimum idle connections
231//! .acquire_timeout(30) // Acquire timeout (seconds)
232//! .idle_timeout(600) // Idle timeout (seconds)
233//! .max_lifetime(1800) // Max lifetime (seconds)
234//! .build()?;
235//!
236//! let pool = Pool::new(config, factory)?;
237//! let conn = pool.acquire().await?; // Acquire connection (with timeout)
238//! pool.release(conn).await; // Release connection
239//! pool.status().await; // PoolStatus { idle, active, max, min }
240//! pool.reap_idle().await; // Reap idle connections
241//! pool.close_all().await; // Close all connections
242//! ```
243//!
244//! ### Transactions
245//!
246//! ```rust,ignore
247//! // Transaction options
248//! let opts = TransactOptions::default()
249//! .with_isolation(IsolationLevel::Serializable)
250//! .read_only()
251//! .with_timeout(Duration::from_secs(30));
252//!
253//! let mut tx = Transaction::new(conn, opts);
254//! tx.execute("INSERT INTO users VALUES (1)").await?;
255//! tx.query("SELECT * FROM users").await?;
256//!
257//! // Savepoints (nested transactions)
258//! let sp = tx.savepoint().await?; // SAVEPOINT sp_N
259//! tx.rollback_to_savepoint(&sp).await?; // ROLLBACK TO SAVEPOINT sp_N
260//! tx.release_savepoint(&sp).await?; // RELEASE SAVEPOINT sp_N
261//!
262//! tx.commit().await?;
263//! // tx.rollback().await?;
264//!
265//! // TransactionManager: manages multiple named transactions
266//! let mgr = TransactionManager::new();
267//! mgr.begin("tx1", conn, opts).await?;
268//! mgr.commit("tx1").await?;
269//! mgr.list().await; // ["tx1"]
270//! mgr.state("tx1").await; // Some(TransactionState::Committed)
271//! ```
272//!
273//! ### Migration System
274//!
275//! ```rust,ignore
276//! // File naming: <version>_<name>_up.sql / <version>_<name>_down.sql
277//! // Example: 001_create_users_up.sql, 001_create_users_down.sql
278//!
279//! let resolver = FileMigrationResolver::new(PathBuf::from("./migrations"));
280//! let migrations = resolver.resolve(DbType::MySQL)?;
281//!
282//! let mut migrator = Migrator::new(MigrationContext::default())
283//! .add_migrations(migrations);
284//!
285//! migrator.migrate().await?; // Execute all pending migrations
286//! migrator.up(Some("003")).await?; // Migrate up to specified version
287//! migrator.down(Some("001")).await?; // Rollback to specified version
288//! migrator.rollback("002").await?; // Rollback a single migration
289//! migrator.reset().await?; // Rollback all + re-execute
290//! migrator.refresh().await?; // Same as reset
291//! migrator.progress(); // MigrationProgress { total, applied, pending }
292//!
293//! // SchemaBuilder: programmatic table creation
294//! let sql = SchemaBuilder::new("users")
295//! .add_column(ColumnDef::new("id", "INT").not_null().auto_increment())
296//! .add_column(ColumnDef::new("name", "VARCHAR").length(255).not_null())
297//! .add_index(IndexDef::new("idx_name", vec!["name"]).unique())
298//! .add_foreign_key(
299//! ForeignKeyDef::new("fk_role", "role_id", "roles", "id")
300//! .on_delete("CASCADE")
301//! )
302//! .build(DbType::MySQL);
303//! ```
304//!
305//! ### Value Type
306//!
307//! ```rust,ignore
308//! // 20 variants, covering all database types
309//! Value::Null | Bool(bool) | I8..I64 | U8..U64 | F32 | F64
310//! | String(String) | Bytes(Vec<u8>) | Uuid(String) | Date(String)
311//! | DateTime(String) | Time(String) | Json(String) | Array(Vec<Value>)
312//!
313//! // Type conversions
314//! value.as_str() // Option<&str>
315//! value.as_i64() // Option<i64> (supports F32/F64/Bool/String→i64 conversion)
316//! value.as_f64() // Option<f64>
317//! value.as_bool() // Option<bool> (supports "true"/"1"/"yes"/"on" etc.)
318//! value.as_bytes() // Option<&[u8]>
319//! value.to_param() // Cow<str> — SQL parameter format
320//!
321//! // From implementations
322//! let v: Value = 42i64.into();
323//! let v: Value = "hello".into();
324//! let v: Value = vec![1u8, 2u8].into();
325//! ```
326//!
327//! ## Error Handling
328//!
329//! Unified error type system, each error carries a unique error code:
330//!
331//! ```rust,ignore
332//! // DbError — 20 variants, error codes DB001-DB020
333//! DbError::QueryError("...")
334//! DbError::ConnectionRefused("...")
335//! DbError::ConnectionTimeout("...")
336//! DbError::NotFound("...")
337//! DbError::ConstraintViolation("...")
338//! // ... etc.
339//!
340//! // PoolError — 6 variants, error codes PL001-PL006
341//! PoolError::Exhausted | Timeout | AlreadyAcquired | InvalidConfig | ...
342//!
343//! // CacheError — 6 variants, error codes CH001-CH006
344//! // TxError — 6 variants (NotStarted, CommitFailed, SavepointError, etc.)
345//!
346//! // Convenience methods
347//! DbError::query("test failed") // Create query error
348//! DbError::connection("timeout") // Create connection error
349//! DbError::not_found("user #42") // Create not-found error
350//! err.is_retryable() // Whether retryable
351//! err.error_code() // "DB001"
352//! ```
353//!
354//! ## Validation Methods
355//!
356//! SZ-ORM ensures quality through a **7-layer validation system**:
357//!
358//! | Method | Description | Test File |
359//! |---------|------|---------|
360//! | **TDD** | 115+ unit tests for core modules | `core.rs` |
361//! | **Integration** | End-to-end with real MySQL/PG/SQLite/Oracle | `integration_mysql.rs`, `integration_pg.rs`, `integration_sqlite.rs` |
362//! | **Jepsen** | 29 concurrency correctness tests + 10 real DB Jepsen | `jepsen.rs`, `real_db_jepsen.rs` |
363//! | **Fuzz** | 11 boundary/edge case discoveries | `fuzz.rs` |
364//! | **Stress** | 77 performance benchmarks | `stress.rs`, `core_bench.rs` |
365//! | **Chaos** | 16 fault robustness tests | `chaos.rs` |
366//! | **Formal** | 14 formal verification invariants | `formal.rs` |
367//!
368//! **Total: 1,723 tests** (1,317 `#[test]` + 406 `#[tokio::test]`; some require real services)
369//!
370//! ## Type Aliases and Constants
371//!
372//! ```rust,ignore
373//! // Type aliases
374//! pub type Shared<T> = Arc<T>;
375//! pub type Boxed<T> = Box<T>;
376//! pub type DbResult<T> = Result<T, DbError>;
377//! pub type PoolResult<T> = Result<T, PoolError>;
378//! pub type CacheResult<T> = Result<T, CacheError>;
379//! pub type TxResult<T> = Result<T, TxError>;
380//!
381//! // Default constants
382//! pub const DEFAULT_BATCH_SIZE: usize = 1000;
383//! pub const DEFAULT_ACQUIRE_TIMEOUT: u64 = 30; // seconds
384//! pub const DEFAULT_IDLE_TIMEOUT: u64 = 600; // seconds
385//! pub const DEFAULT_MAX_LIFETIME: u64 = 1800; // seconds
386//! pub const DEFAULT_MIN_IDLE: u32 = 5;
387//! pub const DEFAULT_MAX_SIZE: u32 = 100;
388//! ```
389//!
390//! ## Export Manifest
391//!
392//! `use sz_orm_core::*;` imports all public symbols from the following modules:
393//!
394//! - `async_trait` (re-exported), `bytes::Bytes`, `chrono::{DateTime, Utc}`, `serde::{Deserialize, Serialize}`
395//! - `cache::*` — `Cache`, `MemoryCache`, `MultiLevelCache`, `CacheStats`
396//! - `db_type::*` — `DbType` enum (11 database types)
397//! - `dialect::*` — `Dialect`, `MySqlDialect`, `PostgreSqlDialect`, `SqliteDialect`, `OracleDialect`, `get_dialect()`
398//! - `error::*` — `DbError`, `PoolError`, `CacheError`, `TxError`
399//! - `migration::*` — `Migration`, `Migrator`, `SchemaBuilder`, `ColumnDef`, `IndexDef`, `ForeignKeyDef`
400//! - `model::*` — `Model`, `ModelExt`, `Relation`, `BelongsTo`, `HasMany`, `HasOne`, `BelongsToMany`
401//! - `pool::*` — `Pool`, `PoolConfig`, `PoolConfigBuilder`, `Connection`, `ConnectionFactory`, `PoolStatus`
402//! - `query::*` — `QueryBuilder<M>` (chainable SQL builder)
403//! - `transaction::*` — `Transaction`, `TransactionManager`, `TransactOptions`, `IsolationLevel`
404//! - `value::*` — `Value` enum (20 variants)
405
406// 文档完整性:全局启用 missing_docs lint(v3.6.0 已补齐全部 pub API 文档)
407#![warn(missing_docs)]
408
409// v3.9.0 M1-T3:derive(Validate) 宏生成 sz_orm_core 绝对路径,
410// crate 内部测试需 self 别名使该路径解析到当前 crate
411#[cfg(test)]
412extern crate self as sz_orm_core;
413
414use std::sync::Arc;
415
416/// Re-export async traits
417pub use async_trait::async_trait;
418
419/// Re-export common types
420pub use bytes::Bytes;
421pub use chrono::{DateTime, Utc};
422pub use serde::{Deserialize, Serialize};
423
424pub mod access_control;
425pub mod accessors;
426pub mod active_model;
427#[allow(missing_docs)]
428pub mod api_coverage;
429pub mod behaviors;
430#[cfg(feature = "benchmark-suite")]
431pub mod benchmark;
432pub mod bloom;
433mod cache;
434pub mod change_tracker;
435pub mod circuit_breaker;
436#[cfg(feature = "type-safe-columns")]
437pub mod column;
438#[cfg(feature = "zero-copy")]
439pub mod columnar;
440#[cfg(any(
441 feature = "prepared-stmt-cache",
442 feature = "async-row-stream",
443 feature = "parallel-batch"
444))]
445pub mod connection_ext;
446pub mod cursor_stream;
447pub mod cycle_detection;
448pub mod data_permission;
449mod db_type;
450pub mod dialect;
451#[cfg(feature = "prod-dialect-security")]
452pub mod dialect_security;
453pub mod dirty_attributes;
454#[cfg(feature = "dist-cache")]
455pub mod dist_cache;
456#[cfg(feature = "dist-cache-cluster")]
457#[allow(missing_docs)]
458pub mod dist_cache_cluster;
459pub mod dynamic_filter;
460pub mod dynamic_sql;
461pub mod eager_loader;
462pub mod entity_graph;
463mod error;
464pub mod find_with_related;
465#[cfg(feature = "compile-governance")]
466pub mod governance;
467pub mod guard;
468pub mod hooks;
469pub mod hydration_plugin;
470pub mod i18n;
471pub mod join_dsl;
472pub mod json_query;
473#[cfg(feature = "l1-cache")]
474pub mod l1_cache;
475pub mod l2_cache;
476pub mod lambda;
477pub mod lazy_loader;
478pub mod linq;
479pub mod migration;
480#[cfg(feature = "migration-dry-run")]
481pub mod migration_dry_run;
482pub mod mock;
483mod model;
484#[cfg(feature = "multi-tenant-pool")]
485#[allow(missing_docs)]
486pub mod multi_tenant_pool;
487pub mod n1_eliminator;
488pub mod nested_active_model;
489pub mod observer;
490pub mod optimistic_lock;
491pub mod paginator;
492pub mod partial_model;
493pub mod phinx_migration;
494#[cfg(feature = "plan-cache")]
495pub mod plan_cache;
496pub mod plugin;
497mod pool;
498#[cfg(feature = "prepared-stmt-cache")]
499pub mod prepared_cache;
500#[cfg(feature = "auto-prewarm")]
501pub mod prewarm;
502#[cfg(feature = "prod-ready")]
503pub mod prod_ready_check;
504mod query;
505pub mod query_cache;
506#[cfg(feature = "query-result-cache")]
507#[allow(missing_docs)]
508pub mod query_result_cache;
509#[cfg(feature = "async-row-stream")]
510pub mod row_stream;
511#[cfg(feature = "rw-split-enhanced")]
512#[allow(missing_docs)]
513pub mod rw_split_enhanced;
514#[cfg(feature = "saga-tx")]
515#[allow(missing_docs)]
516pub mod saga;
517
518#[cfg(feature = "pool-elastic")]
519#[allow(missing_docs)]
520pub mod pool_elastic;
521
522#[cfg(feature = "io-uring")]
523#[allow(missing_docs)]
524pub mod io_uring_probe;
525
526#[cfg(feature = "field-encryption")]
527#[allow(missing_docs)]
528pub mod field_cipher;
529
530#[cfg(feature = "data-validation")]
531pub mod validation;
532/// Re-export QueryBuilder for external use
533pub use query::QueryBuilder;
534#[cfg(feature = "adaptive-query")]
535pub mod adaptive_adapter;
536#[cfg(feature = "cache-coherence")]
537pub mod cache_coherence;
538#[cfg(feature = "l1-cache")]
539#[allow(missing_docs)]
540pub mod cache_warmup_protection;
541#[cfg(feature = "config-center")]
542pub mod config_adapter;
543#[cfg(feature = "connection-level-tenant")]
544pub mod connection_tenant;
545#[cfg(feature = "forward-compat-sandbox")]
546#[allow(missing_docs)]
547pub mod forward_compat_sandbox;
548#[cfg(feature = "graph")]
549pub mod graph_adapter;
550#[cfg(feature = "graphql")]
551pub mod graphql_adapter;
552#[cfg(feature = "structured-logging")]
553pub mod logger_adapter;
554#[cfg(feature = "postgis")]
555pub mod postgis_adapter;
556#[cfg(feature = "read-write-splitting")]
557pub mod rw_adapter;
558#[cfg(feature = "search")]
559pub mod search_adapter;
560#[cfg(feature = "timeseries")]
561pub mod timeseries_adapter;
562#[cfg(feature = "distributed-tracing")]
563pub mod tracing_adapter;
564
565#[cfg(feature = "migration-branch")]
566pub mod migration_branch;
567#[cfg(feature = "l1-cache")]
568pub mod process_l1_cache;
569#[cfg(feature = "qb-migration-tool")]
570pub mod qb_migration_fix;
571#[cfg(feature = "qb-migration-tool")]
572pub mod qb_migration_lint;
573pub mod queryable;
574pub mod quick_query;
575pub mod rate_limiter;
576pub mod relation_trait;
577pub mod repository;
578pub mod result_map;
579pub mod retry;
580#[cfg(feature = "zero-downtime-rollback")]
581pub mod rollback_zero_downtime;
582#[cfg(feature = "schema-diff-viz")]
583pub mod schema_diff_viz;
584pub mod schema_gen;
585pub mod schema_sync;
586#[cfg(feature = "data-seeding")]
587pub mod seeding;
588pub mod select_types;
589pub mod shadow;
590#[cfg(feature = "simd")]
591pub mod simd;
592pub mod smart_eager_loader;
593pub mod sql_buffer;
594pub mod sql_safety;
595#[cfg(feature = "sql-verify-proc")]
596pub mod sql_verify;
597pub mod stream_api;
598#[cfg(feature = "streaming-export")]
599pub mod streaming_export;
600pub mod telemetry;
601#[cfg(feature = "multi-tenant-enhanced")]
602pub mod tenant_context;
603#[cfg(feature = "tenant-quota-rls-enhanced")]
604#[allow(missing_docs)]
605pub mod tenant_quota_rls;
606#[cfg(feature = "multi-tenant-enhanced")]
607pub mod tenant_security;
608mod transaction;
609pub mod type_handler;
610pub mod typed;
611pub mod typed_ast;
612#[cfg(feature = "typed-relation")]
613pub mod typed_relation;
614mod value;
615#[cfg(feature = "zero-copy")]
616pub mod value_borrowed;
617#[cfg(feature = "zero-copy-deep")]
618#[allow(missing_docs)]
619pub mod zero_copy_pipeline;
620
621#[cfg(any(
622 feature = "cdc-mysql",
623 feature = "cdc-postgres",
624 feature = "cdc-sqlite"
625))]
626#[allow(missing_docs)]
627pub mod cdc;
628
629#[cfg(feature = "executor-opt")]
630#[allow(missing_docs)]
631pub mod executor_passes;
632
633// Re-export proc macros
634pub use queryable::Query;
635pub use queryable::QueryAs;
636pub use sz_orm_macros::api_beta;
637pub use sz_orm_macros::api_stable;
638pub use sz_orm_macros::migrate;
639pub use sz_orm_macros::query;
640pub use sz_orm_macros::query_as;
641pub use sz_orm_macros::schema;
642pub use sz_orm_macros::sql_string;
643pub use sz_orm_macros::typed_query;
644// FromQueryResult derive 宏(与 value.rs 中同名 trait 通过显式 use 遮蔽 glob 导出)
645#[cfg(feature = "n1-lint")]
646pub use sz_orm_macros::detect_n_plus_one;
647pub use sz_orm_macros::FromQueryResult;
648pub use sz_orm_macros::RelationTrait;
649#[cfg(feature = "data-validation")]
650pub use sz_orm_macros::Validate;
651
652pub use change_tracker::{ChangeTracker, EntityEntry, EntityState};
653pub use lazy_loader::{LazyCollection, LazyLoader, LazyRef};
654pub use linq::LinqQuery;
655pub use query_cache::{QueryCache, QueryCacheKey, TimestampCache};
656
657pub use cache::*;
658pub use cycle_detection::{CycleDetector, CyclePolicy};
659pub use db_type::*;
660#[allow(ambiguous_glob_reexports)]
661pub use dialect::*;
662pub use eager_loader::NestedEagerResult;
663pub use error::*;
664#[allow(ambiguous_glob_reexports)]
665pub use migration::*;
666pub use model::*;
667pub use nested_active_model::CascadeStrategy;
668pub use pool::*;
669#[allow(unused_imports)]
670pub use query::*;
671pub use schema_sync::{Confirm, DataMigrationHook, DestructiveSyncResult};
672pub use transaction::*;
673pub use value::*;
674
675/// Alias for `Arc<T>`
676pub type Shared<T> = Arc<T>;
677
678/// Alias for `Box<T>`
679pub type Boxed<T> = Box<T>;
680
681/// Alias for Result<T, DbError>
682pub type DbResult<T> = Result<T, DbError>;
683
684/// Result type for pool operations
685pub type PoolResult<T> = Result<T, PoolError>;
686
687/// Result type for cache operations
688pub type CacheResult<T> = Result<T, CacheError>;
689
690/// Result type for transaction operations
691pub type TxResult<T> = Result<T, TxError>;
692
693/// Default batch size for bulk operations
694pub const DEFAULT_BATCH_SIZE: usize = 1000;
695
696/// Default connection timeout in seconds
697pub const DEFAULT_ACQUIRE_TIMEOUT: u64 = 30;
698
699/// Default idle timeout in seconds
700pub const DEFAULT_IDLE_TIMEOUT: u64 = 600;
701
702/// Default max lifetime in seconds
703pub const DEFAULT_MAX_LIFETIME: u64 = 1800;
704
705/// Default minimum idle connections
706pub const DEFAULT_MIN_IDLE: u32 = 5;
707
708/// Default maximum pool size
709pub const DEFAULT_MAX_SIZE: u32 = 100;
710
711#[cfg(test)]
712mod tests {
713 use super::*;
714 use std::error::Error;
715
716 #[test]
717 fn test_db_type() {
718 assert_eq!(DbType::MySQL.as_str(), "mysql");
719 assert_eq!(DbType::PostgreSQL.as_str(), "postgres");
720 assert_eq!(DbType::Sqlite.as_str(), "sqlite");
721 }
722
723 #[test]
724 fn test_value() {
725 let v = Value::Null;
726 assert!(v.is_null());
727
728 let v = Value::I64(42);
729 assert!(v.is_i64());
730
731 let v = Value::String("hello".to_string());
732 assert!(v.is_string());
733 }
734
735 #[test]
736 fn test_db_error_display() {
737 let err = DbError::QueryError("test query failed".to_string());
738 assert_eq!(format!("{}", err), "Query error: test query failed");
739
740 let err = DbError::ConnectionRefused("localhost".to_string());
741 assert_eq!(format!("{}", err), "Connection refused: localhost");
742 }
743
744 #[test]
745 fn test_db_error_source() {
746 let err = DbError::PoolError(PoolError::Timeout);
747 assert!(err.source().is_some());
748 }
749
750 #[tokio::test]
751 async fn test_async_trait_export() {
752 fn _check_send_sync<T: Send + Sync>() {}
753
754 struct TestImpl;
755 #[async_trait]
756 trait AsyncFoo: Send + Sync {
757 async fn foo(&self);
758 }
759
760 #[async_trait]
761 impl AsyncFoo for TestImpl {
762 async fn foo(&self) {}
763 }
764
765 let impl_ = TestImpl;
766 impl_.foo().await;
767 _check_send_sync::<TestImpl>();
768 }
769
770 // ---- compile-time SQL validation macro tests ----
771
772 /// Valid SQL should compile and be usable as a string
773 #[test]
774 fn test_sql_string_valid_select() {
775 let sql = sql_string!("SELECT * FROM users WHERE id = 1");
776 assert!(sql.contains("SELECT"));
777 assert!(sql.contains("FROM"));
778 }
779
780 #[test]
781 fn test_sql_string_valid_insert() {
782 let sql = sql_string!("INSERT INTO users (name) VALUES ('alice')");
783 assert!(sql.contains("INSERT"));
784 }
785
786 #[test]
787 fn test_sql_string_valid_update() {
788 let sql = sql_string!("UPDATE users SET name = 'bob' WHERE id = 1");
789 assert!(sql.contains("UPDATE"));
790 }
791
792 #[test]
793 fn test_sql_string_valid_delete() {
794 let sql = sql_string!("DELETE FROM users WHERE id = 1");
795 assert!(sql.contains("DELETE"));
796 }
797
798 #[test]
799 fn test_sql_string_valid_create() {
800 let sql = sql_string!("CREATE TABLE test (id INT PRIMARY KEY)");
801 assert!(sql.contains("CREATE"));
802 }
803
804 #[test]
805 fn test_sql_string_with_params() {
806 let sql = sql_string!("SELECT * FROM users WHERE id = ?"; params: 1);
807 assert!(sql.contains("?"));
808 }
809
810 #[test]
811 fn test_sql_string_complex_query() {
812 let sql = sql_string!(
813 "SELECT u.*, o.total FROM users u LEFT JOIN orders o ON u.id = o.user_id WHERE u.status = 'active'"
814 );
815 assert!(sql.contains("LEFT JOIN"));
816 }
817
818 #[test]
819 fn test_sql_string_nested_parens() {
820 let sql = sql_string!("SELECT * FROM (SELECT * FROM users) t");
821 assert!(sql.contains("SELECT"));
822 }
823}