zeppelin_embed/meta/
mod.rs1mod alive;
8mod bitmap;
9#[cfg(any(test, feature = "test-support"))]
10#[doc(hidden)]
11pub mod bitmap_observer;
12mod columns;
13mod dict;
14mod predicate;
15
16pub use alive::{AliveError, AliveSet};
17pub use bitmap::DocBitmap;
18#[cfg(any(test, feature = "test-support"))]
19#[doc(hidden)]
20pub use columns::MetadataBuildTestLimits;
21pub use columns::{
22 BoolColumn, BuildError, Column, ColumnInput, ColumnStore, ColumnStoreBuilder, ColumnValue,
23 DictionaryColumn, NumericColumn, RawStringColumn,
24};
25pub use dict::{CodeWidth, DictionaryCodes, DictionaryError, StringDictionary};
26pub use predicate::{EvalError, Predicate, PredicateValue, RangeBound, RangePredicate, evaluate};
27
28pub const TIMESTAMP_COLUMN: ColumnId = ColumnId(0);
30
31#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
33#[repr(transparent)]
34pub struct ColumnId(u32);
35
36impl ColumnId {
37 #[must_use]
39 pub const fn new(value: u32) -> Self {
40 Self(value)
41 }
42
43 #[must_use]
45 pub const fn get(self) -> u32 {
46 self.0
47 }
48}
49
50#[derive(Clone, Copy, Debug, Eq, PartialEq)]
52pub enum ColumnType {
53 U64,
55 I64,
57 F64,
59 Bool,
61 DictionaryString,
63 RawString,
65}
66
67#[derive(Clone, Debug, Eq, PartialEq)]
69pub struct ColumnDefinition {
70 id: ColumnId,
71 name: String,
72 column_type: ColumnType,
73 nullable: bool,
74}
75
76impl ColumnDefinition {
77 #[must_use]
79 pub fn new(
80 id: ColumnId,
81 name: impl Into<String>,
82 column_type: ColumnType,
83 nullable: bool,
84 ) -> Self {
85 Self {
86 id,
87 name: name.into(),
88 column_type,
89 nullable,
90 }
91 }
92
93 #[must_use]
95 pub const fn id(&self) -> ColumnId {
96 self.id
97 }
98
99 #[must_use]
101 pub fn name(&self) -> &str {
102 &self.name
103 }
104
105 #[must_use]
107 pub const fn column_type(&self) -> ColumnType {
108 self.column_type
109 }
110
111 #[must_use]
113 pub const fn is_nullable(&self) -> bool {
114 self.nullable
115 }
116}
117
118#[derive(Clone, Debug, Eq, PartialEq)]
120pub enum SchemaError {
121 ReservedTimestampId,
123 ReservedTimestampName,
125 DuplicateColumnId(ColumnId),
127 DuplicateColumnName(String),
129}
130
131impl std::fmt::Display for SchemaError {
132 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
133 match self {
134 Self::ReservedTimestampId => formatter.write_str("column id 0 is reserved for ts"),
135 Self::ReservedTimestampName => formatter.write_str("column name ts is reserved"),
136 Self::DuplicateColumnId(id) => write!(formatter, "duplicate column id {}", id.get()),
137 Self::DuplicateColumnName(name) => write!(formatter, "duplicate column name {name}"),
138 }
139 }
140}
141
142impl std::error::Error for SchemaError {}
143
144#[derive(Clone, Debug, Eq, PartialEq)]
146pub struct Schema {
147 columns: Vec<ColumnDefinition>,
148}
149
150impl Schema {
151 pub(crate) fn resident_bytes(&self) -> Option<usize> {
152 let definitions = self
153 .columns
154 .capacity()
155 .checked_mul(std::mem::size_of::<ColumnDefinition>())?;
156 self.columns
157 .iter()
158 .try_fold(definitions, |total, definition| {
159 total.checked_add(definition.name.capacity())
160 })
161 }
162
163 #[must_use]
165 pub fn timestamp_only() -> Self {
166 Self {
167 columns: vec![ColumnDefinition::new(
168 TIMESTAMP_COLUMN,
169 "ts",
170 ColumnType::I64,
171 false,
172 )],
173 }
174 }
175
176 pub fn new(user_columns: Vec<ColumnDefinition>) -> Result<Self, SchemaError> {
178 for (position, definition) in user_columns.iter().enumerate() {
179 if definition.id == TIMESTAMP_COLUMN {
180 return Err(SchemaError::ReservedTimestampId);
181 }
182 if definition.name == "ts" {
183 return Err(SchemaError::ReservedTimestampName);
184 }
185 if let Some(duplicate) = user_columns.iter().take(position).find(|candidate| {
186 candidate.id == definition.id || candidate.name == definition.name
187 }) {
188 if duplicate.id == definition.id {
189 return Err(SchemaError::DuplicateColumnId(definition.id));
190 }
191 return Err(SchemaError::DuplicateColumnName(definition.name.clone()));
192 }
193 }
194
195 let mut columns = Self::timestamp_only().columns;
196 columns.reserve(user_columns.len());
197 columns.extend(user_columns);
198 Ok(Self { columns })
199 }
200
201 #[must_use]
203 pub fn columns(&self) -> &[ColumnDefinition] {
204 &self.columns
205 }
206
207 #[must_use]
209 pub fn column(&self, id: ColumnId) -> Option<&ColumnDefinition> {
210 self.columns.iter().find(|definition| definition.id == id)
211 }
212
213 #[must_use]
215 pub fn user_column_count(&self) -> usize {
216 self.columns.len().saturating_sub(1)
217 }
218}