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

Implement Queryable for all non-contradictory stdlib types #22

Open
tailhook opened this issue Mar 24, 2020 · 7 comments
Open

Implement Queryable for all non-contradictory stdlib types #22

tailhook opened this issue Mar 24, 2020 · 7 comments

Comments

@tailhook
Copy link
Contributor

No description provided.

tailhook added a commit that referenced this issue Mar 24, 2020
@dmgolembiowski
Copy link

Would something like this be sufficient?

trait Queryable {
    ...
}

macro_rules! impl_queryable {
    ($($ty:ty),*) => {
        $(
            impl Queryable for $ty {
               ....
                }
            }
        )*
    }   
}

impl_queryable!(u8, i8, u16, i16, u32, i32, u64, i64);

@tailhook
Copy link
Contributor Author

Usually I'm trying to avoid macros. Also I don't think we can have impl for some of listed types, which we don't want have in the database itself. (e.g. we don't have u8 and i8, and u8 may be stored as u16 or as i16) But I think we can have impl for NonZeroU32 (which is probably macro-incompatible with u32 impl).

Also I think it's about Paths and maybe CStrings and various containers which don't have generalization on macro level I think.

@CodesInChaos
Copy link
Contributor

I'd at least use a macro for tuples.

For integers I'd first wait to see if edgedb adds native support for additional integer sizes (with u8 causing complications because it could be an array of bytes, or the Bytes type).

@dmgolembiowski
Copy link

Ah, okay; thank you for explaining. I didn't realize the amount of complexity involved with each of the types when I had suggested the impl_queryable! idea.

@MrFoxPro
Copy link
Contributor

MrFoxPro commented Nov 2, 2023

Do I understand correctly that this will solve my problem:

#[derive(Queryable, Serialize)]
struct SelectedUser {
   id: Uuid,
   created_at: DateTime,
   phone: String,
}
async fn endpoint(State(AppContext { edb }): State<AppContext>) -> Json<SelectedUser> {
   let query = "
      select std::assert_single((
         select User {
            id,
            created_at,
            phone
         } filter (User.phone = <str>$0)
      ))
   ";
   let found_user: SelectedUser = edb.query_required_single(query, &("+790000000",)).await.unwrap();
   return Json(found_user);
}
the trait bound `edgedb_protocol::model::Uuid: Serialize` is not satisfied
the following other types implement trait `Serialize`
required by a bound in `_::_serde::ser::SerializeStruct::serialize_field`

the trait bound `edgedb_protocol::model::Datetime: Serialize` is not satisfied
the following other types implement trait `Serialize`:

So I will able to use id: String and created_at: i64 instead?

Or should I create separate issue?

@darshanDevrai
Copy link

Hey @MrFoxPro

How are you handling

the trait bound `edgedb_protocol::model::Uuid: Serialize` is not satisfied

@MrFoxPro
Copy link
Contributor

Hey @MrFoxPro

How are you handling

the trait bound `edgedb_protocol::model::Uuid: Serialize` is not satisfied

You can use something like this instead of Queryable:

#[derive(Clone)]
pub struct EdgedbSerdeClient(pub edgedb_tokio::Client);
impl EdgedbSerdeClient {
    pub async fn query_serde<R, A>(&self, query: impl AsRef<str>, arguments: &A) -> Result<Vec<R>, anyhow::Error>
    where
        A: QueryArgs,
        R: serde::de::DeserializeOwned,
    {
        let json = self.query_json(query, arguments).await?;
        let parsed = serde_json::from_str::<Vec<R>>(&json)?;
        Ok(parsed)
    }

    pub async fn query_single_serde<R, A>(
        &self,
        query: impl AsRef<str>,
        arguments: &A,
    ) -> Result<Option<R>, anyhow::Error>
    where
        A: QueryArgs,
        R: serde::de::DeserializeOwned,
    {
        let json = self.query_single_json(query, arguments).await?;
        if let Some(json) = json {
            let parsed = serde_json::from_str::<Option<R>>(&json)?;
            return Ok(parsed);
        }
        return Ok(None);
    }

    pub async fn query_required_single_serde<R, A>(
        &self,
        query: impl AsRef<str>,
        arguments: &A,
    ) -> Result<R, anyhow::Error>
    where
        A: QueryArgs,
        R: serde::de::DeserializeOwned,
    {
        let json = self.query_required_single_json(query, arguments).await?;
        let parsed = serde_json::from_str::<R>(&json)?;
        return Ok(parsed);
    }
}
impl std::ops::Deref for EdgedbSerdeClient {
    type Target = edgedb_tokio::Client;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

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

5 participants