Repository navigation
v0.1.0
OxideR-Query v0.1.0
First release. A type-safe, multi-dialect SQL query builder for Rust, inspired by Java's QueryDSL but pushing the type-checking further than a JVM can.
Read this first
The builder targets PostgreSQL, MySQL and SQLite. The optional execution layer and schema codegen support SQLite only.
On PostgreSQL and MySQL you build and render here, then bind the (sql, params) pair with your own driver. You do not get the Db handle yet. If that is a blocker, wait for a later release.
Pre-1.0: the API tracks latest stable Rust and will change.
What the compiler checks
Two things QueryDSL cannot check on the JVM:
- Operand types.
User::name.eq(123)does not compile, becausei64is not an expression of typeString. - Table scope.
User::query().filter(Department::name.eq("AI"))does not compile, because the query never joinedDepartment.
Correlated subqueries track the outer entities they are free in separately from their own scope, so using one where the outer table is absent is also a compile error.
Every advertised guarantee is pinned by a compile_fail doc test. Chapter 14 of the guide is equally explicit about what is not checked: nullability stays out of the type, col and raw are unchecked by design, and SQL's own rules (GROUP BY completeness, aggregates in WHERE) are left to the database.
What is in it
- SELECT, complete: projection, every join kind, aliasing, derived tables,
DISTINCTandDISTINCT ON, null ordering (native or emulated), pagination, row locking with wait policies, set operations, CTEs including recursive ones, window functions with frames, correlated and scalar subqueries. - DML, complete: multi-row insert, insert-select, upsert,
RETURNING,UPDATE ... FROM,DELETE ... USING. - Roughly 200 operators rendered for all three dialects from a template table, with parenthesisation decided once from a central precedence ladder.
- Dialect refusals. A construct the engine cannot run is an
Errfromto_sqlrather than plausible-but-wrong SQL that fails at the database. - Execution over sqlx, and codegen from an existing schema. SQLite only, as above.
Security posture
The crate went through a security, transaction and memory audit before this release, and everything it found is fixed. The trust boundary is now written down in chapter 16 of the guide. In short:
- Values always bind. A payload in a filter reaches the engine as a parameter, never as SQL text.
- Identifiers are
&'static str, so a string an application assembled at runtime does not compile in an identifier position. LIKEoperands are wildcard-escaped with an explicitESCAPE '!', unconditionally, not only for constants.- Codegen escapes every database name written into generated Rust and binds the table name into its introspection query, so a hostile schema is a naming problem rather than a code-execution one.
- Deep expression trees are refused at
MAX_DEPTHrather than overflowing the stack, andAND/ORchains flatten so ordinary dynamic filters never approach the limit.
#![forbid(unsafe_code)] on every crate. No unsafe, no Box::leak, no reference cycle, no global mutable state.
Install
Not on crates.io yet, so depend on the Git repository:
[dependencies]
oxider-query = { git = "https://github.com/OxideR-System/OxideR-Query", tag = "v0.1.0" }
# Optional: async execution over sqlx (SQLite today)
oxider-query-exec = { git = "https://github.com/OxideR-System/OxideR-Query", tag = "v0.1.0" }
# Optional: generate entities from an existing schema (SQLite today)
oxider-query-codegen = { git = "https://github.com/OxideR-System/OxideR-Query", tag = "v0.1.0" }Known gaps
- PostgreSQL and MySQL execution and codegen backends.
#[derive(Projection)].- A GroupBy transformer.
- The renderer clones each
Valueinto the parameter list; removing it needs the render entry points to consume the AST rather than borrow it. - A tree thousands of subqueries deep can still overflow when dropped. Rendering it is refused either way.
Documentation
The guide is sixteen chapters, in Vietnamese, in docs/, and is also published as a Docusaurus site under website/.