Skip to main content

RawQuery

Struct RawQuery 

Source
pub struct RawQuery<D> { /* private fields */ }
Expand description

A whole statement, written by hand.

The builder’s counterpart to raw: that one is a fragment an expression accepts, this one is a statement nothing built it. It is an ordinary Query, so the execution layer’s verbs apply unchanged — fetch_all::<T>() maps hand-written SQL onto a struct exactly as it maps a built statement — and it is an Expression, so it nests as a sub-select in a built statement like any other query.

Construct one from the dialect it is written in: psql::raw_query(…), mysql::raw_query(…), sqlite::raw_query(…) — or, when the SQL is a literal, through that dialect’s sql! (feature macros), which writes the values at the holes they bind to and is the form to reach for first. This one is what sql! expands to, and what SQL arriving at run time — from a file, a migration runner — has to use, since a macro can only read a literal.

Placeholders are ?, on every dialect, and are rewritten into that dialect’s own syntax as the statement renders — $1 on PostgreSQL, ?1 on SQLite, ? on MySQL. Write \? for a literal question mark. The rule is template’s, for the same reason: a hand-written statement should not have to be respelled to move between engines, and a value still never reaches the SQL text. A ? count that disagrees with the bound arguments is an error from build, not a silently misbound statement.

keelson does not parse what you hand it. Everything the builder guarantees — that the SQL is grammatical for the engine, that identifiers are quoted — is yours here; what you keep is the binding, the placeholder rewriting, the row mapping, the transaction, and the tracing span.

§Why this is untyped, and stays untyped

The row type is whatever you name in fetch_all::<T>(), and nothing checks it against the schema. That is the escape hatch’s job description, not a gap waiting to be filled.

The rejected alternative: a proc macro that types the row and the parameters at the call site, by running keelson-gen’s own inference against a committed schema snapshot at compile time. It would work — the analysis is already a library, and the snapshot would need no database at build time, which is more than sqlx’s query! manages. It was rejected because it adds no guarantee keelson does not already offer: the same analysis, against the same schema, producing the same types, is Layer 4 (keelson-gen’s .sql files). The only difference is where the SQL lives. Paying a build-time SQL parser (libpg_query, in C, for PostgreSQL), a new artifact to keep fresh, and a second answer to “typed hand-written SQL” buys locality and nothing else.

So the line is: typed SQL goes in a .sql file (Layer 4) or comes from a generated model (Layer 3), and both are typed because they were derived from the schema. Untyped SQL is this, and its counterpart for fragments. Wanting the compiler to reject a malformed query outright is a real want, and diesel is the library that serves it.

Implementations§

Source§

impl<D> RawQuery<D>

Source

pub fn new(dialect: D, sql: impl Into<Cow<'static, str>>) -> Self

The statement, in dialect’s SQL. Dialect crates wrap this as raw_query, which is how a caller should reach it.

Source

pub fn bind(self, value: impl ToValue) -> Self

Bind a value to the next ?.

Source

pub fn bind_all<V: ToValue>(self, values: impl IntoIterator<Item = V>) -> Self

Bind every value in values, in order — one ? each.

Source

pub fn bind_expr(self, expression: impl IntoExpr) -> Self

Splice an expression into the next ? instead of binding a value.

This is what makes WHERE id IN (?) work: the expression consumes as many placeholder positions as it binds arguments, and the counter keeps going from there. A quoted identifier, a sub-query and a built statement all go in this way.

Source

pub fn kind(self, query_type: QueryType) -> Self

Declare which statement this is.

It feeds the tracing span and nothing else — the execution layer never polices it against the SQL. The default is QueryType::Unknown, which is the honest answer for text keelson has not read: guessing from the leading keyword would be wrong for WITH … INSERT, and keelson does not guess.

Trait Implementations§

Source§

impl<D: Clone> Clone for RawQuery<D>

Source§

fn clone(&self) -> RawQuery<D>

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<D: Debug> Debug for RawQuery<D>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<D: Debug + Send + Sync> Expression for RawQuery<D>

Source§

fn write_sql(&self, w: &mut SqlWriter<'_>)

Append this fragment to w. Read more
Source§

impl<D: Dialect> Query for RawQuery<D>

Source§

fn query_type(&self) -> QueryType

Which statement this renders.
Source§

fn dialect(&self) -> &dyn Dialect

The dialect this query renders itself in. Read more
Source§

fn build(&self) -> Result<(String, Vec<Value>)>

Render to SQL and arguments, numbering placeholders from 1. Read more
Source§

fn build_from(&self, start: usize) -> Result<(String, Vec<Value>)>

build with a different first placeholder position, for splicing into a statement that already has arguments — bob’s BuildN.
Source§

impl<D: Dialect, H, L, M> QueryExtensions<H, L, M> for RawQuery<D>

Source§

fn hooks(&self) -> &[Hook]

Hooks to run before this query executes.
Source§

fn loaders(&self) -> &[Loader]

Loaders to run after this query executes, for eagerly loaded relations.
Source§

fn mapper_mods(&self) -> &[MapperMod]

Adjustments to the row mapper, for relations loaded in the same query.

Auto Trait Implementations§

§

impl<D> !RefUnwindSafe for RawQuery<D>

§

impl<D> !UnwindSafe for RawQuery<D>

§

impl<D> Freeze for RawQuery<D>
where D: Freeze,

§

impl<D> Send for RawQuery<D>
where D: Send,

§

impl<D> Sync for RawQuery<D>
where D: Sync,

§

impl<D> Unpin for RawQuery<D>
where D: Unpin,

§

impl<D> UnsafeUnpin for RawQuery<D>
where D: UnsafeUnpin,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.