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

Method Row.get(index) could not convert Null to Option(T) #305

Open
manortec opened this issue May 5, 2024 · 2 comments
Open

Method Row.get(index) could not convert Null to Option(T) #305

manortec opened this issue May 5, 2024 · 2 comments

Comments

@manortec
Copy link

manortec commented May 5, 2024

I'm writing a web application,and I encountered a problem when using mysql_async. I found that the get or take method of the Row type(Row.get(index))could not correctly convert the Null value to the expected type "None", but other non-Null values ​​could be converted well. The following is my relevant code. This code can be compiled, but a panic error will occur when running this code. At the same time, I also listed a code that can run correctly for comparison. Thank you very much for any help.

#[derive(Debug, Serialize)]
pub struct UserInfo{
    pub guid_user:Option<u64>,
    pub nick_name:Option<String>,
    pub email:Option<String>,
    pub phone:Option<String>,
}

pub async fn  get_info(guid:u64)-> Result<Option<UserInfo>>{
    let mut conn = DB.get().unwrap().get_conn().await?;
    let q="select guid_user,nick_name,email,phone from fp_user where guid_user=?";
    let p=(guid,);
    // let row =conn.exec_first(q,p).await?;
    // let r=row.map(|(guid_user,nick_name,email,phone)|UserInfo{guid_user,nick_name,email,phone});
    let row:Option<Row> =conn.exec_first(q,p).await?;
    let r=row.map(|row|UserInfo{ guid_user: row.get(0), nick_name: row.get(1) ,email:row.get(2), phone: row.get(3) });

    drop(conn);
    Ok(r)
}

When I make a request calling this function, I get the following error:

thread 'tokio-runtime-worker' panicked at /home/allen/.cargo/registry/src/rsproxy.cn-0dccff568467c15b/mysql_common-0.32.1/src/value/convert/mod.rs:122:23:
Could not retrieve `alloc::string::String`: Couldn't convert the value `Null` to a desired type

It should be noted that the fields nick_name and email in my database have null values, and other fields have normal values.
As a comparison test, if you replace the two lines below with the two commented out lines in the above code, it will run correctly.
For another comparison, if the nick_name and email fields are filled with normal values, or the query does not contain fields with null values, the above code can also run correctly.
The result of a correctly executed request is roughly like this.

{
    "code": 0,
    "msg": "OK",
    "data": {
        "guid_user": 1714805969000000,
        "nick_name": null,
        "email": null,
        "phone": "135819131xx"
    }
}

The mysql_async version used in my cargo.toml file is as follows:

mysql_async = { version = "0.34.1", default-features = false, features = ["minimal"]}

The result I expect is that if the type of a certain attribute of my structure is Option (T), then the get or take method of the Row type needs to convert the null value to None.
Thank you very much for your answer.

@manortec manortec changed the title Method Row.get(index) could not convert Null to OPtion(T) Method Row.get(index) could not convert Null to Option(T) May 5, 2024
@blackbeam
Copy link
Owner

Hi. This is because Row::get by itself returns an Option, so if cell type is Option<String>, then the return type of the get function is Option<Option<String>>.
Btw, I would call the get function low level, try something like this instead:

let Some((guid_user, nick_name, email, phone)) = conn.exec_first(q,p).await? else {
    return Ok(None);
};
Ok(UserInfo {
    guid_user,
    nick_name,
    email,
    phone,
});

@manortec
Copy link
Author

manortec commented May 6, 2024

Hi. This is because Row::get by itself returns an Option, so if cell type is Option<String>, then the return type of the get function is Option<Option<String>>. Btw, I would call the get function low level, try something like this instead:

let Some((guid_user, nick_name, email, phone)) = conn.exec_first(q,p).await? else {
    return Ok(None);
};
Ok(UserInfo {
    guid_user,
    nick_name,
    email,
    phone,
});

Thank you very much! I will have a try.

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