mod de;
use serde::de::DeserializeOwned;
use serde_derive::Deserialize;
use crate::client::check_status;
use crate::{Client, Error, Query, ReadQuery};
#[derive(Deserialize)]
#[doc(hidden)]
struct _DatabaseError {
error: String,
}
#[derive(Deserialize, Debug)]
#[doc(hidden)]
pub struct DatabaseQueryResult {
pub results: Vec<serde_json::Value>,
}
impl DatabaseQueryResult {
pub fn deserialize_next<T: 'static>(&mut self) -> Result<Return<T>, Error>
where
T: DeserializeOwned + Send,
{
serde_json::from_value::<Return<T>>(self.results.remove(0)).map_err(|err| {
Error::DeserializationError {
error: format!("could not deserialize: {err}"),
}
})
}
pub fn deserialize_next_tagged<TAG, T: 'static>(
&mut self,
) -> Result<TaggedReturn<TAG, T>, Error>
where
TAG: DeserializeOwned + Send,
T: DeserializeOwned + Send,
{
serde_json::from_value::<TaggedReturn<TAG, T>>(self.results.remove(0)).map_err(|err| {
Error::DeserializationError {
error: format!("could not deserialize: {err}"),
}
})
}
}
#[derive(Deserialize, Debug)]
#[doc(hidden)]
pub struct Return<T> {
#[serde(default = "Vec::new")]
pub series: Vec<Series<T>>,
}
#[derive(Debug)]
pub struct Series<T> {
pub name: String,
pub values: Vec<T>,
}
#[derive(Deserialize, Debug)]
#[doc(hidden)]
pub struct TaggedReturn<TAG, T> {
#[serde(default = "Vec::new")]
pub series: Vec<TaggedSeries<TAG, T>>,
}
#[derive(Debug)]
pub struct TaggedSeries<TAG, T> {
pub name: String,
pub tags: TAG,
pub values: Vec<T>,
}
impl Client {
pub async fn json_query(&self, q: ReadQuery) -> Result<DatabaseQueryResult, Error> {
let query = q.build().map_err(|err| Error::InvalidQueryError {
error: err.to_string(),
})?;
let read_query = query.get();
let read_query_lower = read_query.to_lowercase();
if !read_query_lower.contains("select") && !read_query_lower.contains("show") {
let error = Error::InvalidQueryError {
error: "Only SELECT and SHOW queries supported with JSON deserialization".into(),
};
return Err(error);
}
let url = &format!("{}/query", &self.url);
let mut parameters = self.parameters.as_ref().clone();
parameters.insert("q", read_query);
let mut request_builder = self.client.get(url);
if let Some(ref token) = self.token {
request_builder = request_builder.header("Authorization", format!("Token {token}"))
}
let request_builder = request_builder.query(¶meters);
let res = request_builder
.send()
.await
.map_err(|err| Error::ConnectionError {
error: err.to_string(),
})?;
check_status(&res)?;
let body = res.bytes();
let body = body.await.map_err(|err| Error::ProtocolError {
error: err.to_string(),
})?;
if let Ok(error) = serde_json::from_slice::<_DatabaseError>(&body) {
return Err(Error::DatabaseError { error: error.error });
}
serde_json::from_slice::<DatabaseQueryResult>(&body).map_err(|err| {
Error::DeserializationError {
error: format!("serde error: {err}"),
}
})
}
}