use crate::client::AthenaClient;
use crate::client::backend::{BackendError, QueryResult};
use serde_json::Value;
#[derive(Debug, Clone, Copy)]
pub enum OrderDirection {
Asc,
Desc,
}
#[derive(Debug, Clone)]
pub struct Condition {
pub column: String,
pub operator: ConditionOperator,
pub values: Vec<Value>,
}
#[derive(Debug, Clone, Copy)]
pub enum ConditionOperator {
Eq,
Neq,
Gt,
Lt,
In,
}
impl Condition {
pub fn new(column: impl Into<String>, operator: ConditionOperator, values: Vec<Value>) -> Self {
Self {
column: column.into(),
operator,
values,
}
}
}
pub struct SelectBuilder<'a> {
client: &'a AthenaClient,
table: String,
columns: Vec<String>,
raw_select: Option<String>,
conditions: Vec<Condition>,
order_by: Vec<(String, OrderDirection)>,
limit: Option<usize>,
offset: Option<usize>,
}
impl<'a> SelectBuilder<'a> {
pub(crate) fn new(client: &'a AthenaClient, table: impl Into<String>) -> Self {
Self {
client,
table: table.into(),
columns: Vec::new(),
raw_select: None,
conditions: Vec::new(),
order_by: Vec::new(),
limit: None,
offset: None,
}
}
pub fn columns(mut self, columns: impl IntoIterator<Item = impl Into<String>>) -> Self {
self.columns = columns.into_iter().map(|c| c.into()).collect();
self
}
pub fn raw_select(mut self, select: impl Into<String>) -> Self {
self.raw_select = Some(select.into());
self
}
fn add_condition(
mut self,
column: &str,
operator: ConditionOperator,
values: Vec<Value>,
) -> Self {
self.conditions
.push(Condition::new(column, operator, values));
self
}
pub fn where_eq(self, column: &str, value: impl Into<Value>) -> Self {
self.add_condition(column, ConditionOperator::Eq, vec![value.into()])
}
pub fn where_neq(self, column: &str, value: impl Into<Value>) -> Self {
self.add_condition(column, ConditionOperator::Neq, vec![value.into()])
}
pub fn where_gt(self, column: &str, value: impl Into<Value>) -> Self {
self.add_condition(column, ConditionOperator::Gt, vec![value.into()])
}
pub fn where_lt(self, column: &str, value: impl Into<Value>) -> Self {
self.add_condition(column, ConditionOperator::Lt, vec![value.into()])
}
pub fn where_in(self, column: &str, values: Vec<Value>) -> Self {
self.add_condition(column, ConditionOperator::In, values)
}
pub fn order_by(mut self, column: &str, direction: OrderDirection) -> Self {
self.order_by.push((column.to_string(), direction));
self
}
pub fn limit(mut self, value: usize) -> Self {
self.limit = Some(value);
self
}
pub fn offset(mut self, value: usize) -> Self {
self.offset = Some(value);
self
}
pub async fn execute(self) -> Result<QueryResult, BackendError> {
self.client.execute_select(self).await
}
pub(crate) fn into_parts(self) -> SelectQuery {
SelectQuery {
table: self.table,
columns: self.columns,
raw_select: self.raw_select,
conditions: self.conditions,
order_by: self.order_by,
limit: self.limit,
offset: self.offset,
}
}
}
pub(crate) struct SelectQuery {
pub table: String,
pub columns: Vec<String>,
pub raw_select: Option<String>,
pub conditions: Vec<Condition>,
pub order_by: Vec<(String, OrderDirection)>,
pub limit: Option<usize>,
pub offset: Option<usize>,
}
pub struct InsertBuilder<'a> {
client: &'a AthenaClient,
table: String,
payload: Value,
}
impl<'a> InsertBuilder<'a> {
pub(crate) fn new(client: &'a AthenaClient, table: impl Into<String>) -> Self {
Self {
client,
table: table.into(),
payload: Value::Null,
}
}
pub fn payload(mut self, payload: Value) -> Self {
self.payload = payload;
self
}
pub async fn execute(self) -> Result<QueryResult, BackendError> {
self.client.execute_insert(self).await
}
pub(crate) fn into_parts(self) -> InsertQuery {
InsertQuery {
table: self.table,
payload: self.payload,
}
}
}
pub(crate) struct InsertQuery {
pub table: String,
pub payload: Value,
}
pub struct UpdateBuilder<'a> {
client: &'a AthenaClient,
table: String,
row_id: Option<String>,
payload: Value,
}
impl<'a> UpdateBuilder<'a> {
pub(crate) fn new(
client: &'a AthenaClient,
table: impl Into<String>,
row_id: Option<String>,
) -> Self {
Self {
client,
table: table.into(),
row_id,
payload: Value::Null,
}
}
pub fn payload(mut self, payload: Value) -> Self {
self.payload = payload;
self
}
pub async fn execute(self) -> Result<QueryResult, BackendError> {
self.client.execute_update(self).await
}
pub(crate) fn into_parts(self) -> UpdateQuery {
UpdateQuery {
table: self.table,
row_id: self.row_id,
payload: self.payload,
}
}
}
pub(crate) struct UpdateQuery {
pub table: String,
pub row_id: Option<String>,
pub payload: Value,
}
pub struct DeleteBuilder<'a> {
client: &'a AthenaClient,
table: String,
row_id: Option<String>,
}
impl<'a> DeleteBuilder<'a> {
pub(crate) fn new(
client: &'a AthenaClient,
table: impl Into<String>,
row_id: Option<String>,
) -> Self {
Self {
client,
table: table.into(),
row_id,
}
}
pub async fn execute(self) -> Result<QueryResult, BackendError> {
self.client.execute_delete(self).await
}
pub(crate) fn into_parts(self) -> DeleteQuery {
DeleteQuery {
table: self.table,
row_id: self.row_id,
}
}
}
pub(crate) struct DeleteQuery {
pub table: String,
pub row_id: Option<String>,
}