Skip to main content

prax_query/
lib.rs

1// QueryError carries diagnostic context (source location, parameter list,
2// vendor metadata) so the Result Err arm is intentionally large; boxing it
3// uniformly across the public API would be a breaking change for every caller.
4#![allow(clippy::result_large_err)]
5// Several builder types expose `new` constructors that return associated
6// builder structs rather than `Self`; this is intentional for the staged
7// builder pattern.
8#![allow(clippy::new_ret_no_self)]
9// Methods like `Filter::add`, `SqlBuilder::add` and `from_str` use vendor-named
10// methods that can collide with stdlib trait method names. They are not
11// intended as `std::ops::Add` / `FromStr` impls.
12#![allow(clippy::should_implement_trait)]
13#![allow(clippy::wrong_self_convention)]
14
15//! # prax-query
16//!
17//! Type-safe query builder for the Prax ORM.
18//!
19//! This crate provides the core query building functionality, including:
20//! - Fluent API for building queries (`find_many`, `find_unique`, `create`, `update`, `delete`)
21//! - Type-safe filtering with `where` clauses
22//! - Sorting and pagination
23//! - Relation loading (`include`, `select`)
24//! - Transaction support
25//! - Raw SQL escape hatch
26//! - Middleware system
27//! - Multi-tenant support
28//!
29//! ## Filters
30//!
31//! Build type-safe filters for queries:
32//!
33//! ```rust
34//! use prax_query::{Filter, FilterValue};
35//!
36//! // Equality filter
37//! let filter = Filter::Equals("email".into(), FilterValue::String("test@example.com".into()));
38//!
39//! // Greater than filter
40//! let filter = Filter::Gt("age".into(), FilterValue::Int(18));
41//!
42//! // Contains filter (for strings)
43//! let filter = Filter::Contains("name".into(), FilterValue::String("john".into()));
44//!
45//! // Combine filters with AND/OR
46//! let combined = Filter::and([
47//!     Filter::Equals("active".into(), FilterValue::Bool(true)),
48//!     Filter::Gt("age".into(), FilterValue::Int(18)),
49//! ]);
50//!
51//! let either = Filter::or([
52//!     Filter::Equals("role".into(), FilterValue::String("admin".into())),
53//!     Filter::Equals("role".into(), FilterValue::String("moderator".into())),
54//! ]);
55//! ```
56//!
57//! ## Filter Values
58//!
59//! Convert Rust types to filter values:
60//!
61//! ```rust
62//! use prax_query::FilterValue;
63//!
64//! // Integer values
65//! let val: FilterValue = 42.into();
66//! assert!(matches!(val, FilterValue::Int(42)));
67//!
68//! // String values
69//! let val: FilterValue = "hello".into();
70//! assert!(matches!(val, FilterValue::String(_)));
71//!
72//! // Boolean values
73//! let val: FilterValue = true.into();
74//! assert!(matches!(val, FilterValue::Bool(true)));
75//!
76//! // Float values
77//! let val: FilterValue = 3.14f64.into();
78//! assert!(matches!(val, FilterValue::Float(_)));
79//!
80//! // Null values
81//! let val = FilterValue::Null;
82//! ```
83//!
84//! ## Sorting
85//!
86//! Build sort specifications:
87//!
88//! ```rust
89//! use prax_query::{OrderBy, OrderByField, NullsOrder};
90//!
91//! // Ascending order
92//! let order = OrderByField::asc("created_at");
93//!
94//! // Descending order
95//! let order = OrderByField::desc("updated_at");
96//!
97//! // With NULLS FIRST/LAST
98//! let order = OrderByField::asc("name").nulls(NullsOrder::First);
99//! let order = OrderByField::desc("score").nulls(NullsOrder::Last);
100//!
101//! // Combine multiple orderings
102//! let orders = OrderBy::Field(OrderByField::asc("name"))
103//!     .then(OrderByField::desc("created_at"));
104//! ```
105//!
106//! ## Raw SQL
107//!
108//! Build raw SQL queries with parameter binding:
109//!
110//! ```rust
111//! use prax_query::Sql;
112//!
113//! // Simple query
114//! let sql = Sql::new("SELECT * FROM users");
115//! assert_eq!(sql.sql(), "SELECT * FROM users");
116//!
117//! // Query with parameter - bind appends placeholder
118//! let sql = Sql::new("SELECT * FROM users WHERE id = ")
119//!     .bind(42);
120//! assert_eq!(sql.params().len(), 1);
121//! ```
122//!
123//! ## Connection Strings
124//!
125//! Parse database connection strings:
126//!
127//! ```rust
128//! use prax_query::ConnectionString;
129//!
130//! // PostgreSQL
131//! let conn = ConnectionString::parse("postgres://user:pass@localhost:5432/mydb").unwrap();
132//! assert_eq!(conn.host(), Some("localhost"));
133//! assert_eq!(conn.port(), Some(5432));
134//! assert_eq!(conn.database(), Some("mydb"));
135//!
136//! // MySQL
137//! let conn = ConnectionString::parse("mysql://user:pass@localhost:3306/mydb").unwrap();
138//! ```
139//!
140//! ## Transaction Config
141//!
142//! Configure transaction behavior:
143//!
144//! ```rust
145//! use prax_query::IsolationLevel;
146//!
147//! let level = IsolationLevel::Serializable;
148//! assert_eq!(level.as_sql(), "SERIALIZABLE");
149//! ```
150//!
151//! ## Error Handling
152//!
153//! Work with query errors:
154//!
155//! ```rust
156//! use prax_query::{QueryError, ErrorCode};
157//!
158//! // Create errors
159//! let err = QueryError::not_found("User");
160//! assert_eq!(err.code, ErrorCode::RecordNotFound);
161//! ```
162
163pub mod advanced;
164pub mod async_optimize;
165pub mod batch;
166pub mod builder;
167pub mod cache;
168pub mod connection;
169pub mod cte;
170pub mod data;
171#[allow(dead_code, unused_imports)]
172pub mod data_cache;
173pub mod db_optimize;
174pub mod dialect;
175pub mod error;
176pub mod extension;
177pub mod filter;
178pub mod intern;
179pub mod introspection;
180pub mod json;
181pub mod lazy;
182pub mod logging;
183#[macro_use]
184pub mod macros;
185pub mod mem_optimize;
186pub mod memory;
187pub mod middleware;
188pub mod nested;
189pub mod operations;
190pub mod pagination;
191pub mod partition;
192pub mod pool;
193pub mod procedure;
194pub mod profiling;
195pub mod query;
196pub mod raw;
197pub mod relations;
198pub mod replication;
199pub mod row;
200pub mod search;
201pub mod security;
202pub mod sequence;
203pub mod sql;
204pub mod static_filter;
205pub mod tenant;
206pub mod traits;
207pub mod transaction;
208pub mod trigger;
209pub mod typed_filter;
210pub mod types;
211pub mod upsert;
212pub mod window;
213pub mod zero_copy;
214
215pub use error::{ErrorCode, ErrorContext, QueryError, QueryResult, Suggestion};
216pub use extension::{Extension, ExtensionBuilder, Point, Polygon};
217pub use filter::{
218    AndFilterBuilder, FieldName, Filter, FilterValue, FluentFilterBuilder, LargeValueList,
219    OrFilterBuilder, ScalarFilter, SmallValueList, ToFilterValue, ValueList,
220};
221pub use json::{JsonAgg, JsonFilter, JsonIndex, JsonIndexBuilder, JsonOp, JsonPath, PathSegment};
222pub use nested::{NestedWrite, NestedWriteBuilder, NestedWriteOp, NestedWriteOperations};
223pub use operations::{
224    AggregateField,
225    AggregateOperation,
226    AggregateResult,
227    CountOperation,
228    CreateManyOperation,
229    CreateOperation,
230    DeleteManyOperation,
231    DeleteOperation,
232    FindFirstOperation,
233    FindManyOperation,
234    FindUniqueOperation,
235    GroupByOperation,
236    GroupByResult,
237    HavingCondition,
238    HavingOp,
239    // View operations
240    MaterializedViewAccessor,
241    RefreshMaterializedViewOperation,
242    UpdateManyOperation,
243    UpdateOperation,
244    UpsertOperation,
245    ViewAccessor,
246    ViewCountOperation,
247    ViewFindFirstOperation,
248    ViewFindManyOperation,
249    ViewQueryBuilder,
250    having,
251};
252pub use pagination::{Cursor, CursorDirection, Pagination};
253pub use partition::{
254    HashPartitionDef, ListPartitionDef, Partition, PartitionBuilder, PartitionDef, PartitionType,
255    RangeBound, RangePartitionDef,
256};
257pub use procedure::{
258    Parameter, ParameterMode, ProcedureCall, ProcedureCallOperation, ProcedureEngine,
259    ProcedureResult,
260};
261pub use query::QueryBuilder;
262pub use raw::{RawExecuteOperation, RawQueryOperation, Sql};
263pub use relations::{
264    Include, IncludeSpec, RelationKind, RelationLoader, RelationMeta, RelationSpec, SelectSpec,
265};
266pub use search::{
267    FullTextIndex, FullTextIndexBuilder, FuzzyOptions, HighlightOptions, RankingOptions,
268    SearchLanguage, SearchMode, SearchQuery, SearchQueryBuilder, SearchSql,
269};
270pub use security::{
271    ConnectionProfile, ConnectionProfileBuilder, DataMask, Grant, GrantBuilder, GrantObject,
272    MaskFunction, PolicyCommand, Privilege, RlsPolicy, RlsPolicyBuilder, Role, RoleBuilder,
273    TenantPolicy, TenantSource,
274};
275pub use sequence::{OwnedBy, Sequence, SequenceBuilder};
276pub use traits::{
277    Executable, IntoFilter, MaterializedView, Model, ModelRelationLoader, ModelWithPk, QueryEngine,
278    View, ViewQueryEngine,
279};
280pub use transaction::{IsolationLevel, Transaction, TransactionConfig};
281pub use trigger::{
282    Trigger, TriggerAction, TriggerBuilder, TriggerCondition, TriggerEvent, TriggerLevel,
283    TriggerTiming, UpdateOf,
284};
285pub use types::{
286    NullsOrder, OrderBy, OrderByBuilder, OrderByField, Select, SortOrder, order_patterns,
287};
288pub use upsert::{
289    Assignment, AssignmentValue, ConflictAction, ConflictTarget, UpdateSpec, Upsert, UpsertBuilder,
290};
291pub use window::{
292    FrameBound, FrameClause, FrameExclude, FrameType, NamedWindow, NullsPosition, OrderSpec,
293    WindowFn, WindowFunction, WindowFunctionBuilder, WindowSpec,
294};
295
296// Re-export middleware types
297pub use middleware::{
298    LoggingMiddleware, MetricsMiddleware, Middleware, MiddlewareBuilder, MiddlewareChain,
299    MiddlewareStack, QueryContext, QueryMetadata, QueryMetrics, QueryType, RetryMiddleware,
300    TimingMiddleware,
301};
302
303// Re-export dialect types
304pub use dialect::{Mssql, Mysql, NotSql, Postgres, SqlDialect, Sqlite};
305
306// Re-export connection types
307pub use connection::{
308    ConnectionError, ConnectionOptions, ConnectionString, DatabaseConfig, Driver, EnvExpander,
309    MultiDatabaseConfig, PoolConfig, PoolOptions, SslConfig, SslMode,
310};
311pub use cte::{
312    Cte, CteBuilder, CycleClause, Materialized, SearchClause, SearchMethod, WithClause,
313    WithQueryBuilder,
314};
315
316// Re-export advanced query types
317pub use advanced::{
318    BulkOperation, DistinctOn, LateralJoin, LateralJoinBuilder, LateralJoinType, LockStrength,
319    LockWait, ReturnOperation, Returning, ReturningColumn, RowLock, RowLockBuilder, SampleMethod,
320    SampleSize, TableSample, TableSampleBuilder,
321};
322
323// Re-export data types
324pub use data::{
325    BatchCreate, ConnectData, CreateData, DataBuilder, FieldValue, IntoData, UpdateData,
326};
327
328// Re-export introspection types
329pub use introspection::{
330    CheckConstraint, ColumnInfo, DatabaseSchema, EnumInfo, ForeignKeyInfo, IndexColumn, IndexInfo,
331    NormalizedType, ReferentialAction, SequenceInfo, TableInfo, UniqueConstraint, ViewInfo,
332    generate_prax_schema, normalize_type,
333};
334
335// Re-export tenant types
336pub use tenant::{
337    DynamicResolver, IsolationStrategy, RowLevelConfig, SchemaConfig, StaticResolver, TenantConfig,
338    TenantConfigBuilder, TenantContext, TenantId, TenantInfo, TenantMiddleware, TenantResolver,
339};
340
341// Re-export intern types
342pub use intern::{clear_interned, fields, intern, intern_cow, interned_count};
343
344// Re-export pool types
345pub use pool::{FilterBuilder, FilterPool, IntoPooledValue, PooledFilter, PooledValue};
346
347// Re-export SQL builder types
348pub use sql::{
349    AdvancedQueryCapacity, CachedSql, DatabaseType, FastSqlBuilder, LazySql, QueryCapacity,
350    SqlBuilder, SqlTemplateCache as SqlCache, global_sql_cache, keywords, templates,
351};
352
353// Re-export optimized builder types
354pub use builder::{
355    BuilderPool,
356    ColumnList,
357    ColumnNameList,
358    CowColumnList,
359    CowIdentifier,
360    ExprList,
361    // Note: FrameBound and FrameType are also defined in window module
362    FrameBound as BuilderFrameBound,
363    FrameType as BuilderFrameType,
364    Identifier,
365    OptimizedWindowSpec,
366    OrderByList,
367    PartitionByList,
368    ReusableBuilder,
369    WindowFrame,
370};
371
372// Re-export database optimization types
373pub use db_optimize::{
374    BatchConfig, CachedStatement, IndexHint, IndexHintType, JoinHint, JoinMethod,
375    MongoPipelineBuilder, PipelineStage, PreparedStatementCache, PreparedStatementStats,
376    QueryHints, global_statement_cache,
377};
378
379// Re-export zero-copy types
380pub use zero_copy::{
381    CteRef, FrameBoundRef, FrameRef, FrameTypeRef, JsonPathRef, PathSegmentRef, WindowSpecRef,
382    WithClauseRef,
383};
384
385// Re-export cache types
386pub use cache::{
387    CacheStats, CachedQuery, ExecutionPlan, ExecutionPlanCache, PlanHint, QueryCache, QueryHash,
388    QueryKey, SqlTemplate, SqlTemplateCache, get_global_template, global_template_cache,
389    patterns as cache_patterns, precompute_query_hash, register_global_template,
390};
391
392// Re-export batch types
393pub use batch::{
394    Batch, BatchBuilder, BatchOperation, BatchResult, OperationResult, Pipeline, PipelineBuilder,
395    PipelineQuery, PipelineResult, QueryResult as PipelineQueryResult,
396};
397
398// Re-export row deserialization types
399pub use row::{FromColumn, FromRow, FromRowRef, RowData, RowError, RowRef, RowRefIter};
400
401// Re-export lazy loading types
402pub use lazy::{Lazy, LazyRelation, ManyToOneLoader, OneToManyLoader};
403
404// Re-export static filter utilities
405pub use static_filter::{
406    CompactValue, StaticFilter, and2, and3, and4, and5, contains, ends_with, eq,
407    fields as static_fields, gt, gte, in_list, is_not_null, is_null, lt, lte, ne, not, not_in_list,
408    or2, or3, or4, or5, starts_with,
409};
410
411// Re-export typed filter utilities
412pub use typed_filter::{
413    And, AndN, Contains, DirectSql, EndsWith, Eq, Gt, Gte, InI64, InI64Slice, InStr, InStrSlice,
414    IsNotNull, IsNull, LazyFilter, Lt, Lte, Maybe, Ne, Not as TypedNot, NotInI64Slice, Or, OrN,
415    StartsWith, TypedFilter, and_n, eq as typed_eq, gt as typed_gt, gte as typed_gte,
416    in_i64 as typed_in_i64, in_i64_slice, in_str as typed_in_str, in_str_slice,
417    is_not_null as typed_is_not_null, is_null as typed_is_null, lazy, lt as typed_lt,
418    lte as typed_lte, ne as typed_ne, not_in_i64_slice, or_n,
419};
420
421// Re-export memory optimization utilities
422pub use memory::{
423    BufferPool, CompactFilter, GLOBAL_BUFFER_POOL, GLOBAL_STRING_POOL, MemoryStats, PoolStats,
424    PooledBuffer, StringPool, get_buffer, intern as memory_intern,
425};
426
427// Re-export logging utilities
428pub use logging::{
429    get_log_format, get_log_level, init as init_logging, init_debug, init_with_level,
430    is_debug_enabled,
431};
432
433// Re-export replication types
434pub use replication::{
435    ConnectionRouter, HealthStatus, LagMeasurement, LagMonitor, ReadPreference, ReplicaConfig,
436    ReplicaHealth, ReplicaRole, ReplicaSetBuilder, ReplicaSetConfig,
437};
438
439// Re-export async optimization types
440pub use async_optimize::{
441    ConcurrencyConfig, ConcurrentExecutor, ExecutionStats, IntrospectionConfig,
442    IntrospectionResult, PipelineConfig, PipelineError, PipelineResult as AsyncPipelineResult,
443    QueryPipeline, TaskError, TaskResult,
444    concurrent::execute_batch as async_execute_batch,
445    concurrent::execute_chunked as async_execute_chunked,
446    introspect::{
447        BatchIntrospector, ColumnMetadata, ConcurrentIntrospector, ForeignKeyMetadata,
448        IndexMetadata, IntrospectionError, IntrospectionPhase, IntrospectorBuilder, TableMetadata,
449    },
450    pipeline::{BulkInsertPipeline, BulkUpdatePipeline, SimulatedExecutor},
451};
452
453// Re-export memory optimization types
454pub use mem_optimize::{
455    GlobalInterner, IdentifierCache, InternedStr, ScopedInterner,
456    arena::{ArenaScope, ArenaStats, QueryArena, ScopedFilter, ScopedQuery, ScopedValue},
457    interning::{get_interned, intern as global_intern, intern_component, intern_qualified},
458    lazy::{LazyColumn, LazyForeignKey, LazyIndex, LazySchema, LazySchemaStats, LazyTable},
459};
460
461// Re-export profiling types
462pub use profiling::{
463    AllocationRecord, AllocationStats, AllocationTracker, HeapProfiler, HeapReport, HeapStats,
464    LeakDetector, LeakReport, LeakSeverity, MemoryProfiler, MemoryReport, MemorySnapshot,
465    PotentialLeak, SnapshotDiff, TrackedAllocator, disable_profiling, enable_profiling,
466    is_profiling_enabled, with_profiling,
467};
468
469// Re-export smallvec for macros
470pub use smallvec;
471
472/// Prelude module for convenient imports.
473pub mod prelude {
474    pub use crate::advanced::{LateralJoin, Returning, RowLock, TableSample};
475    pub use crate::cte::{Cte, CteBuilder, WithClause};
476    pub use crate::error::{QueryError, QueryResult};
477    pub use crate::extension::{Extension, Point, Polygon};
478    pub use crate::filter::{Filter, FilterValue, ScalarFilter};
479    pub use crate::introspection::{DatabaseSchema, TableInfo, generate_prax_schema};
480    pub use crate::json::{JsonFilter, JsonOp, JsonPath};
481    pub use crate::nested::{
482        NestedWrite, NestedWriteBuilder, NestedWriteOp, NestedWriteOperations,
483    };
484    pub use crate::operations::*;
485    pub use crate::pagination::{Cursor, CursorDirection, Pagination};
486    pub use crate::partition::{Partition, PartitionBuilder, PartitionType, RangeBound};
487    pub use crate::procedure::{
488        Parameter, ParameterMode, ProcedureCall, ProcedureEngine, ProcedureResult,
489    };
490    pub use crate::query::QueryBuilder;
491    pub use crate::raw::{RawExecuteOperation, RawQueryOperation, Sql};
492    pub use crate::raw_query;
493    pub use crate::relations::{Include, IncludeSpec, RelationSpec, SelectSpec};
494    pub use crate::replication::{ConnectionRouter, ReadPreference, ReplicaSetConfig};
495    pub use crate::search::{FullTextIndex, SearchMode, SearchQuery, SearchQueryBuilder};
496    pub use crate::security::{Grant, GrantBuilder, RlsPolicy, Role, RoleBuilder};
497    pub use crate::sequence::{Sequence, SequenceBuilder};
498    pub use crate::traits::{
499        Executable, IntoFilter, MaterializedView, Model, QueryEngine, View, ViewQueryEngine,
500    };
501    pub use crate::transaction::{IsolationLevel, Transaction, TransactionConfig};
502    pub use crate::trigger::{
503        Trigger, TriggerAction, TriggerBuilder, TriggerCondition, TriggerEvent, TriggerLevel,
504        TriggerTiming,
505    };
506    pub use crate::types::{OrderBy, Select, SortOrder};
507    pub use crate::upsert::{ConflictAction, ConflictTarget, Upsert, UpsertBuilder};
508    pub use crate::window::{WindowFn, WindowFunction, WindowSpec};
509
510    // Tenant types
511    pub use crate::tenant::{IsolationStrategy, TenantConfig, TenantContext, TenantMiddleware};
512
513    // Async optimization types
514    pub use crate::async_optimize::{
515        ConcurrencyConfig, ConcurrentExecutor, IntrospectionConfig, PipelineConfig, QueryPipeline,
516    };
517
518    // Memory optimization types
519    pub use crate::mem_optimize::{GlobalInterner, InternedStr, LazySchema, QueryArena};
520
521    // Profiling types
522    pub use crate::profiling::{
523        LeakDetector, MemoryProfiler, MemorySnapshot, enable_profiling, with_profiling,
524    };
525}