Skip to content

v0.1.0

Choose a tag to compare

@trantruong-dev trantruong-dev released this 08 Sep 04:03
· 25 commits to main since this release

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, because i64 is not an expression of type String.
  • Table scope. User::query().filter(Department::name.eq("AI")) does not compile, because the query never joined Department.

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, DISTINCT and DISTINCT 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 Err from to_sql rather 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.
  • LIKE operands are wildcard-escaped with an explicit ESCAPE '!', 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_DEPTH rather than overflowing the stack, and AND/OR chains 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 Value into 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/.