perspective_client/virtual_server/features.rs
1// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
2// ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
3// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
4// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
5// ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
6// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
7// ┃ Copyright (c) 2017, the Perspective Authors. ┃
8// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
9// ┃ This file is part of the Perspective library, distributed under the terms ┃
10// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
11// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
12
13use std::borrow::Cow;
14
15use indexmap::IndexMap;
16use serde::{Deserialize, Serialize};
17
18use crate::config::GroupRollupMode;
19use crate::proto::get_features_resp::{AggregateArgs, AggregateOptions, ColumnTypeOptions};
20use crate::proto::{ColumnType, GetFeaturesResp};
21
22/// Describes the capabilities supported by a virtual server handler.
23///
24/// This struct is returned by
25/// [`VirtualServerHandler::get_features`](super::VirtualServerHandler::get_features)
26/// to inform clients about which operations are available.
27#[derive(Debug, Default, Deserialize, Serialize)]
28pub struct Features<'a> {
29 /// Whether group-by aggregation is supported.
30 #[serde(default)]
31 pub group_by: bool,
32
33 /// Which `group_by_rollup_mode` options are supported
34 #[serde(default)]
35 pub group_rollup_mode: Vec<GroupRollupMode>,
36
37 /// Whether split-by (pivot) operations are supported.
38 #[serde(default)]
39 pub split_by: bool,
40
41 /// Available filter operators per column type.
42 #[serde(default)]
43 pub filter_ops: IndexMap<ColumnType, Vec<Cow<'a, str>>>,
44
45 /// Available aggregate functions per column type.
46 #[serde(default)]
47 pub aggregates: IndexMap<ColumnType, Vec<AggSpec<'a>>>,
48
49 /// Whether sorting is supported.
50 #[serde(default)]
51 pub sort: bool,
52
53 /// Whether computed expressions are supported.
54 #[serde(default)]
55 pub expressions: bool,
56
57 /// Whether update callbacks are supported.
58 #[serde(default)]
59 pub on_update: bool,
60}
61
62/// Specification for an aggregate function.
63///
64/// Aggregates can either take no additional arguments ([`AggSpec::Single`])
65/// or require column type arguments ([`AggSpec::Multiple`]).
66#[derive(Clone, Debug, Deserialize, Serialize)]
67#[serde(untagged)]
68pub enum AggSpec<'a> {
69 /// An aggregate function with no additional arguments.
70 Single(Cow<'a, str>),
71 /// An aggregate function that requires column type arguments.
72 Multiple(Cow<'a, str>, Vec<ColumnType>),
73}
74
75impl<'a> From<Features<'a>> for GetFeaturesResp {
76 fn from(value: Features<'a>) -> GetFeaturesResp {
77 GetFeaturesResp {
78 group_by: value.group_by,
79 group_rollup_mode: value
80 .group_rollup_mode
81 .iter()
82 .map(|x| crate::proto::GroupRollupMode::from(*x) as i32)
83 .collect(),
84 split_by: value.split_by,
85 expressions: value.expressions,
86 on_update: value.on_update,
87 sort: value.sort,
88 aggregates: value
89 .aggregates
90 .iter()
91 .map(|(dtype, aggs)| {
92 (*dtype as u32, AggregateOptions {
93 aggregates: aggs
94 .iter()
95 .map(|agg| match agg {
96 AggSpec::Single(cow) => AggregateArgs {
97 name: cow.to_string(),
98 args: vec![],
99 },
100 AggSpec::Multiple(cow, column_types) => AggregateArgs {
101 name: cow.to_string(),
102 args: column_types.iter().map(|x| *x as i32).collect(),
103 },
104 })
105 .collect(),
106 })
107 })
108 .collect(),
109 filter_ops: value
110 .filter_ops
111 .iter()
112 .map(|(ty, options)| {
113 (*ty as u32, ColumnTypeOptions {
114 options: options.iter().map(|x| (*x).to_string()).collect(),
115 })
116 })
117 .collect(),
118 }
119 }
120}