liveBook · Manning

FromRow

As explained in Rust Servers, Services, and Apps

FromRow is an SQLx trait for constructing a Rust value from a database query result row.

`sqlx::FromRow` is a trait used to turn a database result row into a Rust struct. In a course API, deriving it for `Course` supports reading database records as values that handlers can return to clients, without writing field-by-field mapping code. section 6.2.1 section 6.2.2

#[derive(Serialize, Debug, Clone, sqlx::FromRow)]
pub struct Course {
    pub course_id: i32,
    pub tutor_id: i32,
    pub course_name: String,
    pub course_description: Option<String>,
    pub course_format: Option<String>,
    pub course_structure: Option<String>,
    pub course_duration: Option<String>,
    pub course_price: Option<i32>,
    pub course_language: Option<String>,
    pub course_level: Option<String>,
    pub posted_time: Option<NaiveDateTime>,
}

The `Course` model derives `sqlx::FromRow` alongside `Serialize`, `Debug`, and `Clone`. Required identifiers and the course name use non-optional fields; fields that may lack database values use `Option<T>`. section 6.2.1

Keep the database record model distinct from request inputs. `Course` includes fields such as `course_id` and `posted_time` that the database can generate; `CreateCourse` carries the fields supplied when creating a course. `FromRow` applies when reading the resulting record into `Course`, not when deserializing the creation request. section 6.2.1

use crate::errors::EzyTutorError;
use crate::models::course::*;
use sqlx::postgres::PgPool;
 
 
pub async fn get_courses_for_tutor_db(
    pool: &PgPool,
    tutor_id: i32,
) -> Result<Vec<Course>, EzyTutorError> {
    // Prepare SQL statement
 
    let course_rows: Vec<Course> = sqlx::query_as!(    #1
        Course,
        "SELECT * FROM ezy_course_c6 where tutor_id = $1",
        tutor_id
    )
    .fetch_all(pool)                                   #2
    .await?;                                           #3
 
    Ok(course_rows)                                    #4
}

In `src/iter5/dbaccess/course.rs`, `sqlx::query_as!` names `Course` as the result type, runs a tutor-filtered `SELECT`, and uses `fetch_all` to return `Vec<Course>`. The derived mapping avoids assigning each selected column to a struct field by hand. section 6.2.2

The same result-mapping pattern appears across course operations:

  • Fetch one course with `fetch_optional`; return the `Course` when present or a not-found error when absent. section 6.2.2
  • Insert a course with PostgreSQL `RETURNING` to obtain the new record as a `Course` in the same query. section 6.2.2
  • Fetch the existing `Course` before an update so omitted optional update fields can retain their stored values. section 6.2.2

Automatic mapping is a convenience, not the only approach: database records can also be mapped to Rust structs manually when `query_as!` is unsuitable. The treatment uses the derive in application code rather than implementing the trait by hand. section 6.4 section 6.2.2

How Rust Servers, Services, and Apps covers it

How deep it goes
Shows a derive and its use with `query_as!`, while leaving trait internals and a handwritten `FromRow` implementation unexplored.
Examples
Uses a `Course` struct and tutor-filtered `SELECT`, single-course lookup, and `INSERT ... RETURNING` queries.
What it assumes
Assumes familiarity with Rust structs and database queries; introduces the derive through an existing course model rather than teaching traits from zero.
What you can do after
Apply it via SQLx to derive row mapping for `Course` and return typed results from course database functions.
How it connects
Connects SQLx `query_as!`, Rust structs, PostgreSQL queries, and optional database fields.

Also explained in

Compare how 2 books explain FromRow →

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.