pub mod aggregate;
pub mod choices;
pub mod column;
pub mod dynamic;
pub mod expr;
pub mod file_field;
pub mod foreign_key;
pub mod forms_runtime;
pub mod m2m;
pub mod masked;
pub mod model;
pub mod multichoice;
pub mod one_to_one;
pub mod post;
pub mod queryset;
pub mod reverse_accessor;
pub mod reverse_set;
pub mod search;
pub mod tsvector;
pub mod validation;
pub mod validators;
pub mod write;
use std::marker::PhantomData;
use std::ops::{BitAnd, BitOr};
pub use aggregate::{Aggregate, AggregateKind};
pub fn pk_key(value: &serde_json::Value) -> String {
match value {
serde_json::Value::Number(n) => format!("n:{n}"),
serde_json::Value::String(s) => format!("s:{s}"),
other => format!("o:{other}"),
}
}
pub fn escape_like_literal(s: &str) -> String {
let mut out = String::with_capacity(s.len());
for ch in s.chars() {
if matches!(ch, '\\' | '%' | '_') {
out.push('\\');
}
out.push(ch);
}
out
}
pub struct Subquery {
inner: sea_query::SelectStatement,
}
impl Subquery {
pub(crate) fn from_select(inner: sea_query::SelectStatement) -> Self {
Self { inner }
}
pub(crate) fn into_statement(self) -> sea_query::SelectStatement {
self.inner
}
}
pub use choices::ChoiceField;
pub use dynamic::{CsvImportReport, DynError, DynQuerySet, decode_to_string, import_table_rows};
pub use expr::{F, FColExt, FExpr, Q};
pub use file_field::{FileField, ImageField};
pub use foreign_key::ForeignKey;
pub use m2m::{M2M, load_junction_selection, set_junction_dynamic};
pub use masked::{MaskError, MaskKeyring, Masked, set_mask_keyring};
pub use model::{
ArrayElement, FieldSpec, FkAction, HydrateRelated, M2MRelationSpec, Model,
OneToOneRelationSpec, PrimaryKey, ReverseFkRelationSpec, SqlType,
};
pub use multichoice::MultiChoice;
pub use one_to_one::OneToOne;
pub use post::Post;
pub use queryset::{GetError, JoinKind, Manager, QuerySet, QuerySetTx, TryForEachError};
pub use reverse_accessor::{ReverseError, ReverseRelations};
pub use reverse_set::ReverseSet;
pub use search::{Search, SearchHit, SearchSources, Searchable};
pub use tsvector::TsVector;
pub use validators::{Email, Slug, Url, ValidatorError, validate_text_format};
pub use write::{SaveError, slugify};
pub struct Predicate<T> {
pub(crate) cond: sea_query::SimpleExpr,
pub(crate) cond_sqlite: Option<sea_query::SimpleExpr>,
_phantom: PhantomData<T>,
}
impl<T> Predicate<T> {
pub fn col_eq(col: &'static str, value: impl Into<sea_query::Value>) -> Self {
let expr = sea_query::Expr::col(sea_query::Alias::new(col)).eq(value);
Self::new(expr)
}
pub(crate) fn new(cond: sea_query::SimpleExpr) -> Self {
Self {
cond,
cond_sqlite: None,
_phantom: PhantomData,
}
}
pub(crate) fn new_with_sqlite(
cond: sea_query::SimpleExpr,
cond_sqlite: sea_query::SimpleExpr,
) -> Self {
Self {
cond,
cond_sqlite: Some(cond_sqlite),
_phantom: PhantomData,
}
}
pub(crate) fn cond_for(&self, backend_name: &str) -> sea_query::SimpleExpr {
match backend_name {
"sqlite" => self
.cond_sqlite
.clone()
.unwrap_or_else(|| self.cond.clone()),
_ => self.cond.clone(),
}
}
}
impl<T> Clone for Predicate<T> {
fn clone(&self) -> Self {
Self {
cond: self.cond.clone(),
cond_sqlite: self.cond_sqlite.clone(),
_phantom: PhantomData,
}
}
}
impl<T> BitAnd for Predicate<T> {
type Output = Predicate<T>;
fn bitand(self, rhs: Predicate<T>) -> Predicate<T> {
let any_sqlite_override = self.cond_sqlite.is_some() || rhs.cond_sqlite.is_some();
let combined_sqlite = if any_sqlite_override {
let lhs_sql = self
.cond_sqlite
.clone()
.unwrap_or_else(|| self.cond.clone());
let rhs_sql = rhs.cond_sqlite.clone().unwrap_or_else(|| rhs.cond.clone());
Some(lhs_sql.and(rhs_sql))
} else {
None
};
Predicate {
cond: self.cond.and(rhs.cond),
cond_sqlite: combined_sqlite,
_phantom: PhantomData,
}
}
}
impl<T> BitOr for Predicate<T> {
type Output = Predicate<T>;
fn bitor(self, rhs: Predicate<T>) -> Predicate<T> {
let any_sqlite_override = self.cond_sqlite.is_some() || rhs.cond_sqlite.is_some();
let combined_sqlite = if any_sqlite_override {
let lhs_sql = self
.cond_sqlite
.clone()
.unwrap_or_else(|| self.cond.clone());
let rhs_sql = rhs.cond_sqlite.clone().unwrap_or_else(|| rhs.cond.clone());
Some(lhs_sql.or(rhs_sql))
} else {
None
};
Predicate {
cond: self.cond.or(rhs.cond),
cond_sqlite: combined_sqlite,
_phantom: PhantomData,
}
}
}
pub struct OrderExpr<T> {
pub(crate) column: &'static str,
pub(crate) descending: bool,
_phantom: PhantomData<T>,
}
impl<T> OrderExpr<T> {
pub(crate) fn new(column: &'static str, descending: bool) -> Self {
Self {
column,
descending,
_phantom: PhantomData,
}
}
}