Skip to main content

mito2/read/
read_columns.rs

1// Copyright 2023 Greptime Team
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::mem;
16
17use store_api::storage::{ColumnId, NestedPath};
18
19/// Logical columns to read from a region.
20///
21/// Read columns describe which logical columns and nested fields should be read
22/// from storage. Each read column is identified by its [`ColumnId`],
23/// which represents the root column in the storage schema.
24///
25/// Nested fields under the column are specified by [`NestedPath`] entries.
26/// Each path includes the root column name as its first element.
27///
28/// For example, assume column id `9` corresponds to a root column named `j`
29/// with nested fields:
30///
31/// ```text
32/// j
33/// ├── a
34/// └── b
35///     └── c
36/// ```
37///
38/// The following SQL:
39///
40/// SELECT j.a, j.b.c FROM t
41///
42/// may produce read columns like:
43///
44/// ```text
45/// ReadColumn {
46///     column_id: 9,
47///     nested_paths: [
48///         ["j", "a"],
49///         ["j", "b", "c"],
50///     ]
51/// }
52/// ```
53///
54/// If `nested_paths` is empty, the whole column will be read.
55#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)]
56pub struct ReadColumns {
57    pub cols: Vec<ReadColumn>,
58}
59
60impl ReadColumns {
61    pub fn from_deduped_column_ids<I>(column_ids: I) -> Self
62    where
63        I: IntoIterator<Item = ColumnId>,
64    {
65        let cols = column_ids
66            .into_iter()
67            .map(|col_id| ReadColumn::new(col_id, vec![]))
68            .collect();
69        ReadColumns { cols }
70    }
71
72    pub fn is_empty(&self) -> bool {
73        self.cols.is_empty()
74    }
75
76    pub fn column_ids_iter(&self) -> impl Iterator<Item = ColumnId> + '_ {
77        self.cols.iter().map(|column| column.column_id)
78    }
79
80    pub fn column_ids(&self) -> Vec<ColumnId> {
81        self.column_ids_iter().collect()
82    }
83
84    pub fn columns(&self) -> &[ReadColumn] {
85        &self.cols
86    }
87
88    pub fn estimated_size(&self) -> usize {
89        self.cols.capacity() * mem::size_of::<ReadColumn>()
90            + self
91                .cols
92                .iter()
93                .map(ReadColumn::estimated_size)
94                .sum::<usize>()
95    }
96}
97
98#[derive(Debug, Clone, PartialEq, Eq, Hash)]
99pub struct ReadColumn {
100    pub column_id: ColumnId,
101    /// Nested field paths under this column.
102    /// Empty means reading the whole column.
103    pub nested_paths: Vec<NestedPath>,
104}
105
106impl ReadColumn {
107    pub fn new(column_id: ColumnId, nested_paths: Vec<NestedPath>) -> Self {
108        Self {
109            column_id,
110            nested_paths,
111        }
112    }
113
114    pub fn nested_paths(&self) -> &[NestedPath] {
115        &self.nested_paths
116    }
117
118    pub fn estimated_size(&self) -> usize {
119        mem::size_of::<ColumnId>()
120            + self.nested_paths.capacity() * mem::size_of::<NestedPath>()
121            + self
122                .nested_paths
123                .iter()
124                .map(|path| {
125                    path.capacity() * mem::size_of::<String>()
126                        + path.iter().map(|node| node.capacity()).sum::<usize>()
127                })
128                .sum::<usize>()
129    }
130}