sql_query_builder

A composable SQL query builder for Rust that lets you build dynamic SELECT, INSERT, UPDATE, and DELETE queries with idiomatic, chainable methods.

Library
Cargo
v2.7.2
72stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
45/100Fair
Development Activity32
Maintenance36
Community36
Maturity56
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
75/100Good
Architecture78
Code Quality74
Innovation82
Learning Curve65

sql_query_builder is a Rust crate for constructing SQL queries programmatically through a fluent, chainable API modeled closely on SQL syntax itself. Instead of hand-concatenating strings or reaching for a full ORM, it lets you assemble SELECT, INSERT, UPDATE, DELETE, CREATE TABLE, ALTER TABLE, and transaction statements one clause at a time, conditionally adding pieces based on runtime logic while the builder handles ordering and deduplication.

The crate is dialect-aware through opt-in Cargo features (postgresql, sqlite, mysql) that unlock database-specific clauses like LIMIT/OFFSET, WITH, UNION/INTERSECT/EXCEPT, and MySQL’s PARTITION, while a standard core works across all three. It intentionally does not validate or interpret the SQL you pass in, favoring composability and predictable output over guardrails, and ships a debug() method for inspecting the query state mid-build.

What You Get

  • Builders for Select, Insert, Update, Delete, CreateTable, AlterTable, DropTable, and Transaction statements, all following the same chainable pattern.
  • Optional postgresql, sqlite, and mysql Cargo features that add dialect-specific clauses (LIMIT/OFFSET, WITH, UNION/INTERSECT/EXCEPT, PARTITION, CreateIndex/DropIndex) without bloating the default build.
  • Composition helpers (raw(), raw_before(), raw_after()) for dropping in hand-written SQL fragments at any point in a generated query for edge cases the builder API doesn’t cover.
  • A debug() method that prints the current state of a query mid-construction, useful for tracing complex conditional query assembly.
  • Order-independent, deduplicating clause accumulation — calling the same clause method multiple times appends values rather than producing duplicate or conflicting SQL.

Common Use Cases

  • Building dynamic search/filter endpoints where WHERE clauses are added conditionally based on which query parameters a caller supplied.
  • Composing complex multi-join, multi-CTE reporting queries from small, independently testable builder functions.
  • Writing lightweight data-access code without pulling in a full ORM’s schema/migration machinery.
  • Generating transaction scripts (BEGIN/SAVEPOINT/COMMIT/ROLLBACK) alongside the statements they wrap.

Under The Hood

Architecture The crate is organized as a set of per-command modules (select, insert, update, delete, alter_table, create_table, drop_table, create_index, drop_index, transaction, values) each following an identical three-file pattern: a <command>.rs with the public chainable builder methods, a <command>_internal.rs with private concat/format plumbing, and a mod.rs re-export point — with the shared structure.rs defining the plain-data structs (Select, Insert, Update, Delete, etc.) that every module operates on via impl blocks scattered across files rather than one large struct-and-methods file. Cross-cutting behavior is expressed through traits in behavior.rs (TransactionQuery, WithQuery) marking which builder types are legal inside a transaction or a WITH clause, and concat/ holds one file per SQL dialect implementing a shared Concat trait that each builder delegates to for final string assembly — so adding a new SQL dialect means adding one concat implementation, not touching every builder. Data flow is a straightforward builder-pattern accumulation: each chained method pushes into a private field via push_unique() and returns self by value; only as_string()/debug()/Display trigger the actual concatenation via fmt.rs. If the core Concat trait or the structure.rs field layout changed, every command module and every dialect’s concat implementation would need to change in lockstep, since they’re the two seams every builder passes through.

Tech Stack sql_query_builder is a zero-runtime-dependency Rust crate (edition 2021, MSRV 1.62) — the only dependency declared in Cargo.toml is a dev-dependency used for test-output diffing. It has no database driver, no async runtime, and no ORM layer underneath it; it purely emits SQL strings, leaving execution to whatever driver the consumer already uses. Three additive Cargo features (postgresql, sqlite, mysql) gate dialect-specific clauses at compile time, and the docs.rs build metadata enables all three for complete API docs. CI runs the test suite four times against the crate’s minimum-supported Rust version — once for the standard core and once per dialect feature — with no additional linting, formatting, or coverage gate wired into CI, though local scripts exist for coverage and formatting.

Code Quality Tests live almost entirely as an external integration suite of dozens of spec files, one per clause or command, supplemented by extensive runnable doctest examples embedded directly in the public API’s doc comments across nearly every method, giving the crate genuinely thorough test coverage for its surface area. Error handling is essentially absent by design — the builder API takes plain strings and never validates or parses SQL, so there are no Result types or panics to reason about in the public surface, a deliberate, documented tradeoff rather than an oversight. Naming is consistent and SQL-idiomatic, private fields are prefixed to separate builder state from public methods, and the crate ships a formatting config though CI does not enforce a format or lint check.

API Design The public API is highly ergonomic: every builder method takes a plain string and returns an owned instance, so getting started requires no setup beyond creating a new builder — no config structs, no connection objects — and method names mirror SQL syntax almost one-to-one, keeping the learning curve close to “if you know SQL, you know this API.” Naming is consistent throughout, and documentation quality is exceptional — nearly every public method carries a doc comment with a runnable example and its literal SQL output shown inline, which also means the doctest suite exercises the majority of the README-level API surface as living documentation. The main ergonomic cost is the escape-hatch API, which requires importing and matching a per-builder clause enum, and the fact that feature-gated methods simply don’t exist unless the right Cargo feature is enabled, which can surprise a newcomer with a confusing compiler error rather than a clear feature hint.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search