How to implement tokio_postgres::types::ToSql for enum type (rust, postgres)

447 Views Asked by At

I need to implement the tokio_postgres::types::ToSql for an enum type (rust and db as enum implemented) and I had no idea how to ...

Example

enum Flag {MyFlag1, MyFlag2, MyFlag3};
// on postgres db :
//    CREATE TYPE flag AS ENUM ('my_flag_1', 'my_flag_2', 'my_flag_3');

impl ToSql for Flag {
  fn to_sql(&self, ty: &Type, out: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
    // ???
  }
  fn accepts(ty: &Type) -> bool {
    // ???
  }
}

Can someone help me?

1

There are 1 best solutions below

0
Einliterflasche On

From the postgres-types documentation (which both tokio-postgres and postgres are based on so this will work for both crates):

Postgres enums correspond to C-like enums in Rust:

CREATE TYPE "Mood" AS ENUM (
    'Sad',
    'Ok',
    'Happy'
);
use postgres_types::{ToSql, FromSql};

#[derive(Debug, ToSql, FromSql)]
enum Mood {
    Sad,
    Ok,
    Happy,
}

and for naming:

You can use #[postgres(name = "flag")] to adjust the enum name and rename_all = "snake_case" to adjust the variant names (for more extensive information see the docs I linked). In your case the final code would look like this:

// tokio_postgres reexports postgres_types as the types module
use tokio_postgres::types::ToSql;

#[derive(Debug, ToSql)] // ToSql requires Debug
#[postgres(name = "flag", rename_all = "snake_case")]
enum Flag {
    MyFlag1, 
    MyFlag2, 
    MyFlag3
}

This will correctly parse your postgres enum created with

CREATE TYPE flag AS ENUM ('my_flag_1', 'my_flag_2', 'my_flag_3');