use serde::{Deserialize, Serialize};
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum VectorExpr {
Literal(Vec<f32>),
Parameter(String),
}
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Value {
Integer(i64),
UnsignedInteger(u64),
Float(f64),
String(String),
Boolean(bool),
Null,
Parameter(String),
Temporal(TemporalExpr),
Subquery(Box<Subquery>),
}
impl From<i64> for Value {
fn from(v: i64) -> Self {
Self::Integer(v)
}
}
impl From<u64> for Value {
fn from(v: u64) -> Self {
Self::UnsignedInteger(v)
}
}
impl From<f64> for Value {
fn from(v: f64) -> Self {
Self::Float(v)
}
}
impl From<&str> for Value {
fn from(v: &str) -> Self {
Self::String(v.to_string())
}
}
impl From<String> for Value {
fn from(v: String) -> Self {
Self::String(v)
}
}
impl From<bool> for Value {
fn from(v: bool) -> Self {
Self::Boolean(v)
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Subquery {
pub select: super::select::SelectStatement,
#[serde(default)]
pub correlations: Vec<CorrelatedColumn>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct CorrelatedColumn {
pub outer_table: String,
pub outer_column: String,
pub inner_column: String,
}
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum TemporalExpr {
Now,
Interval(IntervalValue),
Subtract(Box<TemporalExpr>, Box<TemporalExpr>),
Add(Box<TemporalExpr>, Box<TemporalExpr>),
}
impl TemporalExpr {
#[must_use]
pub fn to_epoch_seconds(&self) -> i64 {
use std::time::{SystemTime, UNIX_EPOCH};
let now = SystemTime::now()
.duration_since(UNIX_EPOCH)
.map_or(0, |d| i64::try_from(d.as_secs()).unwrap_or(i64::MAX));
match self {
Self::Now => now,
Self::Interval(iv) => iv.to_seconds(),
Self::Subtract(left, right) => left.to_epoch_seconds() - right.to_epoch_seconds(),
Self::Add(left, right) => left.to_epoch_seconds() + right.to_epoch_seconds(),
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct IntervalValue {
pub magnitude: i64,
pub unit: IntervalUnit,
}
impl IntervalValue {
#[must_use]
pub fn to_seconds(&self) -> i64 {
match self.unit {
IntervalUnit::Seconds => self.magnitude,
IntervalUnit::Minutes => self.magnitude * 60,
IntervalUnit::Hours => self.magnitude * 3600,
IntervalUnit::Days => self.magnitude * 86400,
IntervalUnit::Weeks => self.magnitude * 604_800,
IntervalUnit::Months => self.magnitude * 2_592_000,
}
}
}
impl Value {
#[must_use]
pub fn to_json(&self) -> serde_json::Value {
match self {
Self::Integer(i) => serde_json::json!(i),
Self::UnsignedInteger(u) => serde_json::json!(u),
Self::Float(f) => serde_json::json!(f),
Self::String(s) => serde_json::json!(s),
Self::Boolean(b) => serde_json::json!(b),
Self::Parameter(p) => serde_json::json!(format!("${p}")),
Self::Temporal(t) => serde_json::json!(t.to_epoch_seconds()),
Self::Null | Self::Subquery(_) => serde_json::Value::Null,
}
}
}
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum IntervalUnit {
Seconds,
Minutes,
Hours,
Days,
Weeks,
Months,
}