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}