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}