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

Using Enums with query_typed #1180

Open
alex-richman-onesignal opened this issue Sep 19, 2024 · 3 comments
Open

Using Enums with query_typed #1180

alex-richman-onesignal opened this issue Sep 19, 2024 · 3 comments

Comments

@alex-richman-onesignal
Copy link

Hi,

I'm converting some code from query to query_typed, so it can sit behind a transactional pooler.

I have a query that looks like this, whcih works fine:

conn.query("SELECT * FROM macguffins WHERE kind = $1;", &[&kind]).await

And coverted it to query_typed by adding Type::ANYENUM, which is the only enum related type I could find i n the crate:

conn.query_typed("SELECT * FROM macguffins WHERE kind = $1;", &[(&kind, Type::ANYENUM)]).await

But this does not work, throwing:

error serializing parameter 0: cannot convert between the Rust type `macguffin_factory::postgres::MacguffinKind` and the Postgres type `anyenum

MacguffinKind looks like:

#[derive(Debug, FromSql, ToSql, Clone, Copy)]
#[postgres(name = "macguffin_kind")]
pub enum MacguffinKind {
    #[postgres(name = "blue")]
    Blue,
    #[postgres(name = "Green")]
    Green,
}

I tried adding allow_mismatch to the enum derive, but no dice.

What's the right way to use Enums with query_typed?

Thanks!

  • Alex.
@sfackler
Copy link
Owner

You can extract a Type for user-defined Postgres types by preparing a query and pulling it out of the Statement. Something like this (untested):

let stmt = client.prepare("SELECT $1::macguffin_kind")?;
let macguffin_kind_type = stmt.params()[0].clone();

@alex-richman-onesignal
Copy link
Author

Thanks, this is interesting -- I was able to get it working like this:

let statement = conn.prepare("SELECT $1::macguffin_kind;").await?;
let macguffin_kind_type = stmt.params()[0].clone();

Where macguffin_kind_type came back as:

Other(Other { name: "macguffin_kind", oid: 33131, kind: Enum(["blue", "green"]), schema: "public" })

Seems like we should also be able to build that Other type ourselves without calling a prepare, something like this is accepted:

Type::new("macguffin_kind".to_string(), 33131, Kind::Enum(vec!["blue".to_string(), "green".to_string()]), "public".to_string());

I suppose the issue being that the OID will be different per server. However even if I set the oid to 0 it's still accepted and works in the query so maybe it's not required for this specific case?

Either way, it would be cool if this were somehow baked into the FormSql/ToSql derives to make the query_typed a little easier to use.

@sfackler
Copy link
Owner

Setting the OID to 0 is the same thing as not using query_typed. The whole point of that method vs query is that you are telling the server the specific type OIDs of each query parameter.

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