Skip to main content

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}