1use serde::{Deserialize, Serialize};
5use serde_json::{Map, Value};
6
7pub use crate::options::OptionField;
8use crate::{Kind, PluginId};
9
10#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
15pub struct Envelope<T> {
16 #[serde(default, skip_serializing_if = "Option::is_none")]
17 pub id: Option<u64>,
18 #[serde(flatten)]
19 pub body: T,
20}
21
22impl<T> Envelope<T> {
23 pub fn new(id: Option<u64>, body: T) -> Envelope<T> {
24 Envelope { id, body }
25 }
26}
27
28#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
30#[serde(tag = "type", rename_all = "snake_case")]
31pub enum Request {
32 Hello {
34 min_version: u32,
35 max_version: u32,
36 core_version: String,
37 #[serde(default, skip_serializing_if = "Option::is_none")]
40 plugin: Option<PluginId>,
41 },
42 Describe {},
45 Validate {
48 options: Map<String, Value>,
49 },
50 ValidateConnection {
55 connection: Map<String, Value>,
56 #[serde(default, skip_serializing_if = "Vec::is_empty")]
57 unresolved: Vec<String>,
58 },
59 Open {
61 connection: Map<String, Value>,
62 read_only: bool,
63 },
64 Execute {
67 sql: String,
68 #[serde(default, skip_serializing_if = "Option::is_none")]
69 row_limit: Option<u64>,
70 },
71 Check {
73 sql: String,
74 },
75 Write {
78 path: String,
79 format: String,
80 options: Map<String, Value>,
81 result_sets: Vec<ResultSetMeta>,
82 #[serde(default, skip_serializing_if = "Option::is_none")]
83 template: Option<Value>,
84 },
85 ResultSetEnd {},
86 Finish {},
87 Deliver {
93 #[serde(default, skip_serializing_if = "Option::is_none")]
94 local_path: Option<String>,
95 #[serde(default, skip_serializing_if = "Option::is_none")]
96 remote_path: Option<String>,
97 #[serde(default, skip_serializing_if = "Vec::is_empty")]
98 files: Vec<DeliveryFile>,
99 connection: Map<String, Value>,
100 #[serde(default)]
101 options: Map<String, Value>,
102 #[serde(default, skip_serializing_if = "Option::is_none")]
103 message: Option<Message>,
104 },
105 Load {
109 name: String,
110 },
111 Close {},
113 Cancel {},
117}
118
119#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
121#[serde(tag = "type", rename_all = "snake_case")]
122pub enum Response {
123 Hello {
124 protocol_version: u32,
125 kind: Kind,
126 name: String,
127 version: String,
128 #[serde(default)]
129 capabilities: Vec<String>,
130 #[serde(default, skip_serializing_if = "Vec::is_empty")]
132 provides: Vec<PluginId>,
133 },
134 VersionMismatch {
135 min_version: u32,
136 max_version: u32,
137 },
138 Describe {
139 connection_fields: Vec<ConnectionField>,
140 #[serde(default, skip_serializing_if = "Vec::is_empty")]
141 option_fields: Vec<OptionField>,
142 #[serde(default, skip_serializing_if = "Option::is_none")]
146 identifier_quote: Option<String>,
147 #[serde(default, skip_serializing_if = "Option::is_none")]
150 message_limit: Option<u64>,
151 },
152 Validated {
154 errors: Vec<String>,
155 #[serde(default, skip_serializing_if = "Vec::is_empty")]
157 warnings: Vec<String>,
158 },
159 Ok {},
160 Result {
162 columns: Vec<String>,
163 },
164 ResultEnd {
165 rows: u64,
166 },
167 NoResult {
168 #[serde(default, skip_serializing_if = "Option::is_none")]
169 rows_affected: Option<u64>,
170 },
171 Written {
172 files: Vec<String>,
173 #[serde(default, skip_serializing_if = "Vec::is_empty")]
175 warnings: Vec<String>,
176 },
177 Delivered {
178 location: String,
179 #[serde(default, skip_serializing_if = "Option::is_none")]
181 attempts: Option<u32>,
182 },
183 Loaded {
186 relation: String,
187 rows: u64,
188 #[serde(default, skip_serializing_if = "Option::is_none")]
189 warning: Option<String>,
190 },
191 Error {
196 message: String,
197 #[serde(default, skip_serializing_if = "Option::is_none")]
198 kind: Option<String>,
199 #[serde(default, skip_serializing_if = "Option::is_none")]
200 code: Option<String>,
201 },
202 Log {
204 level: LogLevel,
205 message: String,
206 #[serde(default, skip_serializing_if = "Map::is_empty")]
208 fields: Map<String, Value>,
209 },
210 Progress {
212 #[serde(default, skip_serializing_if = "Option::is_none")]
213 message: Option<String>,
214 #[serde(default, skip_serializing_if = "Option::is_none")]
215 done: Option<u64>,
216 #[serde(default, skip_serializing_if = "Option::is_none")]
217 total: Option<u64>,
218 },
219}
220
221impl Response {
222 pub fn error(message: impl Into<String>) -> Response {
224 Response::Error {
225 message: message.into(),
226 kind: None,
227 code: None,
228 }
229 }
230}
231
232pub const ERROR_KINDS: &[&str] = &[
234 "config",
235 "plugin",
236 "refused",
237 "connection",
238 "auth",
239 "query",
240 "delivery",
241 "internal",
242 "cancelled",
243 "timed_out",
244];
245
246#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
249#[serde(rename_all = "lowercase")]
250pub enum LogLevel {
251 Error,
252 Warn,
253 Info,
254 Debug,
255 Trace,
256}
257
258#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
260pub struct Message {
261 pub title: String,
263 pub text: String,
265 #[serde(default, skip_serializing_if = "Option::is_none")]
268 pub html: Option<String>,
269 pub path: String,
271}
272
273#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
275pub struct DeliveryFile {
276 pub local_path: String,
277 #[serde(default, skip_serializing_if = "Option::is_none")]
278 pub remote_path: Option<String>,
279}
280
281#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
283pub struct ResultSetMeta {
284 pub name: String,
286 pub query: String,
288 pub result_index: usize,
290 #[serde(default, skip_serializing_if = "Option::is_none")]
291 pub anchor: Option<String>,
292 #[serde(default, skip_serializing_if = "Option::is_none")]
293 pub header: Option<bool>,
294 #[serde(default, skip_serializing_if = "std::collections::BTreeMap::is_empty")]
296 pub columns: std::collections::BTreeMap<String, ColumnOptions>,
297 #[serde(default, skip_serializing_if = "Option::is_none")]
300 pub autofit: Option<bool>,
301 #[serde(default, skip_serializing_if = "Option::is_none")]
303 pub style: Option<crate::style::SheetStyle>,
304}
305
306#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
308pub struct ColumnOptions {
309 #[serde(default, skip_serializing_if = "Option::is_none")]
311 pub format: Option<String>,
312 #[serde(default, skip_serializing_if = "Option::is_none")]
315 pub formula: Option<String>,
316 #[serde(default, skip_serializing_if = "Option::is_none")]
319 pub total: Option<String>,
320 #[serde(default, skip_serializing_if = "Option::is_none")]
322 pub width: Option<ColumnWidth>,
323 #[serde(default, skip_serializing_if = "Option::is_none")]
325 pub style: Option<crate::style::CellStyle>,
326}
327
328#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
330#[serde(untagged)]
331pub enum ColumnWidth {
332 Chars(f64),
333 Auto(AutoWidth),
334}
335
336#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
338#[serde(rename_all = "lowercase")]
339pub enum AutoWidth {
340 Auto,
341}
342
343#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
344pub struct ConnectionField {
345 pub name: String,
346 #[serde(default)]
347 pub description: String,
348 #[serde(default)]
349 pub required: bool,
350 #[serde(default)]
352 pub secret: bool,
353 #[serde(default, skip_serializing_if = "Option::is_none")]
354 pub default: Option<Value>,
355 #[serde(default, skip_serializing_if = "Option::is_none")]
358 pub same_as_source: Option<String>,
359 #[serde(default, skip_serializing_if = "std::ops::Not::not")]
362 pub manual: bool,
363 #[serde(default, skip_serializing_if = "Option::is_none")]
365 pub kind: Option<FieldKind>,
366 #[serde(default, skip_serializing_if = "Vec::is_empty")]
368 pub choices: Vec<String>,
369}
370
371#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
373#[serde(rename_all = "snake_case")]
374pub enum FieldKind {
375 String,
376 Integer,
378 Boolean,
379 Path,
381 Duration,
383 Map,
385}
386
387impl ConnectionField {
388 pub fn new(name: &str, description: &str) -> Self {
389 ConnectionField {
390 name: name.into(),
391 description: description.into(),
392 required: false,
393 secret: false,
394 default: None,
395 same_as_source: None,
396 manual: false,
397 kind: None,
398 choices: Vec::new(),
399 }
400 }
401 pub fn kind(mut self, kind: FieldKind) -> Self {
402 self.kind = Some(kind);
403 self
404 }
405 pub fn choices(mut self, choices: &[&str]) -> Self {
406 self.choices = choices.iter().map(|c| c.to_string()).collect();
407 self.kind.get_or_insert(FieldKind::String);
408 self
409 }
410 pub fn required(mut self) -> Self {
411 self.required = true;
412 self
413 }
414 pub fn secret(mut self) -> Self {
415 self.secret = true;
416 self
417 }
418 pub fn default(mut self, v: impl Into<Value>) -> Self {
419 self.default = Some(v.into());
420 self
421 }
422 pub fn same_as_source(mut self, source_type: &str) -> Self {
423 self.same_as_source = Some(source_type.into());
424 self
425 }
426 pub fn manual(mut self) -> Self {
427 self.manual = true;
428 self
429 }
430}