1use serde::{Deserialize, Serialize};
6
7use crate::value::Value;
8
9use super::auth::AuthResponse;
10use super::opcodes::ResponseStatus;
11use super::request_fields::RequestFields;
12
13#[derive(Debug, Clone, Serialize, Deserialize)]
20pub struct NativeRequest {
21 pub op: super::opcodes::OpCode,
23 pub seq: u64,
25 #[serde(flatten)]
27 pub fields: RequestFields,
28}
29
30impl zerompk::ToMessagePack for NativeRequest {
31 fn write<W: zerompk::Write>(&self, writer: &mut W) -> zerompk::Result<()> {
32 writer.write_array_len(3)?;
33 self.op.write(writer)?;
34 writer.write_u64(self.seq)?;
35 self.fields.write(writer)
36 }
37}
38
39impl<'a> zerompk::FromMessagePack<'a> for NativeRequest {
40 fn read<R: zerompk::Read<'a>>(reader: &mut R) -> zerompk::Result<Self> {
41 let len = reader.read_array_len()?;
42 if len != 3 {
43 return Err(zerompk::Error::ArrayLengthMismatch {
44 expected: 3,
45 actual: len,
46 });
47 }
48 let op = super::opcodes::OpCode::read(reader)?;
49 let seq = reader.read_u64()?;
50 let fields = RequestFields::read(reader)?;
51 Ok(Self { op, seq, fields })
52 }
53}
54
55#[derive(
59 Debug, Clone, Serialize, Deserialize, zerompk::ToMessagePack, zerompk::FromMessagePack,
60)]
61#[msgpack(map)]
62pub struct NativeResponse {
63 pub seq: u64,
65 pub status: ResponseStatus,
67 #[serde(skip_serializing_if = "Option::is_none")]
69 pub columns: Option<Vec<String>>,
70 #[serde(skip_serializing_if = "Option::is_none")]
72 pub rows: Option<Vec<Vec<Value>>>,
73 #[serde(skip_serializing_if = "Option::is_none")]
75 pub rows_affected: Option<u64>,
76 pub watermark_lsn: u64,
78 #[serde(skip_serializing_if = "Option::is_none")]
80 pub error: Option<ErrorPayload>,
81 #[serde(skip_serializing_if = "Option::is_none")]
83 pub auth: Option<AuthResponse>,
84 #[serde(default, skip_serializing_if = "Vec::is_empty")]
88 #[msgpack(default)]
89 pub warnings: Vec<String>,
90}
91
92#[derive(
94 Debug, Clone, Serialize, Deserialize, zerompk::ToMessagePack, zerompk::FromMessagePack,
95)]
96pub struct ErrorPayload {
97 pub code: String,
99 pub message: String,
101}
102
103impl NativeResponse {
104 pub fn ok(seq: u64) -> Self {
106 Self {
107 seq,
108 status: ResponseStatus::Ok,
109 columns: None,
110 rows: None,
111 rows_affected: None,
112 watermark_lsn: 0,
113 error: None,
114 auth: None,
115 warnings: Vec::new(),
116 }
117 }
118
119 pub fn from_query_result(seq: u64, qr: crate::result::QueryResult, lsn: u64) -> Self {
121 Self {
122 seq,
123 status: ResponseStatus::Ok,
124 columns: Some(qr.columns),
125 rows: Some(qr.rows),
126 rows_affected: Some(qr.rows_affected),
127 watermark_lsn: lsn,
128 error: None,
129 auth: None,
130 warnings: Vec::new(),
131 }
132 }
133
134 pub fn error(seq: u64, code: impl Into<String>, message: impl Into<String>) -> Self {
136 Self {
137 seq,
138 status: ResponseStatus::Error,
139 columns: None,
140 rows: None,
141 rows_affected: None,
142 watermark_lsn: 0,
143 error: Some(ErrorPayload {
144 code: code.into(),
145 message: message.into(),
146 }),
147 auth: None,
148 warnings: Vec::new(),
149 }
150 }
151
152 pub fn auth_ok(seq: u64, username: String, tenant_id: u64) -> Self {
154 Self {
155 seq,
156 status: ResponseStatus::Ok,
157 columns: None,
158 rows: None,
159 rows_affected: None,
160 watermark_lsn: 0,
161 error: None,
162 auth: Some(AuthResponse {
163 username,
164 tenant_id,
165 }),
166 warnings: Vec::new(),
167 }
168 }
169
170 pub fn status_row(seq: u64, message: impl Into<String>) -> Self {
172 Self {
173 seq,
174 status: ResponseStatus::Ok,
175 columns: Some(vec!["status".into()]),
176 rows: Some(vec![vec![Value::String(message.into())]]),
177 rows_affected: Some(1),
178 watermark_lsn: 0,
179 error: None,
180 auth: None,
181 warnings: Vec::new(),
182 }
183 }
184}