uqa_client/
sql_stream_frame.rs1use std::collections::BTreeMap;
8use std::fmt;
9
10use serde::{Deserialize, Serialize};
11use uqa_core::Value;
12
13#[derive(Clone, Deserialize, PartialEq, Serialize)]
15#[serde(tag = "type", rename_all = "snake_case")]
16pub enum SQLStreamFrame {
17 Metadata {
18 columns: Vec<String>,
19 row_count: usize,
20 spilled_to_disk: bool,
21 request_id: String,
22 },
23 Row {
24 row: BTreeMap<String, Value>,
25 },
26 Complete {
27 row_count: usize,
28 request_id: String,
29 },
30 Error {
31 code: String,
32 message: String,
33 request_id: String,
34 #[serde(
35 default,
36 deserialize_with = "deserialize_diagnostic",
37 skip_serializing_if = "Option::is_none"
38 )]
39 diagnostic: Option<crate::SQLDiagnostic>,
40 },
41}
42
43fn deserialize_diagnostic<'de, D: serde::Deserializer<'de>>(
44 deserializer: D,
45) -> Result<Option<crate::SQLDiagnostic>, D::Error> {
46 let value = Option::<serde_json::Value>::deserialize(deserializer)?;
47 Ok(value.and_then(|value| serde_json::from_value(value).ok()))
48}
49
50impl SQLStreamFrame {
51 pub fn request_id(&self) -> Option<&str> {
52 match self {
53 Self::Metadata { request_id, .. }
54 | Self::Complete { request_id, .. }
55 | Self::Error { request_id, .. } => Some(request_id),
56 Self::Row { .. } => None,
57 }
58 }
59
60 pub const fn is_terminal(&self) -> bool {
61 matches!(self, Self::Complete { .. } | Self::Error { .. })
62 }
63}
64
65impl fmt::Debug for SQLStreamFrame {
66 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
67 formatter.write_str("SQLStreamFrame([REDACTED])")
68 }
69}