Skip to main content

fluss/metadata/
json_serde.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18use crate::error::Error::JsonSerdeError;
19use crate::error::{Error, Result};
20use crate::metadata::datatype::{DataField, DataType, DataTypes};
21use crate::metadata::table::{Column, Schema, TableDescriptor};
22use serde_json::{Value, json};
23use std::collections::HashMap;
24
25pub trait JsonSerde: Sized {
26    fn serialize_json(&self) -> Result<Value>;
27
28    fn deserialize_json(node: &Value) -> Result<Self>;
29}
30
31impl DataType {
32    pub fn to_type_root(&self) -> &str {
33        match &self {
34            DataType::Boolean(_) => "BOOLEAN",
35            DataType::TinyInt(_) => "TINYINT",
36            DataType::SmallInt(_) => "SMALLINT",
37            DataType::Int(_) => "INTEGER",
38            DataType::BigInt(_) => "BIGINT",
39            DataType::Float(_) => "FLOAT",
40            DataType::Double(_) => "DOUBLE",
41            DataType::Char(_) => "CHAR",
42            DataType::String(_) => "STRING",
43            DataType::Decimal(_) => "DECIMAL",
44            DataType::Date(_) => "DATE",
45            DataType::Time(_) => "TIME_WITHOUT_TIME_ZONE",
46            DataType::Timestamp(_) => "TIMESTAMP_WITHOUT_TIME_ZONE",
47            DataType::TimestampLTz(_) => "TIMESTAMP_WITH_LOCAL_TIME_ZONE",
48            DataType::Bytes(_) => "BYTES",
49            DataType::Binary(_) => "BINARY",
50            DataType::Array(_) => "ARRAY",
51            DataType::Map(_) => "MAP",
52            DataType::Row(_) => "ROW",
53        }
54    }
55}
56
57impl DataType {
58    const FIELD_NAME_TYPE_NAME: &'static str = "type";
59    const FIELD_NAME_NULLABLE: &'static str = "nullable";
60    const FIELD_NAME_LENGTH: &'static str = "length";
61    const FIELD_NAME_PRECISION: &'static str = "precision";
62    const FIELD_NAME_SCALE: &'static str = "scale";
63    #[allow(dead_code)]
64    const FIELD_NAME_ELEMENT_TYPE: &'static str = "element_type";
65    #[allow(dead_code)]
66    const FIELD_NAME_KEY_TYPE: &'static str = "key_type";
67    #[allow(dead_code)]
68    const FIELD_NAME_VALUE_TYPE: &'static str = "value_type";
69    #[allow(dead_code)]
70    const FIELD_NAME_FIELDS: &'static str = "fields";
71    #[allow(dead_code)]
72    const FIELD_NAME_FIELD_NAME: &'static str = "name";
73    // ROW
74    #[allow(dead_code)]
75    const FIELD_NAME_FIELD_TYPE: &'static str = "field_type";
76    #[allow(dead_code)]
77    const FIELD_NAME_FIELD_DESCRIPTION: &'static str = "description";
78}
79
80impl JsonSerde for DataType {
81    fn serialize_json(&self) -> Result<Value> {
82        let mut obj = serde_json::Map::new();
83
84        obj.insert(
85            Self::FIELD_NAME_TYPE_NAME.to_string(),
86            json!(Self::to_type_root(self)),
87        );
88        if !self.is_nullable() {
89            obj.insert(Self::FIELD_NAME_NULLABLE.to_string(), json!(false));
90        }
91
92        match &self {
93            DataType::Boolean(_)
94            | DataType::TinyInt(_)
95            | DataType::SmallInt(_)
96            | DataType::Int(_)
97            | DataType::BigInt(_)
98            | DataType::Float(_)
99            | DataType::Double(_)
100            | DataType::String(_)
101            | DataType::Bytes(_)
102            | DataType::Date(_) => {
103                // do nothing
104            }
105            DataType::Char(_type) => {
106                obj.insert(Self::FIELD_NAME_LENGTH.to_string(), json!(_type.length()));
107            }
108            DataType::Binary(_type) => {
109                obj.insert(Self::FIELD_NAME_LENGTH.to_string(), json!(_type.length()));
110            }
111            DataType::Decimal(_type) => {
112                obj.insert(
113                    Self::FIELD_NAME_PRECISION.to_string(),
114                    json!(_type.precision()),
115                );
116                obj.insert(Self::FIELD_NAME_SCALE.to_string(), json!(_type.scale()));
117            }
118            DataType::Time(_type) => {
119                obj.insert(
120                    Self::FIELD_NAME_PRECISION.to_string(),
121                    json!(_type.precision()),
122                );
123            }
124            DataType::Timestamp(_type) => {
125                obj.insert(
126                    Self::FIELD_NAME_PRECISION.to_string(),
127                    json!(_type.precision()),
128                );
129            }
130            DataType::TimestampLTz(_type) => {
131                obj.insert(
132                    Self::FIELD_NAME_PRECISION.to_string(),
133                    json!(_type.precision()),
134                );
135            }
136            DataType::Array(_type) => {
137                obj.insert(
138                    Self::FIELD_NAME_ELEMENT_TYPE.to_string(),
139                    _type.get_element_type().serialize_json()?,
140                );
141            }
142            DataType::Map(_type) => {
143                obj.insert(
144                    Self::FIELD_NAME_KEY_TYPE.to_string(),
145                    _type.key_type().serialize_json()?,
146                );
147                obj.insert(
148                    Self::FIELD_NAME_VALUE_TYPE.to_string(),
149                    _type.value_type().serialize_json()?,
150                );
151            }
152            DataType::Row(_type) => {
153                let fields: Vec<Value> = _type
154                    .fields()
155                    .iter()
156                    .map(|field| field.serialize_json())
157                    .collect::<Result<_>>()?;
158                obj.insert(Self::FIELD_NAME_FIELDS.to_string(), json!(fields));
159            }
160        }
161        Ok(Value::Object(obj))
162    }
163
164    fn deserialize_json(node: &Value) -> Result<Self> {
165        let mut _is_nullable = true;
166        let type_root = node
167            .get(Self::FIELD_NAME_TYPE_NAME)
168            .and_then(|v| v.as_str())
169            .ok_or_else(|| Error::JsonSerdeError {
170                message: format!(
171                    "Couldn't find field {} while deserializing datatype.",
172                    Self::FIELD_NAME_TYPE_NAME
173                ),
174            })?;
175
176        let mut data_type = match type_root {
177            "BOOLEAN" => DataTypes::boolean(),
178            "TINYINT" => DataTypes::tinyint(),
179            "SMALLINT" => DataTypes::smallint(),
180            "INTEGER" => DataTypes::int(),
181            "BIGINT" => DataTypes::bigint(),
182            "FLOAT" => DataTypes::float(),
183            "DOUBLE" => DataTypes::double(),
184            "CHAR" => {
185                let length = node
186                    .get(Self::FIELD_NAME_LENGTH)
187                    .and_then(|v| v.as_u64())
188                    .ok_or_else(|| Error::JsonSerdeError {
189                        message: format!("Missing required field: {}", Self::FIELD_NAME_LENGTH),
190                    })? as u32;
191                DataTypes::char(length)
192            }
193            "STRING" => DataTypes::string(),
194            "DECIMAL" => {
195                let precision = node
196                    .get(Self::FIELD_NAME_PRECISION)
197                    .and_then(|v| v.as_u64())
198                    .ok_or_else(|| Error::JsonSerdeError {
199                        message: format!("Missing required field: {}", Self::FIELD_NAME_PRECISION),
200                    })? as u32;
201                let scale = node
202                    .get(Self::FIELD_NAME_SCALE)
203                    .and_then(|v| v.as_u64())
204                    .unwrap_or(0) as u32;
205                DataType::Decimal(
206                    crate::metadata::datatype::DecimalType::with_nullable(true, precision, scale)
207                        .map_err(|e| Error::JsonSerdeError {
208                        message: format!("Invalid DECIMAL parameters: {e}"),
209                    })?,
210                )
211            }
212            "DATE" => DataTypes::date(),
213            "TIME_WITHOUT_TIME_ZONE" => {
214                let precision = node
215                    .get(Self::FIELD_NAME_PRECISION)
216                    .and_then(|v| v.as_u64())
217                    .unwrap_or(0) as u32;
218                DataType::Time(
219                    crate::metadata::datatype::TimeType::with_nullable(true, precision).map_err(
220                        |e| Error::JsonSerdeError {
221                            message: format!("Invalid TIME_WITHOUT_TIME_ZONE precision: {e}"),
222                        },
223                    )?,
224                )
225            }
226            "TIMESTAMP_WITHOUT_TIME_ZONE" => {
227                let precision = node
228                    .get(Self::FIELD_NAME_PRECISION)
229                    .and_then(|v| v.as_u64())
230                    .unwrap_or(6) as u32;
231                DataType::Timestamp(
232                    crate::metadata::datatype::TimestampType::with_nullable(true, precision)
233                        .map_err(|e| Error::JsonSerdeError {
234                            message: format!("Invalid TIMESTAMP_WITHOUT_TIME_ZONE precision: {e}"),
235                        })?,
236                )
237            }
238            "TIMESTAMP_WITH_LOCAL_TIME_ZONE" => {
239                let precision = node
240                    .get(Self::FIELD_NAME_PRECISION)
241                    .and_then(|v| v.as_u64())
242                    .unwrap_or(6) as u32;
243                DataType::TimestampLTz(
244                    crate::metadata::datatype::TimestampLTzType::with_nullable(true, precision)
245                        .map_err(|e| Error::JsonSerdeError {
246                            message: format!(
247                                "Invalid TIMESTAMP_WITH_LOCAL_TIME_ZONE precision: {e}"
248                            ),
249                        })?,
250                )
251            }
252            "BYTES" => DataTypes::bytes(),
253            "BINARY" => {
254                let length = node
255                    .get(Self::FIELD_NAME_LENGTH)
256                    .and_then(|v| v.as_u64())
257                    .unwrap_or(1) as usize;
258                DataTypes::binary(length)
259            }
260            "ARRAY" => {
261                let element_type_node =
262                    node.get(Self::FIELD_NAME_ELEMENT_TYPE).ok_or_else(|| {
263                        Error::JsonSerdeError {
264                            message: format!(
265                                "Missing required field: {}",
266                                Self::FIELD_NAME_ELEMENT_TYPE
267                            ),
268                        }
269                    })?;
270                let element_type = DataType::deserialize_json(element_type_node)?;
271                DataTypes::array(element_type)
272            }
273            "MAP" => {
274                let key_type_node =
275                    node.get(Self::FIELD_NAME_KEY_TYPE)
276                        .ok_or_else(|| Error::JsonSerdeError {
277                            message: format!(
278                                "Missing required field: {}",
279                                Self::FIELD_NAME_KEY_TYPE
280                            ),
281                        })?;
282                let key_type = DataType::deserialize_json(key_type_node)?;
283                let value_type_node =
284                    node.get(Self::FIELD_NAME_VALUE_TYPE)
285                        .ok_or_else(|| Error::JsonSerdeError {
286                            message: format!(
287                                "Missing required field: {}",
288                                Self::FIELD_NAME_VALUE_TYPE
289                            ),
290                        })?;
291                let value_type = DataType::deserialize_json(value_type_node)?;
292                DataTypes::map(key_type, value_type)
293            }
294            "ROW" => {
295                let fields_node = node
296                    .get(Self::FIELD_NAME_FIELDS)
297                    .ok_or_else(|| Error::JsonSerdeError {
298                        message: format!("Missing required field: {}", Self::FIELD_NAME_FIELDS),
299                    })?
300                    .as_array()
301                    .ok_or_else(|| Error::JsonSerdeError {
302                        message: format!("{} must be an array", Self::FIELD_NAME_FIELDS),
303                    })?;
304                let mut fields = Vec::with_capacity(fields_node.len());
305                for field_node in fields_node {
306                    fields.push(DataField::deserialize_json(field_node)?);
307                }
308                DataTypes::row(fields)
309            }
310            _ => {
311                return Err(Error::JsonSerdeError {
312                    message: format!("Unknown type root: {type_root}"),
313                });
314            }
315        };
316
317        if let Some(nullable) = node.get(Self::FIELD_NAME_NULLABLE) {
318            let nullable_value = nullable.as_bool().unwrap_or(true);
319            if !nullable_value {
320                data_type = data_type.as_non_nullable();
321            }
322        }
323        Ok(data_type)
324    }
325}
326
327impl DataField {
328    const NAME: &'static str = "name";
329    const FIELD_TYPE: &'static str = "field_type";
330    const DESCRIPTION: &'static str = "description";
331}
332
333impl JsonSerde for DataField {
334    fn serialize_json(&self) -> Result<Value> {
335        let mut obj = serde_json::Map::new();
336
337        obj.insert(Self::NAME.to_string(), json!(self.name()));
338        obj.insert(
339            Self::FIELD_TYPE.to_string(),
340            self.data_type.serialize_json()?,
341        );
342
343        if let Some(description) = &self.description {
344            obj.insert(Self::DESCRIPTION.to_string(), json!(description));
345        }
346
347        Ok(Value::Object(obj))
348    }
349
350    fn deserialize_json(node: &Value) -> Result<DataField> {
351        let name = node
352            .get(Self::NAME)
353            .and_then(|v| v.as_str())
354            .ok_or_else(|| Error::JsonSerdeError {
355                message: format!("Missing required field: {}", Self::NAME),
356            })?
357            .to_string();
358
359        let field_type_node = node
360            .get(Self::FIELD_TYPE)
361            .ok_or_else(|| Error::JsonSerdeError {
362                message: format!("Missing required field: {}", Self::FIELD_TYPE),
363            })?;
364
365        let data_type = DataType::deserialize_json(field_type_node)?;
366
367        let description = node
368            .get(Self::DESCRIPTION)
369            .and_then(|v| v.as_str())
370            .map(|s| s.to_string());
371
372        Ok(DataField::new(name, data_type, description))
373    }
374}
375
376impl Column {
377    const NAME: &'static str = "name";
378    const DATA_TYPE: &'static str = "data_type";
379    const COMMENT: &'static str = "comment";
380}
381
382impl JsonSerde for Column {
383    fn serialize_json(&self) -> Result<Value> {
384        let mut obj = serde_json::Map::new();
385
386        // Common fields
387        obj.insert(Self::NAME.to_string(), json!(self.name()));
388        obj.insert(
389            Self::DATA_TYPE.to_string(),
390            self.data_type().serialize_json()?,
391        );
392
393        if let Some(comment) = &self.comment() {
394            obj.insert(Self::COMMENT.to_string(), json!(comment));
395        }
396
397        Ok(Value::Object(obj))
398    }
399
400    fn deserialize_json(node: &Value) -> Result<Column> {
401        let name = node
402            .get(Self::NAME)
403            .and_then(|v| v.as_str())
404            .ok_or_else(|| Error::JsonSerdeError {
405                message: format!("Missing required field: {}", Self::NAME),
406            })?;
407
408        let data_type_node = node
409            .get(Self::DATA_TYPE)
410            .ok_or_else(|| Error::JsonSerdeError {
411                message: format!("Missing required field: {}", Self::DATA_TYPE),
412            })?;
413
414        let data_type = DataType::deserialize_json(data_type_node)?;
415
416        let mut column = Column::new(name, data_type);
417
418        if let Some(comment) = node.get(Self::COMMENT).and_then(|v| v.as_str()) {
419            column = column.with_comment(comment);
420        }
421
422        Ok(column)
423    }
424}
425
426impl Schema {
427    const COLUMNS_NAME: &'static str = "columns";
428    const PRIMARY_KEY_NAME: &'static str = "primary_key";
429    const VERSION_KEY: &'static str = "version";
430    const VERSION: u32 = 1;
431}
432
433impl JsonSerde for Schema {
434    fn serialize_json(&self) -> Result<Value> {
435        let mut obj = serde_json::Map::new();
436
437        // Serialize version
438        obj.insert(Self::VERSION_KEY.to_string(), json!(Self::VERSION));
439
440        // Serialize columns
441        let columns: Vec<Value> = self
442            .columns()
443            .iter()
444            .map(|col| col.serialize_json())
445            .collect::<Result<_>>()?;
446        obj.insert(Self::COLUMNS_NAME.to_string(), json!(columns));
447
448        // Serialize primary key if present
449        if let Some(primary_key) = &self.primary_key() {
450            let pk_values: Vec<Value> = primary_key
451                .column_names()
452                .iter()
453                .map(|name| json!(name))
454                .collect();
455            obj.insert(Self::PRIMARY_KEY_NAME.to_string(), json!(pk_values));
456        }
457        Ok(Value::Object(obj))
458    }
459
460    fn deserialize_json(node: &Value) -> Result<Schema> {
461        let columns_node = node
462            .get(Self::COLUMNS_NAME)
463            .ok_or_else(|| Error::JsonSerdeError {
464                message: format!("Missing required field: {}", Self::COLUMNS_NAME),
465            })?
466            .as_array()
467            .ok_or_else(|| Error::JsonSerdeError {
468                message: format!("{} must be an array", Self::COLUMNS_NAME),
469            })?;
470
471        let mut columns = Vec::with_capacity(columns_node.len());
472        for col_node in columns_node {
473            columns.push(Column::deserialize_json(col_node)?);
474        }
475
476        let mut schema_builder = Schema::builder().with_columns(columns);
477
478        if let Some(pk_node) = node.get(Self::PRIMARY_KEY_NAME) {
479            let pk_array = pk_node
480                .as_array()
481                .ok_or_else(|| Error::invalid_table("Primary key must be an array"))?;
482
483            let mut primary_keys = Vec::with_capacity(pk_array.len());
484            for name_node in pk_array {
485                primary_keys.push(
486                    name_node.as_str().ok_or_else(|| {
487                        Error::invalid_table("Primary key element must be a string")
488                    })?,
489                );
490            }
491
492            schema_builder = schema_builder.primary_key(primary_keys);
493        }
494
495        schema_builder.build()
496    }
497}
498
499impl TableDescriptor {
500    const SCHEMA_NAME: &'static str = "schema";
501    const COMMENT_NAME: &'static str = "comment";
502    const PARTITION_KEY_NAME: &'static str = "partition_key";
503    const BUCKET_KEY_NAME: &'static str = "bucket_key";
504    const BUCKET_COUNT_NAME: &'static str = "bucket_count";
505    const PROPERTIES_NAME: &'static str = "properties";
506    const CUSTOM_PROPERTIES_NAME: &'static str = "custom_properties";
507    const VERSION_KEY: &'static str = "version";
508    const VERSION: u32 = 1;
509
510    fn deserialize_properties(node: &Value) -> Result<HashMap<String, String>> {
511        let obj = node.as_object().ok_or_else(|| Error::JsonSerdeError {
512            message: "Properties must be an object".to_string(),
513        })?;
514
515        let mut properties = HashMap::with_capacity(obj.len());
516        for (key, value) in obj {
517            properties.insert(
518                key.clone(),
519                value
520                    .as_str()
521                    .ok_or_else(|| Error::JsonSerdeError {
522                        message: "Property value must be a string".to_string(),
523                    })?
524                    .to_owned(),
525            );
526        }
527
528        Ok(properties)
529    }
530}
531
532impl JsonSerde for TableDescriptor {
533    fn serialize_json(&self) -> Result<Value> {
534        let mut obj = serde_json::Map::new();
535
536        // Serialize version
537        obj.insert(Self::VERSION_KEY.to_string(), json!(Self::VERSION));
538
539        // Serialize schema
540        obj.insert(
541            Self::SCHEMA_NAME.to_string(),
542            self.schema().serialize_json()?,
543        );
544
545        // Serialize comment if present
546        if let Some(comment) = &self.comment() {
547            obj.insert(Self::COMMENT_NAME.to_string(), json!(comment));
548        }
549
550        // Serialize partition keys
551        let partition_keys: Vec<Value> =
552            self.partition_keys().iter().map(|key| json!(key)).collect();
553        obj.insert(Self::PARTITION_KEY_NAME.to_string(), json!(partition_keys));
554
555        // Serialize table distribution if present
556        if let Some(dist) = &self.table_distribution() {
557            let bucket_keys: Vec<Value> = dist.bucket_keys().iter().map(|key| json!(key)).collect();
558            obj.insert(Self::BUCKET_KEY_NAME.to_string(), json!(bucket_keys));
559
560            if let Some(count) = dist.bucket_count() {
561                obj.insert(Self::BUCKET_COUNT_NAME.to_string(), json!(count));
562            }
563        }
564
565        // Serialize properties
566        obj.insert(Self::PROPERTIES_NAME.to_string(), json!(self.properties()));
567
568        obj.insert(
569            Self::CUSTOM_PROPERTIES_NAME.to_string(),
570            json!(self.custom_properties()),
571        );
572
573        Ok(Value::Object(obj))
574    }
575
576    fn deserialize_json(node: &Value) -> Result<Self> {
577        let mut builder = TableDescriptor::builder();
578
579        // Deserialize schema
580        let schema_node = node.get(Self::SCHEMA_NAME).ok_or_else(|| JsonSerdeError {
581            message: format!("Missing required field: {}", Self::SCHEMA_NAME),
582        })?;
583        let schema = Schema::deserialize_json(schema_node)?;
584        builder = builder.schema(schema);
585
586        // Deserialize comment if present
587        if let Some(comment_node) = node.get(Self::COMMENT_NAME) {
588            let comment = comment_node
589                .as_str()
590                .ok_or_else(|| JsonSerdeError {
591                    message: format!("{} must be a string", Self::COMMENT_NAME),
592                })?
593                .to_owned();
594            builder = builder.comment(comment.as_str());
595        }
596
597        let partition_node = node
598            .get(Self::PARTITION_KEY_NAME)
599            .ok_or_else(|| JsonSerdeError {
600                message: format!("Missing required field: {}", Self::PARTITION_KEY_NAME),
601            })?
602            .as_array()
603            .ok_or_else(|| JsonSerdeError {
604                message: format!("{} must be an array", Self::PARTITION_KEY_NAME),
605            })?;
606
607        let mut partition_keys = Vec::with_capacity(partition_node.len());
608        for key_node in partition_node {
609            partition_keys.push(
610                key_node
611                    .as_str()
612                    .ok_or_else(|| JsonSerdeError {
613                        message: format!("{} element must be a string", Self::PARTITION_KEY_NAME),
614                    })?
615                    .to_owned(),
616            );
617        }
618        builder = builder.partitioned_by(partition_keys);
619
620        let mut bucket_count = None;
621        let mut bucket_keys = vec![];
622        if let Some(bucket_key_node) = node.get(Self::BUCKET_KEY_NAME) {
623            let bucket_key_node = bucket_key_node.as_array().ok_or_else(|| JsonSerdeError {
624                message: format!("{} must be an array", Self::BUCKET_KEY_NAME),
625            })?;
626
627            for key_node in bucket_key_node {
628                bucket_keys.push(
629                    key_node
630                        .as_str()
631                        .ok_or_else(|| JsonSerdeError {
632                            message: "Bucket key must be a string".to_string(),
633                        })?
634                        .to_owned(),
635                );
636            }
637        }
638
639        if let Some(bucket_count_node) = node.get(Self::BUCKET_COUNT_NAME) {
640            bucket_count = bucket_count_node.as_u64().map(|n| n as i32);
641        }
642
643        if bucket_count.is_some() || !bucket_keys.is_empty() {
644            builder = builder.distributed_by(bucket_count, bucket_keys);
645        }
646
647        // Deserialize properties
648        let properties =
649            Self::deserialize_properties(node.get(Self::PROPERTIES_NAME).ok_or_else(|| {
650                JsonSerdeError {
651                    message: format!("Missing required field: {}", Self::PROPERTIES_NAME),
652                }
653            })?)?;
654        builder = builder.properties(properties);
655
656        // Deserialize custom properties
657        let custom_properties = Self::deserialize_properties(
658            node.get(Self::CUSTOM_PROPERTIES_NAME)
659                .ok_or_else(|| JsonSerdeError {
660                    message: format!("Missing required field: {}", Self::CUSTOM_PROPERTIES_NAME),
661                })?,
662        )?;
663        builder = builder.custom_properties(custom_properties);
664
665        builder.build()
666    }
667}
668
669#[cfg(test)]
670mod tests {
671    use super::*;
672    use crate::metadata::DataTypes;
673
674    #[test]
675    fn test_datatype_json_serde() {
676        let data_types = vec![
677            DataTypes::boolean(),
678            DataTypes::tinyint(),
679            DataTypes::smallint(),
680            DataTypes::int().as_non_nullable(),
681            DataTypes::bigint(),
682            DataTypes::float(),
683            DataTypes::double(),
684            DataTypes::char(10),
685            DataTypes::string(),
686            DataTypes::decimal(10, 2),
687            DataTypes::date(),
688            DataTypes::time(),
689            DataTypes::timestamp(),
690            DataTypes::timestamp_ltz(),
691            DataTypes::bytes(),
692            DataTypes::binary(100),
693            DataTypes::array(DataTypes::int()),
694            DataTypes::map(DataTypes::string(), DataTypes::int()),
695            DataTypes::row(vec![
696                DataField::new("f1".to_string(), DataTypes::int(), None),
697                DataField::new(
698                    "f2".to_string(),
699                    DataTypes::string(),
700                    Some("desc".to_string()),
701                ),
702            ]),
703        ];
704
705        for dt in data_types {
706            let json = dt.serialize_json().unwrap();
707            let deserialized = DataType::deserialize_json(&json).unwrap();
708            assert_eq!(dt, deserialized);
709        }
710    }
711
712    #[test]
713    fn test_invalid_datatype_validation() {
714        use serde_json::json;
715
716        // Invalid DECIMAL precision (> 38)
717        let invalid_decimal = json!({
718            "type": "DECIMAL",
719            "precision": 50,
720            "scale": 2
721        });
722        let result = DataType::deserialize_json(&invalid_decimal);
723        assert!(result.is_err());
724        assert!(
725            result
726                .unwrap_err()
727                .to_string()
728                .contains("Invalid DECIMAL parameters")
729        );
730
731        // Invalid TIME precision (> 9)
732        let invalid_time = json!({
733            "type": "TIME_WITHOUT_TIME_ZONE",
734            "precision": 15
735        });
736        let result = DataType::deserialize_json(&invalid_time);
737        assert!(result.is_err());
738        assert!(
739            result
740                .unwrap_err()
741                .to_string()
742                .contains("Invalid TIME_WITHOUT_TIME_ZONE precision")
743        );
744
745        // Invalid TIMESTAMP precision (> 9)
746        let invalid_timestamp = json!({
747            "type": "TIMESTAMP_WITHOUT_TIME_ZONE",
748            "precision": 20
749        });
750        let result = DataType::deserialize_json(&invalid_timestamp);
751        assert!(result.is_err());
752        assert!(
753            result
754                .unwrap_err()
755                .to_string()
756                .contains("Invalid TIMESTAMP_WITHOUT_TIME_ZONE precision")
757        );
758
759        // Invalid TIMESTAMP_LTZ precision (> 9)
760        let invalid_timestamp_ltz = json!({
761            "type": "TIMESTAMP_WITH_LOCAL_TIME_ZONE",
762            "precision": 10
763        });
764        let result = DataType::deserialize_json(&invalid_timestamp_ltz);
765        assert!(result.is_err());
766        assert!(
767            result
768                .unwrap_err()
769                .to_string()
770                .contains("Invalid TIMESTAMP_WITH_LOCAL_TIME_ZONE precision")
771        );
772
773        // Invalid DECIMAL scale (> precision)
774        let invalid_decimal_scale = json!({
775            "type": "DECIMAL",
776            "precision": 10,
777            "scale": 15
778        });
779        let result = DataType::deserialize_json(&invalid_decimal_scale);
780        assert!(result.is_err());
781        assert!(
782            result
783                .unwrap_err()
784                .to_string()
785                .contains("Invalid DECIMAL parameters")
786        );
787    }
788}