kdb_connection/queries/
kdql.rs1use std::collections::HashMap;
4
5use serde::{Deserialize, Serialize};
6
7use crate::prelude::*;
8
9#[derive(Deserialize, Serialize)]
10#[serde(untagged)]
11pub enum Value
12{
13 Integer(i64),
14 Float(f64),
15 String(String),
16 Array(Vec<Value>),
17 Map(ValueMap),
18}
19
20macro_rules! value_into {
21 ($name:tt, $type:ty) => {
22 impl From<$type> for Value
23 {
24 fn from(value: $type) -> Value
25 {
26 Value::$name(value.into())
27 }
28 }
29 };
30}
31
32value_into!(Integer, i64);
33value_into!(Float, f64);
34value_into!(String, String);
35value_into!(String, &str);
36value_into!(Array, Vec<Value>);
37value_into!(Map, ValueMap);
38
39pub type ValueMap = HashMap<String, Value>;
40
41#[macro_export]
50macro_rules! krql_value_map {
51 ($($k:expr => $v:expr),* $(,)?) => {
53 {
54 let value_map: $crate::queries::kdql::ValueMap = core::convert::From::from([$(($k.to_string(), $v.into()),)*]);
55 value_map
56 }
57 };
58}
59
60#[derive(Deserialize, Serialize)]
61#[serde(untagged)]
62pub enum What
63{
64 #[serde(serialize_with = "serialize_all", deserialize_with = "deserialize_all")]
65 All,
66 Identifiers(Vec<String>),
67}
68
69fn serialize_all<S>(serializer: S) -> Result<S::Ok, S::Error>
70where
71 S: serde::ser::Serializer,
72{
73 serializer.serialize_str("*")
74}
75
76fn deserialize_all<'de, D>(deserializer: D) -> Result<(), D::Error>
77where
78 D: serde::de::Deserializer<'de>,
79{
80 use serde::de::Error;
81 let s = String::deserialize(deserializer)?;
82 if s == "*"
83 {
84 Ok(())
85 }
86 else
87 {
88 Err(D::Error::custom("Expected '*'"))
89 }
90}
91
92impl From<Vec<&str>> for What
93{
94 fn from(value: Vec<&str>) -> Self
95 {
96 Self::Identifiers(value.into_iter().map(|x| x.to_owned()).collect())
97 }
98}
99
100#[derive(Deserialize, Serialize)]
102#[serde(rename_all = "lowercase")]
103pub enum KDQLQuery
104{
105 Create
107 {
108 into: String,
110 documents: Vec<HashMap<String, Value>>,
112 },
113 Drop(Vec<String>),
115 Retrieve
117 {
118 what: What,
120 from: String,
122 matches: HashMap<String, Value>,
124 },
125}
126
127impl TryFrom<&KDQLQuery> for dbc::Query
128{
129 type Error = Error;
130 fn try_from(value: &KDQLQuery) -> std::result::Result<Self, Self::Error>
131 {
132 let kdql_query = serde_json::to_string(value)?;
134 Ok(dbc::Query::new(
135 kdql_query,
136 Default::default(),
137 dbc::QueryType::KDQL,
138 ))
139 }
140}
141
142impl TryFrom<KDQLQuery> for dbc::Query
143{
144 type Error = Error;
145 fn try_from(value: KDQLQuery) -> std::result::Result<Self, Self::Error>
146 {
147 (&value).try_into()
148 }
149}
150
151#[cfg(test)]
152mod test
153{
154 use super::{KDQLQuery, What};
155 #[test]
156 fn test_kdql_create()
157 {
158 let query = KDQLQuery::Create {
159 into: "test".into(),
160 documents: vec![
161 krql_value_map!("name" => "a"),
162 krql_value_map!("name" => "b"),
163 ],
164 };
165 assert_eq!(
166 serde_saphyr::to_string(&query).unwrap(),
167 r#"create:
168 into: test
169 documents:
170 - name: a
171 - name: b
172"#
173 );
174 }
175 #[test]
176 fn test_kdql_retrieve_all()
177 {
178 let query = KDQLQuery::Retrieve {
179 what: What::All,
180 from: "test".into(),
181 matches: krql_value_map!("name" => "a"),
182 };
183 assert_eq!(
184 serde_saphyr::to_string(&query).unwrap(),
185 r#"retrieve:
186 what: "*"
187 from: test
188 matches:
189 name: a
190"#
191 );
192 }
193 #[allow(dead_code)]
196 fn test_kdql_retrieve_age()
197 {
198 let query = KDQLQuery::Retrieve {
199 what: vec!["age"].into(),
200 from: "test".into(),
201 matches: krql_value_map!("name" => "a"),
202 };
203 assert_eq!(
204 serde_saphyr::to_string(&query).unwrap(),
205 r#"retrieve:
206 what:
207 - age
208 from: test
209 matches:
210 name: a
211"#
212 );
213 }
214}