Skip to content

Custom queries

Sometimes the ORM is not enough and you need to write a complex query by hand. Rwf provides an easy way to execute arbitrary queries and map the results to a model struct:

let users = User::find_by_sql(
    "SELECT * FROM users ORDER BY RANDOM() LIMIT 1",
    &[]
)
  .fetch_all(&mut conn)
  .await?;

Note

Since this query is not generated by the ORM, you need to make sure to return all the necessary columns and correct data types to map the results to the Rust struct.

Passing parameters

Custom queries accept parameters just like any other ORM query. Postgres uses the dollar notation ($1) for value placeholders, for example:

let users = User::find_by_sql(
    "SELECT * FROM users
    WHERE id BETWEEN $1 AND $2
    ORDER BY RANDOM()",
    &[25, 50],
).fetch_all(&mut conn)
.await?;

Make sure the parameter values are passed in the same order as the placeholders in the query.

Use the database driver directly

If you want to bypass the ORM entirely and just execute queries, you can do so by checking out a connection and calling the query_cached method on it:

let mut conn = Pool::connection().await?;

let results = conn
    .query_cached("SELECT * FROM wherever WHERE column = $1", &[5])
    .await?;

Rwf uses tokio_postgres underneath to talk to Postgres, so you'll receive a Vec<tokio_postgres::Row> as a result of executing that function.

Since tokio_postgres uses prepared statements, query_cached ensures that identical queries are not prepared more than once per connection. If you want to bypass that and use tokio_postgres directly, you can use client() instead:

let mut conn = Pool::connection().await?;

// Returns a `tokio_postgres::Client`
let client = conn.client();

client
    .execute("SELECT 1", &[])
    .await?;