I'm using the postgres-rs crate to retrieve info from a database. The query result gets stored in a postgres::Row
where I can read a value at a time with Row::get()
.
So far so good, but now I want to read a PostgreSQL smallint
or i16
, and use this value as an i64
in Rust. I got it to work with:
let temp: Option<i16> = row.get(index);
let value = if let Some(v) = temp { Some(i64::from(v)) } else { None };
But it must be because my lack of experience with Rust that I can't write a one liner. I've tried:
let value: Option<i64> = row.get::<Option<i16>>::get(index);
But that leaves me with an error:
the trait `postgres::row::RowIndex` is not implemented for `std::option::Option<i64>`
Also I can't seem to cast option values directly:
let value: Option<usize> = Some(1 as i16).into();
This also gives me a similar error:
the trait `From<Option<i16>>` is not implemented for `Option<usize>`
I assume these errors are by design, but I'm still wondering if there isn't a shorter or better way to rewrite my first working example.
Row::get()
takes two generic type arguments: I
, type of the index, and T
, type of the return vaue. Your attempt to specify the type argument sets the first one, which is I
, whereas you meant to set T
. This is why you get the error that "trait RowIndex
is not implemented for Option<i64>
". You need to use _
to leave it to the compiler to infer I
:
let value: Option<i64> = row.get::<_, Option<i16>>(index).map(Into::into);
Your other issue that you try to convert to usize
using the From
(or Into
) trait, which doesn't work because From
is for conversions that can't fail. Since there are i16
values that can't be represented as usize
(all the negative ones), From<i16>
is not implemented for usize
. Instead, you need to use TryFrom
, which is, and handle errors accordingly.