use std::collections::BTreeMap;
use std::fmt;
use serde::{Deserialize, Serialize};
use uqa_core::Value;
#[derive(Clone, Deserialize, PartialEq, Serialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum SQLStreamFrame {
Metadata {
columns: Vec<String>,
row_count: usize,
spilled_to_disk: bool,
request_id: String,
},
Row {
row: BTreeMap<String, Value>,
},
Complete {
row_count: usize,
request_id: String,
},
Error {
code: String,
message: String,
request_id: String,
#[serde(
default,
deserialize_with = "deserialize_diagnostic",
skip_serializing_if = "Option::is_none"
)]
diagnostic: Option<crate::SQLDiagnostic>,
},
}
fn deserialize_diagnostic<'de, D: serde::Deserializer<'de>>(
deserializer: D,
) -> Result<Option<crate::SQLDiagnostic>, D::Error> {
let value = Option::<serde_json::Value>::deserialize(deserializer)?;
Ok(value.and_then(|value| serde_json::from_value(value).ok()))
}
impl SQLStreamFrame {
pub fn request_id(&self) -> Option<&str> {
match self {
Self::Metadata { request_id, .. }
| Self::Complete { request_id, .. }
| Self::Error { request_id, .. } => Some(request_id),
Self::Row { .. } => None,
}
}
pub const fn is_terminal(&self) -> bool {
matches!(self, Self::Complete { .. } | Self::Error { .. })
}
}
impl fmt::Debug for SQLStreamFrame {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("SQLStreamFrame([REDACTED])")
}
}