1use std::collections::HashMap;
14
15use indexmap::IndexMap;
16use prost::Message as ProstMessage;
17use prost::bytes::{Bytes, BytesMut};
18
19use super::data::RowPathStyle;
20use super::error::VirtualServerError;
21use super::generic_sql_model::{column_path_source, sort_column_paths};
22use super::handler::VirtualServerHandler;
23use crate::config::{ViewConfig, ViewConfigUpdate};
24use crate::proto::response::ClientResp;
25use crate::proto::table_validate_expr_resp::ExprValidationError;
26use crate::proto::{
27 ColumnType, GetFeaturesResp, GetHostedTablesResp, MakeTableResp, Request, Response,
28 ServerError, TableMakePortResp, TableMakeViewResp, TableOnDeleteResp, TableRemoveDeleteResp,
29 TableSchemaResp, TableSizeResp, TableValidateExprResp, ViewColumnPathsResp, ViewDeleteResp,
30 ViewDimensionsResp, ViewExpressionSchemaResp, ViewGetConfigResp, ViewGetMinMaxResp,
31 ViewOnDeleteResp, ViewOnUpdateResp, ViewRemoveDeleteResp, ViewRemoveOnUpdateResp,
32 ViewSchemaResp, ViewToArrowResp, ViewToColumnsStringResp, ViewToCsvResp,
33 ViewToNdjsonStringResp, ViewToRowsStringResp,
34};
35
36macro_rules! respond {
37 ($msg:ident, $name:ident { $($rest:tt)* }) => {{
38 let mut resp = BytesMut::new();
39 let resp2 = ClientResp::$name($name {
40 $($rest)*
41 });
42
43 Response {
44 msg_id: $msg.msg_id,
45 entity_id: $msg.entity_id,
46 client_resp: Some(resp2),
47 }.encode(&mut resp).map_err(VirtualServerError::EncodeError)?;
48
49 resp.freeze()
50 }};
51}
52
53pub struct VirtualServer<T: VirtualServerHandler> {
59 handler: T,
60 view_to_table: IndexMap<String, String>,
61 view_configs: IndexMap<String, ViewConfig>,
62 view_schemas: IndexMap<String, IndexMap<String, ColumnType>>,
63}
64
65impl<T: VirtualServerHandler> VirtualServer<T> {
66 pub fn new(handler: T) -> Self {
68 Self {
69 handler,
70 view_configs: IndexMap::default(),
71 view_to_table: IndexMap::default(),
72 view_schemas: IndexMap::default(),
73 }
74 }
75
76 pub async fn handle_request(
81 &mut self,
82 bytes: Bytes,
83 ) -> Result<Bytes, VirtualServerError<T::Error>> {
84 let msg = Request::decode(bytes).map_err(VirtualServerError::DecodeError)?;
85 tracing::debug!(
86 "Handling request: entity_id={}, req={:?}",
87 msg.entity_id,
88 msg.client_req
89 );
90
91 match self.internal_handle_request(msg.clone()).await {
92 Ok(resp) => Ok(resp),
93 Err(err) => {
94 tracing::error!("{}", err);
95 Ok(respond!(msg, ServerError {
96 message: err.to_string(),
97 status_code: 0
98 }))
99 },
100 }
101 }
102
103 async fn get_cached_view_schema(
104 &mut self,
105 entity_id: &str,
106 to_psp_format: bool,
107 ) -> Result<IndexMap<String, ColumnType>, VirtualServerError<T::Error>> {
108 if !self.view_schemas.contains_key(entity_id) {
109 self.view_schemas.insert(
110 entity_id.to_string(),
111 self.handler
112 .view_schema(entity_id, self.view_configs.get(entity_id).unwrap())
113 .await?,
114 );
115 }
116
117 if to_psp_format {
118 let config = self.view_configs.get(entity_id).unwrap();
122 Ok(self
123 .view_schemas
124 .get(entity_id)
125 .unwrap()
126 .iter()
127 .map(|(k, v)| {
128 let name = column_path_source(k, config)
129 .map(|(_, col)| col.to_string())
130 .unwrap_or_else(|| k.clone());
131
132 (name, *v)
133 })
134 .collect())
135 } else {
136 Ok(self.view_schemas.get(entity_id).cloned().unwrap())
137 }
138 }
139
140 async fn internal_handle_request(
141 &mut self,
142 msg: Request,
143 ) -> Result<Bytes, VirtualServerError<T::Error>> {
144 use crate::proto::request::ClientReq::*;
145 let resp = match msg.client_req.unwrap() {
146 GetFeaturesReq(_) => {
147 let features = self.handler.get_features().await?;
148 respond!(msg, GetFeaturesResp { ..features.into() })
149 },
150 GetHostedTablesReq(_) => {
151 respond!(msg, GetHostedTablesResp {
152 table_infos: self.handler.get_hosted_tables().await?
153 })
154 },
155 TableSchemaReq(_) => {
156 respond!(msg, TableSchemaResp {
157 schema: Some(crate::proto::Schema {
158 schema: self
159 .handler
160 .table_schema(msg.entity_id.as_str())
161 .await?
162 .iter()
163 .map(|x| crate::proto::schema::KeyTypePair {
164 name: x.0.to_string(),
165 r#type: *x.1 as i32,
166 })
167 .collect()
168 })
169 })
170 },
171 TableMakePortReq(req) => {
172 respond!(msg, TableMakePortResp {
173 port_id: self.handler.table_make_port(&req).await?
174 })
175 },
176 TableMakeViewReq(req) => {
177 self.view_to_table
178 .insert(req.view_id.clone(), msg.entity_id.clone());
179
180 let mut config: ViewConfigUpdate = req.config.clone().unwrap_or_default().into();
181
182 if let Some(windows) = &config.windows
185 && windows.values().any(|w| w.order_by.is_none())
186 && self.handler.get_features().await?.unordered
187 {
188 return Err(VirtualServerError::Other(
189 "This data store is unordered - windows require an explicit `order_by`"
190 .to_string(),
191 ));
192 }
193
194 let bytes = respond!(msg, TableMakeViewResp {
195 view_id: self
196 .handler
197 .table_make_view(msg.entity_id.as_str(), req.view_id.as_str(), &mut config)
198 .await?
199 });
200
201 self.view_configs.insert(req.view_id.clone(), config.into());
202 bytes
203 },
204 TableSizeReq(_) => {
205 respond!(msg, TableSizeResp {
206 size: self.handler.table_size(msg.entity_id.as_str()).await?
207 })
208 },
209 TableValidateExprReq(req) => {
210 let mut expression_schema = HashMap::<String, i32>::default();
211 let mut expression_alias = HashMap::<String, String>::default();
212 let mut errors = HashMap::<String, ExprValidationError>::default();
213 for (name, ex) in req.column_to_expr.iter() {
214 let _ = expression_alias.insert(name.clone(), ex.clone());
215 match self
216 .handler
217 .table_validate_expression(&msg.entity_id, ex.as_str())
218 .await
219 {
220 Ok(dtype) => {
221 let _ = expression_schema.insert(name.clone(), dtype as i32);
222 },
223 Err(e) => {
224 let _ = errors.insert(name.clone(), ExprValidationError {
225 error_message: format!("{}", e),
226 line: 0,
227 column: 0,
228 });
229 },
230 }
231 }
232
233 respond!(msg, TableValidateExprResp {
234 expression_schema,
235 errors,
236 expression_alias,
237 })
238 },
239 ViewSchemaReq(_) => {
240 respond!(msg, ViewSchemaResp {
241 schema: self
242 .get_cached_view_schema(&msg.entity_id, true)
243 .await?
244 .into_iter()
245 .map(|(x, y)| (x.to_string(), y as i32))
246 .collect()
247 })
248 },
249 ViewDimensionsReq(_) => {
250 let view_id = &msg.entity_id;
251 let table_id = self
252 .view_to_table
253 .get(view_id)
254 .ok_or_else(|| VirtualServerError::UnknownViewId(view_id.to_string()))?;
255
256 let num_table_rows = self.handler.table_size(table_id).await?;
257 let num_table_columns = self.handler.table_column_size(table_id).await? as u32;
258 let config = self.view_configs.get(view_id).unwrap();
259 let num_view_columns = self.handler.view_column_size(view_id, config).await? as u32;
260 let num_view_rows = self.handler.view_size(view_id).await?;
261 let resp = ViewDimensionsResp {
262 num_table_columns,
263 num_table_rows,
264 num_view_columns,
265 num_view_rows,
266 };
267
268 respond!(msg, ViewDimensionsResp { ..resp })
269 },
270 ViewGetConfigReq(_) => {
271 respond!(msg, ViewGetConfigResp {
272 config: Some(
273 ViewConfigUpdate::from(
274 self.view_configs.get(&msg.entity_id).unwrap().clone()
275 )
276 .into()
277 )
278 })
279 },
280 ViewExpressionSchemaReq(_) => {
281 let mut schema = HashMap::<String, i32>::default();
282 let table_id = self.view_to_table.get(&msg.entity_id);
283 for (name, ex) in self
284 .view_configs
285 .get(&msg.entity_id)
286 .unwrap()
287 .expressions
288 .iter()
289 {
290 match self
291 .handler
292 .table_validate_expression(table_id.unwrap(), ex.as_str())
293 .await
294 {
295 Ok(dtype) => {
296 let _ = schema.insert(name.clone(), dtype as i32);
297 },
298 Err(_e) => {
299 },
301 }
302 }
303
304 let resp = ViewExpressionSchemaResp { schema };
305 respond!(msg, ViewExpressionSchemaResp { ..resp })
306 },
307 ViewColumnPathsReq(_) => {
308 let config = self.view_configs.get(&msg.entity_id).unwrap();
309 let mut paths: Vec<String> = self
310 .handler
311 .view_schema(msg.entity_id.as_str(), config)
312 .await?
313 .keys()
314 .cloned()
315 .collect();
316
317 if !config.split_by.is_empty() {
318 sort_column_paths(&mut paths, config);
319 }
320
321 respond!(msg, ViewColumnPathsResp { paths })
322 },
323 ViewToArrowReq(view_to_arrow_req) => {
324 let viewport = view_to_arrow_req.viewport.unwrap();
325 let schema = self.get_cached_view_schema(&msg.entity_id, false).await?;
326 let config = self.view_configs.get(&msg.entity_id).unwrap();
327 let mut cols = self
328 .handler
329 .view_get_data(msg.entity_id.as_str(), config, &schema, &viewport)
330 .await?;
331
332 let arrow = cols
333 .render_to_arrow_ipc()
334 .map_err(|e| VirtualServerError::Other(e.to_string()))?;
335
336 respond!(msg, ViewToArrowResp { arrow })
337 },
338 ViewToCsvReq(view_to_csv_req) => {
339 let viewport = view_to_csv_req.viewport.unwrap();
340 let schema = self.get_cached_view_schema(&msg.entity_id, false).await?;
341 let config = self.view_configs.get(&msg.entity_id).unwrap();
342 let mut cols = self
343 .handler
344 .view_get_data(msg.entity_id.as_str(), config, &schema, &viewport)
345 .await?;
346
347 let rows = cols.render_to_rows(RowPathStyle::PerLevel);
348 let mut csv = String::new();
349 if let Some(first_row) = rows.first() {
350 let headers: Vec<&str> = first_row.keys().map(|k| k.as_str()).collect();
351 csv.push_str(&headers.join(","));
352 csv.push('\n');
353 }
354
355 for row in &rows {
356 let values: Vec<String> = row
357 .values()
358 .map(|cell| serde_json::to_string(cell).unwrap_or_default())
359 .collect();
360 csv.push_str(&values.join(","));
361 csv.push('\n');
362 }
363
364 respond!(msg, ViewToCsvResp { csv })
365 },
366 ViewToNdjsonStringReq(view_to_ndjson_req) => {
367 let viewport = view_to_ndjson_req.viewport.unwrap();
368 let schema = self.get_cached_view_schema(&msg.entity_id, false).await?;
369 let config = self.view_configs.get(&msg.entity_id).unwrap();
370 let mut cols = self
371 .handler
372 .view_get_data(msg.entity_id.as_str(), config, &schema, &viewport)
373 .await?;
374
375 let rows = cols.render_to_rows(RowPathStyle::PerLevel);
376 let ndjson_string = rows
377 .iter()
378 .map(serde_json::to_string)
379 .collect::<Result<Vec<_>, _>>()
380 .map_err(|e| VirtualServerError::InvalidJSON(std::sync::Arc::new(e)))?
381 .join("\n");
382
383 respond!(msg, ViewToNdjsonStringResp { ndjson_string })
384 },
385 ViewToRowsStringReq(view_to_rows_string_req) => {
386 let viewport = view_to_rows_string_req.viewport.unwrap();
387 let schema = self.get_cached_view_schema(&msg.entity_id, false).await?;
388 let config = self.view_configs.get(&msg.entity_id).unwrap();
389 let mut cols = self
390 .handler
391 .view_get_data(msg.entity_id.as_str(), config, &schema, &viewport)
392 .await?;
393
394 let rows = cols.render_to_rows(RowPathStyle::Sidecar);
395 let json_string = serde_json::to_string(&rows)
396 .map_err(|e| VirtualServerError::InvalidJSON(std::sync::Arc::new(e)))?;
397
398 respond!(msg, ViewToRowsStringResp { json_string })
399 },
400 ViewToColumnsStringReq(view_to_columns_string_req) => {
401 let viewport = view_to_columns_string_req.viewport.unwrap();
402 let schema = self.get_cached_view_schema(&msg.entity_id, false).await?;
403 let config = self.view_configs.get(&msg.entity_id).unwrap();
404 let mut cols = self
405 .handler
406 .view_get_data(msg.entity_id.as_str(), config, &schema, &viewport)
407 .await?;
408
409 let json_string = cols
410 .render_to_columns_json(
411 RowPathStyle::Sidecar,
412 view_to_columns_string_req.id.unwrap_or_default(),
413 )
414 .map_err(|e| VirtualServerError::Other(e.to_string()))?;
415
416 respond!(msg, ViewToColumnsStringResp { json_string })
417 },
418 ViewDeleteReq(_) => {
419 self.handler.view_delete(msg.entity_id.as_str()).await?;
420 self.view_to_table.shift_remove(&msg.entity_id);
421 self.view_configs.shift_remove(&msg.entity_id);
422 respond!(msg, ViewDeleteResp {})
423 },
424 MakeTableReq(req) => {
425 self.handler
426 .make_table(&msg.entity_id, req.data.as_ref().unwrap())
427 .await?;
428 respond!(msg, MakeTableResp {})
429 },
430 ViewGetMinMaxReq(req) => {
431 let config = self.view_configs.get(&msg.entity_id).unwrap();
432 let (min, max) = self
433 .handler
434 .view_get_min_max(&msg.entity_id, &req.column_name, config)
435 .await?;
436 respond!(msg, ViewGetMinMaxResp {
437 min: Some(min.into()),
438 max: Some(max.into()),
439 })
440 },
441
442 TableOnDeleteReq(_) => {
444 respond!(msg, TableOnDeleteResp {})
445 },
446 ViewOnUpdateReq(_) => {
447 respond!(msg, ViewOnUpdateResp {
448 delta: None,
449 port_id: 0
450 })
451 },
452 ViewOnDeleteReq(_) => {
453 respond!(msg, ViewOnDeleteResp {})
454 },
455 ViewRemoveOnUpdateReq(_) => {
456 respond!(msg, ViewRemoveOnUpdateResp {})
457 },
458 TableRemoveDeleteReq(_) => {
459 respond!(msg, TableRemoveDeleteResp {})
460 },
461 ViewRemoveDeleteReq(_) => {
462 respond!(msg, ViewRemoveDeleteResp {})
463 },
464 x => {
465 return Err(VirtualServerError::Other(format!(
467 "Unhandled request: {:?}",
468 x
469 )));
470 },
471 };
472
473 Ok(resp)
474 }
475}