queryweave_sql/lib.rs
1//! The `queryweave` runtime for the persistence layer: the traits and SQL the
2//! code generated for entities and wrappers (`Columns`, `AppendToQuery`,
3//! `AppendToQueryWithSeparator`) names, on top of the core runtime
4//! (`queryweave`), which it re-exports so that code names only this crate.
5//!
6//! This is where the domain's database-agnostic filters, sorting and writes
7//! (`queryweave::FilterCondition`, `queryweave::SortKey`,
8//! `queryweave::FieldValue`) become SQL. They name domain fields; the
9//! [`Columns`] of the entity storing them say which column each lives in, and
10//! write the SQL against them.
11//!
12//! The SQL is portable across the databases sqlx supports: Postgres,
13//! MySQL/MariaDB and SQLite (any [`BindValues`] database). What stays
14//! database-specific is semantics, not syntax: `LIKE` is case-sensitive on
15//! Postgres but case-insensitive on SQLite (for ASCII) and under MySQL's
16//! default collations, and column names are written unquoted, so they must not
17//! be reserved words of the database.
18
19mod bind;
20mod columns;
21mod sql;
22
23pub use queryweave::*;
24
25pub use bind::BindValues;
26pub use columns::{
27 Columns, Message, column_for, first_field_without_column, missing_column_message,
28};
29pub use sql::{push_page, sql_direction, sql_operator};
30
31/// The sqlx query builder the clauses are appended to, and the separated
32/// builder `Columns::push_assignments` returns: re-exported so the generated
33/// code (and its callers) name the same sqlx as this crate, whatever the user
34/// calls their own sqlx dependency.
35pub use sqlx::{QueryBuilder, query_builder::Separated};
36
37/// Not public API: what the code generated by `queryweave-derive`
38/// calls.
39///
40/// The inherent methods `#[derive(Columns)]` emits run the column check
41/// themselves (so a missing column is reported at *their* caller, the line
42/// writing the data, rather than inside the derive) and then call the
43/// unchecked writers here, so the check is not reported twice.
44#[doc(hidden)]
45pub mod __private {
46 pub use crate::columns::assert_model_columns;
47 #[cfg(feature = "merge-patch")]
48 pub use crate::sql::push_assignments;
49 pub use crate::sql::{push_conditions, push_order_by};
50 pub use queryweave::__private::*;
51}
52
53/// Append the filters query to the parent query.
54pub trait AppendToQuery {
55 /// Append the filters query to the parent query, for any [`BindValues`]
56 /// database.
57 fn append_to_query<DB, F>(
58 &self,
59 query_builder: &mut QueryBuilder<'_, DB>,
60 privileged_guard_option: Option<F>,
61 ) where
62 DB: BindValues,
63 F: FnOnce(&mut QueryBuilder<'_, DB>, &Self);
64}
65
66/// Append to query individual filters.
67pub trait AppendToQueryWithSeparator {
68 /// Append to query individual filters, for any [`BindValues`] database.
69 fn append_to_query<DB: BindValues>(
70 &self,
71 query_builder: &mut QueryBuilder<'_, DB>,
72 separator: &str,
73 );
74}