SQLx built its reputation on a strong idea: SQL queries checked at compile time, against a real database, before the program even runs. That is precisely the feature QoreDB does not use. A database client runs the SQL you type, against a schema it discovers at connection time — there is nothing to verify at build time. So QoreDB leans on SQLx for its other strengths: an asynchronous connection pool and typed decoding of results. The rest, it handles at runtime.
Why no compile-time queries
SQLx's query! and query_as! macros are its headline feature: they query a reference database at compile time to validate the syntax and infer the return types. That assumes two things QoreDB never has: a schema known in advance, and a database reachable during the build. Here, the query belongs to the user and the schema belongs to the database they just opened. You will therefore find none of these macros in the driver code — not by oversight, but because they would make no sense on arbitrary SQL.
What QoreDB keeps from SQLx: the pool
Where SQLx is irreplaceable is connection management. Every relational engine SQLx covers — PostgreSQL, MySQL/MariaDB, SQLite — relies on its typed pool (PgPool, MySqlPool, SqlitePool), built through the matching PoolOptions. QoreDB exposes the settings that matter: minimum and maximum connection bounds, and an acquire timeout. It is all asynchronous, sitting on tokio (runtime-tokio, tls-rustls), so that a long-running query never freezes the interface.
Queries at runtime, not at compile time
When you run a query, your SQL is passed as-is to sqlx::query(query). QoreDB simply decides whether to fetch rows or execute without a result set, based on a safety-side prefix check (returns_rows / is_select_prefix). Before running anything, it applies the namespace on the connection — a search_path, for instance — so the query executes in the right schema. No rewriting, no translation: SQLx acts as transport, not interpreter.
The queries QoreDB generates itself, on the other hand — schema introspection, metadata — are parameterized with .bind(), which keeps them clear of any injection. The distinction is sharp: the user's SQL passes untouched, the tool's SQL is always bound by parameters.
Typed decoding, the real value
A raw result, on the wire, is just a sequence of bytes. SQLx can turn them into usable Rust types, and for that QoreDB enables the decoders that matter: chrono for dates, rust_decimal and bigdecimal for exact numbers, uuid for identifiers. That is what makes it possible to display a date or a decimal correctly rather than as an approximate string, consistently from one engine to the next.
A pool, and therefore cancellation
Because the pool handles real server connections, QoreDB can do more than open and close them. For each query, it captures the server-side process identifier (the backend PID on PostgreSQL) and keeps it for the duration of the execution. If you cancel, it opens a second connection and asks the engine to interrupt the first. This capability follows directly from the choice of an asynchronous pool: without it, a query once launched would be a query you can no longer stop.
QoreDB's relationship with SQLx is telling of how it picks its dependencies. It takes what holds up under a generic client — a solid pool, reliable typed decoding — and sets aside the compile-time part, not out of distrust, but because the query is not its own to validate. It is the same logic as everywhere else: not promising a guarantee it cannot actually keep.
Stay updated on new releases
Subscribe to get product releases, new drivers notifications, and technical tutorials.

