use crate::filter::FilterValue;
pub type CreatePayload = Vec<(String, FilterValue)>;
pub type UpdatePayload = Vec<(String, WriteOp)>;
#[derive(Debug, Clone, PartialEq)]
pub enum WriteOp {
Set(FilterValue),
Increment(FilterValue),
Decrement(FilterValue),
Multiply(FilterValue),
Divide(FilterValue),
Unset,
}
impl WriteOp {
pub fn is_arithmetic(&self) -> bool {
matches!(
self,
WriteOp::Increment(_)
| WriteOp::Decrement(_)
| WriteOp::Multiply(_)
| WriteOp::Divide(_)
)
}
pub fn to_set_fragment(
&self,
column: &str,
placeholder: &str,
) -> (String, Option<FilterValue>) {
match self {
WriteOp::Set(v) => (format!("{column} = {placeholder}"), Some(v.clone())),
WriteOp::Increment(v) => (
format!("{column} = {column} + {placeholder}"),
Some(v.clone()),
),
WriteOp::Decrement(v) => (
format!("{column} = {column} - {placeholder}"),
Some(v.clone()),
),
WriteOp::Multiply(v) => (
format!("{column} = {column} * {placeholder}"),
Some(v.clone()),
),
WriteOp::Divide(v) => (
format!("{column} = {column} / {placeholder}"),
Some(v.clone()),
),
WriteOp::Unset => (format!("{column} = NULL"), None),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn write_op_set_fragment() {
let op = WriteOp::Set(FilterValue::Int(7));
let (frag, val) = op.to_set_fragment("age", "$1");
assert_eq!(frag, "age = $1");
assert_eq!(val, Some(FilterValue::Int(7)));
}
#[test]
fn write_op_increment_fragment() {
let op = WriteOp::Increment(FilterValue::Int(1));
let (frag, val) = op.to_set_fragment("count", "$2");
assert_eq!(frag, "count = count + $2");
assert_eq!(val, Some(FilterValue::Int(1)));
}
#[test]
fn write_op_unset_skips_param() {
let op = WriteOp::Unset;
let (frag, val) = op.to_set_fragment("name", "$1");
assert_eq!(frag, "name = NULL");
assert!(val.is_none());
}
#[test]
fn write_op_is_arithmetic() {
assert!(WriteOp::Increment(FilterValue::Int(1)).is_arithmetic());
assert!(WriteOp::Decrement(FilterValue::Int(1)).is_arithmetic());
assert!(WriteOp::Multiply(FilterValue::Int(1)).is_arithmetic());
assert!(WriteOp::Divide(FilterValue::Int(1)).is_arithmetic());
assert!(!WriteOp::Set(FilterValue::Int(1)).is_arithmetic());
assert!(!WriteOp::Unset.is_arithmetic());
}
}