1use serde::{Deserialize, Serialize};
4use serde_json::{Map, Value};
5
6pub use crate::options::OptionField;
7use crate::{Kind, PluginId};
8
9#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
11#[serde(tag = "type", rename_all = "snake_case")]
12pub enum Request {
13 Hello {
15 min_version: u32,
16 max_version: u32,
17 core_version: String,
18 #[serde(default, skip_serializing_if = "Option::is_none")]
21 plugin: Option<PluginId>,
22 },
23 Describe {},
26 Validate {
29 options: Map<String, Value>,
30 },
31 Open {
33 connection: Map<String, Value>,
34 read_only: bool,
35 },
36 Execute {
39 sql: String,
40 #[serde(default, skip_serializing_if = "Option::is_none")]
41 row_limit: Option<u64>,
42 },
43 Check {
45 sql: String,
46 },
47 Write {
50 path: String,
51 format: String,
52 options: Map<String, Value>,
53 result_sets: Vec<ResultSetMeta>,
54 #[serde(default, skip_serializing_if = "Option::is_none")]
55 template: Option<Value>,
56 },
57 ResultSetEnd {},
58 Finish {},
59 Deliver {
65 #[serde(default, skip_serializing_if = "Option::is_none")]
66 local_path: Option<String>,
67 #[serde(default, skip_serializing_if = "Option::is_none")]
68 remote_path: Option<String>,
69 #[serde(default, skip_serializing_if = "Vec::is_empty")]
70 files: Vec<DeliveryFile>,
71 connection: Map<String, Value>,
72 #[serde(default)]
73 options: Map<String, Value>,
74 #[serde(default, skip_serializing_if = "Option::is_none")]
75 message: Option<Message>,
76 },
77 Load {
81 name: String,
82 },
83 Close {},
85}
86
87#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
89#[serde(tag = "type", rename_all = "snake_case")]
90pub enum Response {
91 Hello {
92 protocol_version: u32,
93 kind: Kind,
94 name: String,
95 version: String,
96 #[serde(default)]
97 capabilities: Vec<String>,
98 #[serde(default, skip_serializing_if = "Vec::is_empty")]
100 provides: Vec<PluginId>,
101 },
102 VersionMismatch {
103 min_version: u32,
104 max_version: u32,
105 },
106 Describe {
107 connection_fields: Vec<ConnectionField>,
108 #[serde(default, skip_serializing_if = "Vec::is_empty")]
109 option_fields: Vec<OptionField>,
110 #[serde(default, skip_serializing_if = "Option::is_none")]
114 identifier_quote: Option<String>,
115 #[serde(default, skip_serializing_if = "Option::is_none")]
118 message_limit: Option<u64>,
119 },
120 Validated {
122 errors: Vec<String>,
123 },
124 Ok {},
125 Result {
127 columns: Vec<String>,
128 },
129 ResultEnd {
130 rows: u64,
131 },
132 NoResult {
133 #[serde(default, skip_serializing_if = "Option::is_none")]
134 rows_affected: Option<u64>,
135 },
136 Written {
137 files: Vec<String>,
138 #[serde(default, skip_serializing_if = "Vec::is_empty")]
140 warnings: Vec<String>,
141 },
142 Delivered {
143 location: String,
144 },
145 Loaded {
148 relation: String,
149 rows: u64,
150 #[serde(default, skip_serializing_if = "Option::is_none")]
151 warning: Option<String>,
152 },
153 Error {
154 message: String,
155 },
156}
157
158#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
160pub struct Message {
161 pub title: String,
163 pub text: String,
165 #[serde(default, skip_serializing_if = "Option::is_none")]
168 pub html: Option<String>,
169 pub path: String,
171}
172
173#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
175pub struct DeliveryFile {
176 pub local_path: String,
177 #[serde(default, skip_serializing_if = "Option::is_none")]
178 pub remote_path: Option<String>,
179}
180
181#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
183pub struct ResultSetMeta {
184 pub name: String,
186 pub query: String,
188 pub result_index: usize,
190 #[serde(default, skip_serializing_if = "Option::is_none")]
191 pub anchor: Option<String>,
192 #[serde(default, skip_serializing_if = "Option::is_none")]
193 pub header: Option<bool>,
194 #[serde(default, skip_serializing_if = "std::collections::BTreeMap::is_empty")]
196 pub columns: std::collections::BTreeMap<String, ColumnOptions>,
197}
198
199#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
201pub struct ColumnOptions {
202 #[serde(default, skip_serializing_if = "Option::is_none")]
204 pub format: Option<String>,
205 #[serde(default, skip_serializing_if = "Option::is_none")]
208 pub formula: Option<String>,
209 #[serde(default, skip_serializing_if = "Option::is_none")]
212 pub total: Option<String>,
213}
214
215#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
216pub struct ConnectionField {
217 pub name: String,
218 #[serde(default)]
219 pub description: String,
220 #[serde(default)]
221 pub required: bool,
222 #[serde(default)]
224 pub secret: bool,
225 #[serde(default, skip_serializing_if = "Option::is_none")]
226 pub default: Option<Value>,
227 #[serde(default, skip_serializing_if = "Option::is_none")]
230 pub same_as_source: Option<String>,
231 #[serde(default, skip_serializing_if = "std::ops::Not::not")]
234 pub manual: bool,
235}
236
237impl ConnectionField {
238 pub fn new(name: &str, description: &str) -> Self {
239 ConnectionField {
240 name: name.into(),
241 description: description.into(),
242 required: false,
243 secret: false,
244 default: None,
245 same_as_source: None,
246 manual: false,
247 }
248 }
249 pub fn required(mut self) -> Self {
250 self.required = true;
251 self
252 }
253 pub fn secret(mut self) -> Self {
254 self.secret = true;
255 self
256 }
257 pub fn default(mut self, v: impl Into<Value>) -> Self {
258 self.default = Some(v.into());
259 self
260 }
261 pub fn same_as_source(mut self, source_type: &str) -> Self {
262 self.same_as_source = Some(source_type.into());
263 self
264 }
265 pub fn manual(mut self) -> Self {
266 self.manual = true;
267 self
268 }
269}