liveBook · Manning

SQLx

As explained in Rust Servers, Services, and Apps

SQLx is a Rust library for asynchronous, compile-time checked interaction with SQL databases.

SQLx is a Rust crate for asynchronous database access. In an Actix Web service backed by Postgres, it keeps database calls asynchronous alongside request handling. It accepts raw SQL, checks queries at compile time, and provides a connection pool. section 4.2.1 section 1.3.1

A practical path from database setup to a working API is:

  • Add SQLx to Cargo.toml with the postgres, runtime-tokio-native-tls, macros, and chrono features. Create the Postgres database, credentials, and course table; set DATABASE_URL. section 4.2.2
  • In a standalone Rust program, connect with PgPool::connect(&database_url).await, run a query, and print the result. This isolates connectivity problems before adding the web server. section 4.2.2
  • In the Actix service, create the pool in main(), inject it into application state, and pass it from handlers to database access functions. section 4.5

Query courses for a tutor

In src/iter3/db_access.rs, construct a parameterized query with sqlx::query!("SELECT tutor_id, course_id, course_name, posted_time FROM ezy_course_c4 WHERE tutor_id = $1", tutor_id). Call fetch_all(pool).await, then map the returned rows into Course structs. Use fetch_one(pool).await for a single course; an INSERT ... RETURNING query likewise retrieves the newly posted course. The table supplies posted_time through its default rather than through the insert arguments. section 4.4.1

Listing 4.6 Database access code for retrieving all courses for a tutor
use super::models::Course;
use sqlx::postgres::PgPool;
 
pub async fn get_courses_for_tutor_db(pool: &PgPool, tutor_id: i32) ->
Vec<Course> {
   // Prepare SQL statement
   let course_rows = sqlx::query!(                       #1
       "SELECT tutor_id, course_id, course_name, posted_time FROM
       ezy_course_c4 where tutor_id = $1",
       tutor_id
   )
   .fetch_all(pool)                                      #2
   .await
   .unwrap();
   // Extract result
   course_rows                                           #3
       .iter()
       .map(|course_row| Course {
           course_id: course_row.course_id,
           tutor_id: course_row.tutor_id,
           course_name: course_row.course_name.clone(),
           posted_time: Some(chrono::NaiveDateTime::from(
           course_row.posted_time.unwrap())),
       })
       .collect()
}

The tutor-course access function shows the query! macro, parameter binding, pooled asynchronous fetch, and conversion of database rows into Course values together. section 4.4.1

How Rust Servers, Services, and Apps covers it

How deep it goes
Works through dependency and database setup, a standalone connection test, pool integration, queries, row conversion, and tests.
Examples
Uses a course table and tutor-course APIs to demonstrate fetch_all, fetch_one, and INSERT ... RETURNING.
What it assumes
Starts database setup from installation and credentials, then tests SQLx in a standalone Rust program before Actix integration.
What you can do after
Build it from scratch: configure a Postgres connection, then implement pooled asynchronous database access for course APIs.
How it connects
Links SQL queries and connection pooling to Actix Web application state, handlers, Postgres, and Rust structs.

Also explained in

Compare how 2 books explain SQLx →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Rust Servers, Services, and Apps. The section links point to the parts of the book it draws on.