edgedb_composable_query/
tuples.rs

1use edgedb_protocol::value::Value;
2
3use crate::value::{EdgedbSetValue, EdgedbValue};
4
5impl EdgedbValue for () {
6    type NativeArgType = ();
7
8    fn from_edgedb_value(value: Value) -> anyhow::Result<Self> {
9        if let Value::Nothing = value {
10            Ok(())
11        } else {
12            Err(anyhow::anyhow!("expected nothing"))
13        }
14    }
15
16    // fn to_edgedb_value(self) -> anyhow::Result<Value> {
17    //     Ok(Value::Nothing)
18    // }
19}
20
21macro_rules! impl_tuple {
22    ( $count:expr, ($($name:ident,)+), ($($small_name:ident,)+) ) => (
23
24        impl<$($name:EdgedbValue),+> EdgedbValue for ($($name,)+) {
25            // const EXPECTED_CARDINALITY: edgedb_protocol::server_message::Cardinality =
26            //     edgedb_protocol::server_message::Cardinality::One;
27
28            #[allow(unused_parens)] // not sure why
29            type NativeArgType = ($(<$name as EdgedbValue>::NativeArgType),+);
30
31            fn from_edgedb_value(value: edgedb_protocol::value::Value) -> anyhow::Result<Self> {
32                if let Value::Tuple(mut v) = value {
33                    if v.len() != $count {
34                        return Err(anyhow::anyhow!(
35                            "expected tuple of length {}, got {}",
36                            $count,
37                            v.len()
38                        ));
39                    }
40
41                    Ok(($($name::from_edgedb_set_value(v.pop().unwrap())?,)+))
42                } else {
43                    Err(anyhow::anyhow!("expected tuple"))
44                }
45            }
46
47            // fn to_edgedb_value(self) -> anyhow::Result<edgedb_protocol::value::Value> {
48            //     let ($($small_name,)+) = self;
49            //     Ok(Value::Tuple(vec![$($small_name.to_edgedb_set_value()?),+]))
50            // }
51
52            // fn interpret_possibly_missing_required_value(val: Option<Self>) -> anyhow::Result<Self> {
53            //     match val {
54            //         Some(val) => Ok(val),
55            //         None => Err(anyhow::anyhow!("expected single value")),
56            //     }
57            // }
58
59            // async fn query_direct(client: &edgedb_tokio::Client, q: &str) -> anyhow::Result<Self> {
60            //     let val = client.query_required_single::<Value, _>(q, &()).await?;
61            //     let val = Self::from_edgedb_set_value(val)?;
62            //     Ok(val)
63            // }
64        }
65
66    )
67}
68
69// macro_rules! impl_tuple {
70//     ( $count:expr, ($($name:ident,)+), ($($small_name:ident,)+) ) => (
71
72//         impl<$($name:EdgedbSetValue),+> EdgedbSetValue for ($($name,)+) {
73//             const EXPECTED_CARDINALITY: edgedb_protocol::server_message::Cardinality =
74//                 edgedb_protocol::server_message::Cardinality::One;
75
76//             fn from_edgedb_set_value(value: edgedb_protocol::value::Value) -> anyhow::Result<Self> {
77//                 if let Value::Tuple(mut v) = value {
78//                     if v.len() != $count {
79//                         return Err(anyhow::anyhow!(
80//                             "expected tuple of length {}, got {}",
81//                             $count,
82//                             v.len()
83//                         ));
84//                     }
85
86//                     Ok(($($name::from_edgedb_set_value(v.pop().unwrap())?,)+))
87//                 } else {
88//                     Err(anyhow::anyhow!("expected tuple"))
89//                 }
90//             }
91
92//             fn to_edgedb_set_value(self) -> anyhow::Result<edgedb_protocol::value::Value> {
93//                 let ($($small_name,)+) = self;
94//                 Ok(Value::Tuple(vec![$($small_name.to_edgedb_set_value()?),+]))
95//             }
96
97//             fn interpret_possibly_missing_required_value(val: Option<Self>) -> anyhow::Result<Self> {
98//                 match val {
99//                     Some(val) => Ok(val),
100//                     None => Err(anyhow::anyhow!("expected single value")),
101//                 }
102//             }
103
104//             async fn query_direct<Args: EdgedbQueryArgs>(client: &edgedb_tokio::Client, q: &str, args: Args) -> anyhow::Result<Self> {
105//                 let val = client.query_required_single::<Value, _>(q, &()).await?;
106//                 let val = Self::from_edgedb_set_value(val)?;
107//                 Ok(val)
108//             }
109//         }
110
111//     )
112// }
113
114impl_tuple! {1, (T0,), (t0,)}
115impl_tuple! {2, (T0, T1,), (t0, t1,)}
116impl_tuple! {3, (T0, T1, T2,), (t0, t1, t2,)}
117impl_tuple! {4, (T0, T1, T2, T3,), (t0, t1, t2, t3,)}
118impl_tuple! {5, (T0, T1, T2, T3, T4,), (t0, t1, t2, t3, t4,)}
119impl_tuple! {6, (T0, T1, T2, T3, T4, T5,), (t0, t1, t2, t3, t4, t5,)}
120
121#[cfg(test)]
122mod test {
123    use crate::{query, refs::Ref, value::EdgedbSetValue, EdgedbObject};
124
125    #[derive(Debug, PartialEq)]
126    struct Inner {
127        req: String,
128        opt: Option<String>,
129    }
130
131    impl EdgedbObject for Inner {
132        fn from_edgedb_object(
133            shape: edgedb_protocol::codec::ObjectShape,
134            mut fields: Vec<Option<edgedb_protocol::value::Value>>,
135        ) -> anyhow::Result<Self> {
136            let mut req = None;
137            let mut opt = None;
138
139            for (i, s) in shape.elements.iter().enumerate() {
140                match s.name.as_str() {
141                    "req" => {
142                        req = fields[i]
143                            .take()
144                            .map(EdgedbSetValue::from_edgedb_set_value)
145                            .transpose()?;
146                    }
147                    "opt" => {
148                        opt = fields[i]
149                            .take()
150                            .map(EdgedbSetValue::from_edgedb_set_value)
151                            .transpose()?;
152                    }
153                    _ => {}
154                }
155            }
156
157            Ok(Self {
158                req: EdgedbSetValue::interpret_possibly_missing_required_value(req)?,
159                opt: EdgedbSetValue::interpret_possibly_missing_required_value(opt)?,
160            })
161        }
162
163        // fn to_edgedb_object(
164        //     &self,
165        // ) -> anyhow::Result<(
166        //     edgedb_protocol::codec::ObjectShape,
167        //     Vec<Option<edgedb_protocol::value::Value>>,
168        // )> {
169        //     todo!()
170        // }
171    }
172
173    #[tokio::test]
174    async fn some_queries() -> anyhow::Result<()> {
175        let conn = edgedb_tokio::create_client().await?;
176
177        dbg!(
178            query::<(Ref<Inner>, Ref<Inner>), ()>(
179                &conn,
180                "
181            with a := (select Inner {id, opt, req} limit 1),
182            select (a, a)
183            ",
184                ()
185            )
186            .await?
187        );
188
189        Ok(())
190    }
191}