1use std::fmt;
16
17use derive_builder::Builder;
18use serde::{Deserialize, Serialize};
19
20use crate::storage::{ColumnDefaultConstraint, ColumnSchema, ConcreteDataType};
21
22pub type ColumnId = u32;
24pub type RegionGroup = u8;
26pub type RegionSeq = u32;
29pub type RegionNumber = u32;
32pub type TableId = u32;
34
35const REGION_GROUP_MASK: u32 = 0b1111_1111 << 24;
36const REGION_SEQ_MASK: u32 = (0b1 << 24) - 1;
37
38pub const MAX_REGION_SEQ: u32 = REGION_SEQ_MASK;
40
41#[derive(Default, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
51pub struct RegionId(u64);
52
53impl RegionId {
54 pub const fn new(table_id: TableId, region_number: RegionNumber) -> RegionId {
56 RegionId(((table_id as u64) << 32) | region_number as u64)
57 }
58
59 pub const fn table_id(&self) -> TableId {
61 (self.0 >> 32) as TableId
62 }
63
64 pub const fn region_number(&self) -> RegionNumber {
66 self.0 as RegionNumber
67 }
68
69 pub const fn region_group(&self) -> RegionGroup {
71 ((self.region_number() & REGION_GROUP_MASK) >> 24) as RegionGroup
72 }
73
74 pub const fn region_sequence(&self) -> RegionSeq {
76 self.region_number() & REGION_SEQ_MASK
77 }
78
79 pub const fn as_u64(&self) -> u64 {
81 self.0
82 }
83
84 pub const fn from_u64(id: u64) -> RegionId {
86 RegionId(id)
87 }
88
89 pub const fn with_group_and_seq(
91 table_id: TableId,
92 group: RegionGroup,
93 seq: RegionSeq,
94 ) -> RegionId {
95 RegionId(
96 ((table_id as u64) << 32)
97 | ((group as u32) << 24) as u64
98 | (seq & REGION_SEQ_MASK) as u64,
99 )
100 }
101}
102
103impl fmt::Debug for RegionId {
104 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
105 write!(
106 f,
107 "{}({}, {})",
108 self.0,
109 self.table_id(),
110 self.region_number()
111 )
112 }
113}
114
115impl fmt::Display for RegionId {
116 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
117 write!(f, "{:?}", self)
118 }
119}
120
121impl From<u64> for RegionId {
122 fn from(region_id: u64) -> RegionId {
123 RegionId::from_u64(region_id)
124 }
125}
126
127impl From<RegionId> for u64 {
128 fn from(region_id: RegionId) -> u64 {
129 region_id.as_u64()
130 }
131}
132
133impl PartialEq<u64> for RegionId {
134 fn eq(&self, other: &u64) -> bool {
135 self.0 == *other
136 }
137}
138
139impl PartialEq<RegionId> for u64 {
140 fn eq(&self, other: &RegionId) -> bool {
141 *self == other.0
142 }
143}
144
145#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Builder)]
147#[builder(pattern = "owned", build_fn(validate = "Self::validate"))]
148pub struct ColumnDescriptor {
149 pub id: ColumnId,
150 #[builder(setter(into))]
151 pub name: String,
152 pub data_type: ConcreteDataType,
153 #[builder(default = "true")]
155 is_nullable: bool,
156 #[builder(default = "false")]
158 is_time_index: bool,
159 #[builder(default)]
162 default_constraint: Option<ColumnDefaultConstraint>,
163 #[builder(default, setter(into))]
164 pub comment: String,
165}
166
167impl ColumnDescriptor {
168 #[inline]
169 pub fn is_nullable(&self) -> bool {
170 self.is_nullable
171 }
172 #[inline]
173 pub fn is_time_index(&self) -> bool {
174 self.is_time_index
175 }
176
177 #[inline]
178 pub fn default_constraint(&self) -> Option<&ColumnDefaultConstraint> {
179 self.default_constraint.as_ref()
180 }
181
182 pub fn to_column_schema(&self) -> ColumnSchema {
185 ColumnSchema::new(&self.name, self.data_type.clone(), self.is_nullable)
186 .with_time_index(self.is_time_index)
187 .with_default_constraint(self.default_constraint.clone())
188 .expect("ColumnDescriptor should validate default constraint")
189 }
190}
191
192impl ColumnDescriptorBuilder {
193 pub fn new<S: Into<String>>(id: ColumnId, name: S, data_type: ConcreteDataType) -> Self {
194 Self {
195 id: Some(id),
196 name: Some(name.into()),
197 data_type: Some(data_type),
198 ..Default::default()
199 }
200 }
201
202 fn validate(&self) -> Result<(), String> {
203 if let Some(name) = &self.name {
204 if name.is_empty() {
205 return Err("name should not be empty".to_string());
206 }
207 }
208
209 if let (Some(Some(constraint)), Some(data_type)) =
210 (&self.default_constraint, &self.data_type)
211 {
212 let is_nullable = self.is_nullable.unwrap_or(true);
215
216 constraint
217 .validate(data_type, is_nullable)
218 .map_err(|e| e.to_string())?;
219 }
220
221 Ok(())
222 }
223}
224
225#[cfg(test)]
226mod tests {
227 use datatypes::value::Value;
228
229 use super::*;
230
231 #[inline]
232 fn new_column_desc_builder() -> ColumnDescriptorBuilder {
233 ColumnDescriptorBuilder::new(3, "test", ConcreteDataType::int32_datatype())
234 }
235
236 #[test]
237 fn test_column_descriptor_builder() {
238 let desc = new_column_desc_builder().build().unwrap();
239 assert_eq!(3, desc.id);
240 assert_eq!("test", desc.name);
241 assert_eq!(ConcreteDataType::int32_datatype(), desc.data_type);
242 assert!(desc.is_nullable);
243 assert!(desc.default_constraint.is_none());
244 assert!(desc.comment.is_empty());
245
246 let desc = new_column_desc_builder()
247 .is_nullable(false)
248 .build()
249 .unwrap();
250 assert!(!desc.is_nullable());
251
252 let desc = new_column_desc_builder()
253 .default_constraint(Some(ColumnDefaultConstraint::Value(Value::Null)))
254 .build()
255 .unwrap();
256 assert_eq!(
257 ColumnDefaultConstraint::Value(Value::Null),
258 *desc.default_constraint().unwrap()
259 );
260
261 let desc = new_column_desc_builder()
262 .default_constraint(Some(ColumnDefaultConstraint::Value(Value::Int32(123))))
263 .build()
264 .unwrap();
265 assert_eq!(
266 ColumnDefaultConstraint::Value(Value::Int32(123)),
267 desc.default_constraint.unwrap()
268 );
269
270 let desc = new_column_desc_builder()
271 .comment("A test column")
272 .build()
273 .unwrap();
274 assert_eq!("A test column", desc.comment);
275
276 assert!(new_column_desc_builder()
277 .is_nullable(false)
278 .default_constraint(Some(ColumnDefaultConstraint::Value(Value::Null)))
279 .build()
280 .is_err());
281 }
282
283 #[test]
284 fn test_descriptor_to_column_schema() {
285 let constraint = ColumnDefaultConstraint::Value(Value::Int32(123));
286 let desc = new_column_desc_builder()
287 .default_constraint(Some(constraint.clone()))
288 .is_nullable(false)
289 .build()
290 .unwrap();
291 let column_schema = desc.to_column_schema();
292 let expected = ColumnSchema::new("test", ConcreteDataType::int32_datatype(), false)
293 .with_default_constraint(Some(constraint))
294 .unwrap();
295
296 assert_eq!(expected, column_schema);
297 }
298
299 #[test]
300 fn test_region_id() {
301 assert_eq!(RegionId::new(0, 1), 1);
302 assert_eq!(4294967296, RegionId::new(1, 0));
303 assert_eq!(4294967297, RegionId::new(1, 1));
304 assert_eq!(4294967396, RegionId::new(1, 100));
305 assert_eq!(8589934602, RegionId::new(2, 10));
306 assert_eq!(18446744069414584330, RegionId::new(u32::MAX, 10));
307
308 let region_id = RegionId::new(u32::MAX, 1);
309 assert_eq!(u32::MAX, region_id.table_id());
310 assert_eq!(1, region_id.region_number());
311 let inner: u64 = region_id.into();
312 assert_eq!(RegionId::from(inner), region_id);
313
314 let region_id = RegionId::new(1234, 5);
315 assert_eq!("5299989643269(1234, 5)", region_id.to_string());
316 assert_eq!("5299989643269(1234, 5)", format!("{:?}", region_id));
317 }
318
319 #[test]
320 fn test_region_id_to_json() {
321 let region_id = RegionId::from(4294967297);
322 let json = serde_json::to_string(®ion_id).unwrap();
323 assert_eq!("4294967297", json);
324
325 let parsed: RegionId = serde_json::from_str(&json).unwrap();
326 assert_eq!(region_id, parsed);
327 }
328
329 #[test]
330 fn test_retrieve_region_group_and_seq() {
331 let region_id = RegionId::with_group_and_seq(111, 222, 333);
332 assert_eq!(111, region_id.table_id());
333 assert_eq!(222, region_id.region_group());
334 assert_eq!(333, region_id.region_sequence());
335
336 let expected_region_number = 222 << 24 | 333;
337 assert_eq!(expected_region_number, region_id.region_number());
338 }
339
340 #[test]
341 fn test_invalid_large_region_sequence() {
342 let region_id = RegionId::with_group_and_seq(111, 222, u32::MAX);
344 assert_eq!(MAX_REGION_SEQ, region_id.region_sequence());
345 }
346}