use serde::{Deserialize, Serialize};
use serde_json::Value as JsonValue;
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Predicate {
pub col: String,
pub op: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub val: Option<JsonValue>,
}
impl Predicate {
pub fn new(col: impl Into<String>, op: impl Into<String>, val: impl Into<JsonValue>) -> Self {
Self {
col: col.into(),
op: op.into(),
val: Some(val.into()),
}
}
pub fn unary(col: impl Into<String>, op: impl Into<String>) -> Self {
Self {
col: col.into(),
op: op.into(),
val: None,
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct OrderBy {
pub col: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub dir: Option<String>,
}
impl OrderBy {
pub fn asc(col: impl Into<String>) -> Self {
Self {
col: col.into(),
dir: Some("asc".into()),
}
}
pub fn desc(col: impl Into<String>) -> Self {
Self {
col: col.into(),
dir: Some("desc".into()),
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Aggregation {
#[serde(skip_serializing_if = "Option::is_none")]
pub col: Option<String>,
pub op: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub alias: Option<String>,
}
impl Aggregation {
pub fn count(alias: Option<&str>) -> Self {
Self {
col: None,
op: "count".into(),
alias: alias.map(str::to_owned),
}
}
pub fn over(op: impl Into<String>, col: impl Into<String>, alias: Option<&str>) -> Self {
Self {
col: Some(col.into()),
op: op.into(),
alias: alias.map(str::to_owned),
}
}
}
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct QueryRequest {
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub columns: Vec<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub predicates: Vec<Predicate>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub group_by: Vec<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub aggregations: Vec<Aggregation>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub having: Vec<Predicate>,
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
pub distinct: bool,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub order_by: Vec<OrderBy>,
#[serde(skip_serializing_if = "Option::is_none")]
pub limit: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub page: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub page_size: Option<u64>,
}
impl QueryRequest {
pub fn builder() -> QueryRequestBuilder {
QueryRequestBuilder::default()
}
}
#[derive(Clone, Debug, Default)]
pub struct QueryRequestBuilder {
inner: QueryRequest,
}
impl QueryRequestBuilder {
pub fn columns<I, S>(mut self, cols: I) -> Self
where
I: IntoIterator<Item = S>,
S: Into<String>,
{
self.inner.columns = cols.into_iter().map(Into::into).collect();
self
}
pub fn predicate(mut self, p: Predicate) -> Self {
self.inner.predicates.push(p);
self
}
pub fn group_by<I, S>(mut self, cols: I) -> Self
where
I: IntoIterator<Item = S>,
S: Into<String>,
{
self.inner.group_by = cols.into_iter().map(Into::into).collect();
self
}
pub fn aggregation(mut self, a: Aggregation) -> Self {
self.inner.aggregations.push(a);
self
}
pub fn having(mut self, p: Predicate) -> Self {
self.inner.having.push(p);
self
}
pub fn distinct(mut self, yes: bool) -> Self {
self.inner.distinct = yes;
self
}
pub fn order_by(mut self, o: OrderBy) -> Self {
self.inner.order_by.push(o);
self
}
pub fn limit(mut self, n: u64) -> Self {
self.inner.limit = Some(n);
self
}
pub fn page(mut self, n: u64) -> Self {
self.inner.page = Some(n);
self
}
pub fn page_size(mut self, n: u64) -> Self {
self.inner.page_size = Some(n);
self
}
pub fn build(self) -> QueryRequest {
self.inner
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct QueryResponse {
pub data: Vec<JsonValue>,
#[serde(default)]
pub page: Option<u64>,
#[serde(default)]
pub page_size: Option<u64>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct SqlResponse {
pub data: Vec<JsonValue>,
#[serde(default)]
pub max_rows: Option<u64>,
}
#[derive(Clone, Debug, Serialize)]
pub struct SqlRequest {
pub sql: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub max_rows: Option<u64>,
}