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

Matching on SqlState #756

Closed
treuherz opened this issue Apr 24, 2021 · 2 comments
Closed

Matching on SqlState #756

treuherz opened this issue Apr 24, 2021 · 2 comments

Comments

@treuherz
Copy link

treuherz commented Apr 24, 2021

I'm trying to figure out how best to catch SQL errors that I'd like to handle specifically or just bubble up, but I'm having some trouble figuring out exactly how to hold SqlState to do this in a way that looks sensible. My first attempt was this:

client
    .execute(/* snip */)
    .map_err(|e|
        match e.as_db_error() {
            Some(dbe) => match (dbe.code(), dbe.column()) {
                (&SqlState::FOREIGN_KEY_VIOLATION, Some("player_id")) => PlayerNotFound(player_id),
                (&SqlState::UNIQUE_VIOLATION, Some("event_id")) => Conflict,
                _ => DatastoreError(anyhow!(e)),
            },
            None => DatastoreError(anyhow!(e))
        }
    )?;

But that gives the error:

error: to use a constant of type `Cow` in a pattern, `Cow` must be annotated with `#[derive(PartialEq, Eq)]`

I can't quite figure out what's happening here, as SqlState has #[derive(PartialEq, Eq)] on it, but the compiler doesn't seem happy with it regardless. The workaround I've ended up with is below

client
    .execute(/* snip */)
    .map_err(|e|
        match e.as_db_error() {
            Some(dbe) => match dbe.column() {
                Some("player_id") if dbe.code() == &SqlState::FOREIGN_KEY_VIOLATION => PlayerNotFound(player_id),
                Some("roll_id") if dbe.code() == &SqlState::UNIQUE_VIOLATION => Conflict,
                _ => DatastoreError(anyhow!(e)),
            },
            None => DatastoreError(anyhow!(e))
        }
    )?;

but it still feels like I'm missing something obvious. I'm not wild about this approach, not least because guards feel less readable than patterns, but also because the SqlState is the primary thing I'm matching on here, the column is secondary info, and having them this way round makes that feel wrong.

I'm not sure if this report is asking for a code change to make this easier, or just a pointer in how to use the struct correctly, but any help would be appreciated either way. If this does work but in a non-obvious way I'd happily write a documentation PR for it.

@sfackler
Copy link
Owner

It is definitely intended to be able to match on SqlState constants. The build failure does make sense though - I will fix.

@treuherz
Copy link
Author

Incredible turnaround, thanks for the fix!

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