From 0cbcb3b374dc6272237c834aabee6433d2b4e424 Mon Sep 17 00:00:00 2001 From: Tobie Morgan Hitchcock Date: Mon, 2 May 2022 00:35:01 +0100 Subject: [PATCH] Simplify database query response object --- lib/src/dbs/executor.rs | 28 ++++------ lib/src/dbs/response.rs | 117 ++++++++++++++++++++++++++-------------- lib/src/err/mod.rs | 10 ++++ 3 files changed, 96 insertions(+), 59 deletions(-) diff --git a/lib/src/dbs/executor.rs b/lib/src/dbs/executor.rs index 03576993..488692e2 100644 --- a/lib/src/dbs/executor.rs +++ b/lib/src/dbs/executor.rs @@ -1,5 +1,5 @@ use crate::ctx::Context; -use crate::dbs::response::{Response, Responses, Status}; +use crate::dbs::response::{Response, Responses}; use crate::dbs::Auth; use crate::dbs::Level; use crate::dbs::Options; @@ -97,9 +97,7 @@ impl Executor { Response { sql: v.sql, time: v.time, - status: Status::Err, - detail: Some(format!("{}", Error::QueryCancelled)), - result: None, + result: Err(Error::QueryCancelled), } } @@ -108,12 +106,10 @@ impl Executor { true => Response { sql: v.sql, time: v.time, - status: Status::Err, - detail: match v.status { - Status::Ok => Some(format!("{}", Error::QueryNotExecuted)), - Status::Err => v.detail, + result: match v.result { + Ok(_) => Err(Error::QueryNotExecuted), + Err(e) => Err(e), }, - result: None, }, _ => v, } @@ -274,10 +270,8 @@ impl Executor { true => Some(format!("{}", stm)), false => None, }, - time: format!("{:?}", dur), - status: Status::Ok, - detail: None, - result: v.output(), + time: dur, + result: Ok(v), }, Err(e) => { // Produce the response @@ -286,10 +280,8 @@ impl Executor { true => Some(format!("{}", stm)), false => None, }, - time: format!("{:?}", dur), - status: Status::Err, - detail: Some(format!("{}", e)), - result: None, + time: dur, + result: Err(e), }; // Mark the error self.err = true; @@ -310,6 +302,6 @@ impl Executor { } } // Return responses - Ok(Responses(out)) + Ok(out) } } diff --git a/lib/src/dbs/response.rs b/lib/src/dbs/response.rs index 20a49e70..1f8dd5af 100644 --- a/lib/src/dbs/response.rs +++ b/lib/src/dbs/response.rs @@ -1,54 +1,89 @@ +use crate::err::Error; use crate::sql::value::Value; -use serde::{Deserialize, Serialize}; +use serde::ser::SerializeStruct; +use serde::Serialize; +use std::time::Duration; -#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] -#[serde(rename_all = "UPPERCASE")] -pub enum Status { - Ok, - Err, -} +pub type Responses = Vec; -#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)] -pub struct Responses(pub Vec); - -impl Responses { - pub fn first(mut self) -> Response { - self.0.remove(0) - } -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +#[derive(Debug)] pub struct Response { - #[serde(skip_serializing_if = "Option::is_none")] pub sql: Option, - pub time: String, - pub status: Status, - #[serde(skip_serializing_if = "Option::is_none")] - pub detail: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub result: Option, + pub time: Duration, + pub result: Result, } impl Response { - // Check if response succeeded - pub fn is_ok(&self) -> bool { - match self.status { - Status::Ok => true, - Status::Err => false, - } - } - // Check if response failed - pub fn is_err(&self) -> bool { - match self.status { - Status::Ok => false, - Status::Err => true, - } + // Return the transaction speed + pub fn speed(&self) -> String { + format!("{:?}", self.time) } // Retrieve the response as a result - pub fn output(self) -> Result { - match self.status { - Status::Ok => Ok(self.result.unwrap()), - Status::Err => Err(self.detail.unwrap()), + pub fn output(&self) -> Result<&Value, &Error> { + match &self.result { + Ok(v) => Ok(v), + Err(e) => Err(e), + } + } +} + +impl Serialize for Response { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + match &self.result { + Ok(v) => match v { + Value::None => match &self.sql { + Some(s) => { + let mut val = serializer.serialize_struct("Response", 3)?; + val.serialize_field("sql", s.as_str())?; + val.serialize_field("time", self.speed().as_str())?; + val.serialize_field("status", "OK")?; + val.end() + } + None => { + let mut val = serializer.serialize_struct("Response", 2)?; + val.serialize_field("time", self.speed().as_str())?; + val.serialize_field("status", "OK")?; + val.end() + } + }, + v => match &self.sql { + Some(s) => { + let mut val = serializer.serialize_struct("Response", 4)?; + val.serialize_field("sql", s.as_str())?; + val.serialize_field("time", self.speed().as_str())?; + val.serialize_field("status", "OK")?; + val.serialize_field("result", v)?; + val.end() + } + None => { + let mut val = serializer.serialize_struct("Response", 3)?; + val.serialize_field("time", self.speed().as_str())?; + val.serialize_field("status", "OK")?; + val.serialize_field("result", v)?; + val.end() + } + }, + }, + Err(e) => match &self.sql { + Some(s) => { + let mut val = serializer.serialize_struct("Response", 4)?; + val.serialize_field("sql", s.as_str())?; + val.serialize_field("time", self.speed().as_str())?; + val.serialize_field("status", "ERR")?; + val.serialize_field("detail", e)?; + val.end() + } + None => { + let mut val = serializer.serialize_struct("Response", 3)?; + val.serialize_field("time", self.speed().as_str())?; + val.serialize_field("status", "ERR")?; + val.serialize_field("detail", e)?; + val.end() + } + }, } } } diff --git a/lib/src/err/mod.rs b/lib/src/err/mod.rs index 165d05fa..bf2a0ff6 100644 --- a/lib/src/err/mod.rs +++ b/lib/src/err/mod.rs @@ -2,6 +2,7 @@ use crate::sql::idiom::Idiom; use crate::sql::thing::Thing; use crate::sql::value::Value; use msgpack::encode::Error as SerdeError; +use serde::Serialize; use std::time::Duration; use storekey::decode::Error as DecodeError; use storekey::encode::Error as EncodeError; @@ -206,3 +207,12 @@ pub enum Error { #[error("Tokio Error: {0}")] Tokio(#[from] TokioError<(Option, Value)>), } + +impl Serialize for Error { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.to_string().as_str()) + } +}