Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FromSql a whole row into a struct #978

Closed
tv42 opened this issue Jan 5, 2023 · 1 comment
Closed

FromSql a whole row into a struct #978

tv42 opened this issue Jan 5, 2023 · 1 comment

Comments

@tv42
Copy link

tv42 commented Jan 5, 2023

Hi. I'd like to fetch rows directly into a struct, without going field by field and doing let field1: MyType = row.get(0) etc. Something like let person: Person = row.get_struct(), which can reuse the composite type logic to parse into a struct deriving FromSql.

You can currently hack around this with the following trick. Here, I'm using the fact that Postgres already defines a composite type for every table; for this trick to work with other than SELECT *, you'd need to define a PG composite type for each query too.

#[derive(Debug, ToSql, FromSql)]
#[postgres(name = "person")]
struct Person {
    id: i64,
    name: String,
    data: Option<Vec<u8>>,
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut client = postgres::Client::connect(
        "host=localhost user=postgres",
        postgres::NoTls,
    )?;

    client.batch_execute(
        "
        CREATE TABLE IF NOT EXISTS person (
            id      BIGSERIAL PRIMARY KEY,
            name    TEXT NOT NULL,
            data    BYTEA
        )
    ",
    )?;

    {
        let name = "Ferris";
        client.execute(
            "INSERT INTO person (name) VALUES ($1)",
            &[&name],
        )?;
    }

    for row in client.query(
        // Jump through hoops to make postgres-types work well.
        "SELECT row(person.*)::person FROM person",
        &[],
    )? {
        let person: Person = row.get(0);
        println!("found person: {:?}", person);
    }

It'd be nice to avoid that extra row(...)::person trickery, and to not need to define Postgres-side composite types for every possible combination of selected columns. postgres-types should be able to enumerate the columns and match each one to a struct field, just like it does with composite types (without needing a composite type).

@sfackler
Copy link
Owner

sfackler commented Jan 6, 2023

As you noted, the composite type can be used in some cases.

Building logic to deserialize an entire row into a Rust struct is something that I think would be best developed in a separate project.

@sfackler sfackler closed this as completed Feb 7, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants