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, PartialOrd, Ord, Hash, Serialize, Deserialize)]
51pub struct RegionId(#[serde(deserialize_with = "str_or_u64")] u64);
52
53fn str_or_u64<'de, D>(deserializer: D) -> Result<u64, D::Error>
55where
56 D: serde::Deserializer<'de>,
57{
58 #[derive(Deserialize)]
59 #[serde(untagged)]
60 enum StrOrU64 {
61 U64(u64),
62 Str(String),
63 }
64 match StrOrU64::deserialize(deserializer)? {
65 StrOrU64::U64(v) => Ok(v),
66 StrOrU64::Str(s) => s.parse::<u64>().map_err(serde::de::Error::custom),
67 }
68}
69
70impl RegionId {
71 pub const fn new(table_id: TableId, region_number: RegionNumber) -> RegionId {
73 RegionId(((table_id as u64) << 32) | region_number as u64)
74 }
75
76 pub const fn table_id(&self) -> TableId {
78 (self.0 >> 32) as TableId
79 }
80
81 pub const fn region_number(&self) -> RegionNumber {
83 self.0 as RegionNumber
84 }
85
86 pub const fn region_group(&self) -> RegionGroup {
88 ((self.region_number() & REGION_GROUP_MASK) >> 24) as RegionGroup
89 }
90
91 pub const fn region_sequence(&self) -> RegionSeq {
93 self.region_number() & REGION_SEQ_MASK
94 }
95
96 pub const fn as_u64(&self) -> u64 {
98 self.0
99 }
100
101 pub const fn from_u64(id: u64) -> RegionId {
103 RegionId(id)
104 }
105
106 pub const fn with_group_and_seq(
108 table_id: TableId,
109 group: RegionGroup,
110 seq: RegionSeq,
111 ) -> RegionId {
112 RegionId(
113 ((table_id as u64) << 32)
114 | ((group as u32) << 24) as u64
115 | (seq & REGION_SEQ_MASK) as u64,
116 )
117 }
118}
119
120impl fmt::Debug for RegionId {
121 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
122 write!(
123 f,
124 "{}({}, {})",
125 self.0,
126 self.table_id(),
127 self.region_number()
128 )
129 }
130}
131
132impl fmt::Display for RegionId {
133 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
134 write!(f, "{:?}", self)
135 }
136}
137
138impl From<u64> for RegionId {
139 fn from(region_id: u64) -> RegionId {
140 RegionId::from_u64(region_id)
141 }
142}
143
144impl From<RegionId> for u64 {
145 fn from(region_id: RegionId) -> u64 {
146 region_id.as_u64()
147 }
148}
149
150impl PartialEq<u64> for RegionId {
151 fn eq(&self, other: &u64) -> bool {
152 self.0 == *other
153 }
154}
155
156impl PartialEq<RegionId> for u64 {
157 fn eq(&self, other: &RegionId) -> bool {
158 *self == other.0
159 }
160}
161
162#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Builder)]
164#[builder(pattern = "owned", build_fn(validate = "Self::validate"))]
165pub struct ColumnDescriptor {
166 pub id: ColumnId,
167 #[builder(setter(into))]
168 pub name: String,
169 pub data_type: ConcreteDataType,
170 #[builder(default = "true")]
172 is_nullable: bool,
173 #[builder(default = "false")]
175 is_time_index: bool,
176 #[builder(default)]
179 default_constraint: Option<ColumnDefaultConstraint>,
180 #[builder(default, setter(into))]
181 pub comment: String,
182}
183
184impl ColumnDescriptor {
185 #[inline]
186 pub fn is_nullable(&self) -> bool {
187 self.is_nullable
188 }
189 #[inline]
190 pub fn is_time_index(&self) -> bool {
191 self.is_time_index
192 }
193
194 #[inline]
195 pub fn default_constraint(&self) -> Option<&ColumnDefaultConstraint> {
196 self.default_constraint.as_ref()
197 }
198
199 pub fn to_column_schema(&self) -> ColumnSchema {
202 ColumnSchema::new(&self.name, self.data_type.clone(), self.is_nullable)
203 .with_time_index(self.is_time_index)
204 .with_default_constraint(self.default_constraint.clone())
205 .expect("ColumnDescriptor should validate default constraint")
206 }
207}
208
209impl ColumnDescriptorBuilder {
210 pub fn new<S: Into<String>>(id: ColumnId, name: S, data_type: ConcreteDataType) -> Self {
211 Self {
212 id: Some(id),
213 name: Some(name.into()),
214 data_type: Some(data_type),
215 ..Default::default()
216 }
217 }
218
219 fn validate(&self) -> Result<(), String> {
220 if let Some(name) = &self.name
221 && name.is_empty()
222 {
223 return Err("name should not be empty".to_string());
224 }
225
226 if let (Some(Some(constraint)), Some(data_type)) =
227 (&self.default_constraint, &self.data_type)
228 {
229 let is_nullable = self.is_nullable.unwrap_or(true);
232
233 constraint
234 .validate(data_type, is_nullable)
235 .map_err(|e| e.to_string())?;
236 }
237
238 Ok(())
239 }
240}
241
242#[cfg(test)]
243mod tests {
244 use datatypes::value::Value;
245
246 use super::*;
247
248 #[inline]
249 fn new_column_desc_builder() -> ColumnDescriptorBuilder {
250 ColumnDescriptorBuilder::new(3, "test", ConcreteDataType::int32_datatype())
251 }
252
253 #[test]
254 fn test_column_descriptor_builder() {
255 let desc = new_column_desc_builder().build().unwrap();
256 assert_eq!(3, desc.id);
257 assert_eq!("test", desc.name);
258 assert_eq!(ConcreteDataType::int32_datatype(), desc.data_type);
259 assert!(desc.is_nullable);
260 assert!(desc.default_constraint.is_none());
261 assert!(desc.comment.is_empty());
262
263 let desc = new_column_desc_builder()
264 .is_nullable(false)
265 .build()
266 .unwrap();
267 assert!(!desc.is_nullable());
268
269 let desc = new_column_desc_builder()
270 .default_constraint(Some(ColumnDefaultConstraint::Value(Value::Null)))
271 .build()
272 .unwrap();
273 assert_eq!(
274 ColumnDefaultConstraint::Value(Value::Null),
275 *desc.default_constraint().unwrap()
276 );
277
278 let desc = new_column_desc_builder()
279 .default_constraint(Some(ColumnDefaultConstraint::Value(Value::Int32(123))))
280 .build()
281 .unwrap();
282 assert_eq!(
283 ColumnDefaultConstraint::Value(Value::Int32(123)),
284 desc.default_constraint.unwrap()
285 );
286
287 let desc = new_column_desc_builder()
288 .comment("A test column")
289 .build()
290 .unwrap();
291 assert_eq!("A test column", desc.comment);
292
293 assert!(
294 new_column_desc_builder()
295 .is_nullable(false)
296 .default_constraint(Some(ColumnDefaultConstraint::Value(Value::Null)))
297 .build()
298 .is_err()
299 );
300 }
301
302 #[test]
303 fn test_descriptor_to_column_schema() {
304 let constraint = ColumnDefaultConstraint::Value(Value::Int32(123));
305 let desc = new_column_desc_builder()
306 .default_constraint(Some(constraint.clone()))
307 .is_nullable(false)
308 .build()
309 .unwrap();
310 let column_schema = desc.to_column_schema();
311 let expected = ColumnSchema::new("test", ConcreteDataType::int32_datatype(), false)
312 .with_default_constraint(Some(constraint))
313 .unwrap();
314
315 assert_eq!(expected, column_schema);
316 }
317
318 #[test]
319 fn test_region_id() {
320 assert_eq!(RegionId::new(0, 1), 1);
321 assert_eq!(4294967296, RegionId::new(1, 0));
322 assert_eq!(4294967297, RegionId::new(1, 1));
323 assert_eq!(4294967396, RegionId::new(1, 100));
324 assert_eq!(8589934602, RegionId::new(2, 10));
325 assert_eq!(18446744069414584330, RegionId::new(u32::MAX, 10));
326
327 let region_id = RegionId::new(u32::MAX, 1);
328 assert_eq!(u32::MAX, region_id.table_id());
329 assert_eq!(1, region_id.region_number());
330 let inner: u64 = region_id.into();
331 assert_eq!(RegionId::from(inner), region_id);
332
333 let region_id = RegionId::new(1234, 5);
334 assert_eq!("5299989643269(1234, 5)", region_id.to_string());
335 assert_eq!("5299989643269(1234, 5)", format!("{:?}", region_id));
336 }
337
338 #[test]
339 fn test_region_id_to_json() {
340 let region_id = RegionId::from(4294967297);
341 let json = serde_json::to_string(®ion_id).unwrap();
342 assert_eq!("4294967297", json);
343
344 let parsed: RegionId = serde_json::from_str(&json).unwrap();
345 assert_eq!(region_id, parsed);
346 }
347
348 #[test]
349 fn test_region_id_from_str() {
350 let region_id_str = "\"8589934602\"";
351 let region_id: RegionId = serde_json::from_str(region_id_str).unwrap();
352 assert_eq!(RegionId::new(2, 10), region_id);
353 }
354
355 #[test]
356 fn test_retrieve_region_group_and_seq() {
357 let region_id = RegionId::with_group_and_seq(111, 222, 333);
358 assert_eq!(111, region_id.table_id());
359 assert_eq!(222, region_id.region_group());
360 assert_eq!(333, region_id.region_sequence());
361
362 let expected_region_number = 222 << 24 | 333;
363 assert_eq!(expected_region_number, region_id.region_number());
364 }
365
366 #[test]
367 fn test_invalid_large_region_sequence() {
368 let region_id = RegionId::with_group_and_seq(111, 222, u32::MAX);
370 assert_eq!(MAX_REGION_SEQ, region_id.region_sequence());
371 }
372}