Reputation: 33
I'm trying to execute an SQL query to a Postgres database, using query_as
. The error I get is:
panicked at 'called `Result::unwrap()` on an `Err` value:
ColumnDecode { index: "\"id\"", source: "mismatched types; Rust type `()`
(as SQL type `VOID`) is not compatible with SQL type `CHAR`" }'
In the database the id
column is of type bpchar(36)
and in Rust I'm using a UuidWrapper
struct for it.
#[derive(PartialEq, Debug, Clone)]
pub struct UuidWrapper(pub(crate) Uuid);
I want to execute the query and store the output into a Post
type:
pub struct Post {
pub id: UuidWrapper,
/* ... */
This struct implements the needed FromRow
trait but the code never enters from_row
impl<'r> FromRow<'r, PgRow> for Post {
fn from_row(row: &PgRow) -> Result<Self, sqlx::Error> {
Ok(Post {
id: UuidWrapper::from(row.try_get("id")?),
/* ... */
})
}
}
This is how I do the query:
async fn select_where(pool: &Pool<Postgres>, query: &str) -> Vec<Self>
where
Self: Sized,
{
let res = query_as!(Post, "select * from posts WHERE owner_id = 'b0648b6c-f3a7-4789-bf57-3b44e15029d9' AND CAST(create_time AS DATE) = '2023-05-14'").fetch_all(pool).await;
let q = format!("SELECT * FROM posts {query}");
query_as::<_, Self>(&q).fetch_all(pool).await.unwrap()
}
The string literal in query_as!
is the same as the value of q
, however this query succeeds and returns a Vec<Post>
, but the query_as
(not macro, with variables instead of hardcoded values) crashes.
Dependencies:
sqlx = { version = "0.7.1",
features = [ "runtime-tokio-rustls", "postgres", "time", "chrono", "uuid", "macros", "chrono" ] }
I tried debugging, changing the UuidWrapper
struct and other wrapper structs, double checking data types to be compatible with the database.
Upvotes: 1
Views: 2526
Reputation: 33
I fixed the issue by changing the FromRow
implementation to:
impl<'r> FromRow<'r, PgRow> for Post {
fn from_row(row: &PgRow) -> Result<Self, sqlx::Error> {
let s: String = row.try_get("id")?;
let id: UuidWrapper = UuidWrapper(Uuid::from_str(s.as_str()).unwrap());
let s: String = row.try_get("owner_id")?;
let owner_id: UuidWrapper = UuidWrapper(Uuid::from_str(s.as_str()).unwrap());
let create_time_str: NaiveDateTime = row.try_get("create_time")?;
Ok(Post {
id,
owner_id,
create_time: DateTimeWrapper(create_time_str),
Now every object is explicitly formed
Upvotes: 2