1use std::fmt;
19use std::hash::Hash;
20use std::sync::Arc;
21
22use crate::error::ArrowError;
23use crate::field::Field;
24use crate::{DataType, FieldRef, Fields, Metadata};
25
26#[derive(Debug, Default)]
28pub struct SchemaBuilder {
29 fields: Vec<FieldRef>,
30 metadata: Metadata,
31}
32
33impl SchemaBuilder {
34 pub fn new() -> Self {
36 Self::default()
37 }
38
39 pub fn with_capacity(capacity: usize) -> Self {
41 Self {
42 fields: Vec::with_capacity(capacity),
43 metadata: Default::default(),
44 }
45 }
46
47 pub fn push(&mut self, field: impl Into<FieldRef>) {
49 self.fields.push(field.into())
50 }
51
52 pub fn remove(&mut self, idx: usize) -> FieldRef {
58 self.fields.remove(idx)
59 }
60
61 pub fn field(&mut self, idx: usize) -> &FieldRef {
67 &mut self.fields[idx]
68 }
69
70 pub fn field_mut(&mut self, idx: usize) -> &mut FieldRef {
76 &mut self.fields[idx]
77 }
78
79 pub fn metadata(&mut self) -> &Metadata {
81 &self.metadata
82 }
83
84 pub fn metadata_mut(&mut self) -> &mut Metadata {
86 &mut self.metadata
87 }
88
89 pub fn reverse(&mut self) {
91 self.fields.reverse();
92 }
93
94 pub fn try_merge(&mut self, field: &FieldRef) -> Result<(), ArrowError> {
98 let existing = self.fields.iter_mut().find(|f| f.name() == field.name());
100 match existing {
101 Some(e) if Arc::ptr_eq(e, field) => {} Some(e) => match Arc::get_mut(e) {
103 Some(e) => e.try_merge(field.as_ref())?,
104 None => {
105 let mut t = e.as_ref().clone();
106 t.try_merge(field)?;
107 *e = Arc::new(t)
108 }
109 },
110 None => self.fields.push(field.clone()),
111 }
112 Ok(())
113 }
114
115 pub fn finish(self) -> Schema {
117 Schema {
118 fields: self.fields.into(),
119 metadata: self.metadata,
120 }
121 }
122}
123
124impl From<&Fields> for SchemaBuilder {
125 fn from(value: &Fields) -> Self {
126 Self {
127 fields: value.to_vec(),
128 metadata: Default::default(),
129 }
130 }
131}
132
133impl From<Fields> for SchemaBuilder {
134 fn from(value: Fields) -> Self {
135 Self {
136 fields: value.to_vec(),
137 metadata: Default::default(),
138 }
139 }
140}
141
142impl From<&Schema> for SchemaBuilder {
143 fn from(value: &Schema) -> Self {
144 Self::from(value.clone())
145 }
146}
147
148impl From<Schema> for SchemaBuilder {
149 fn from(value: Schema) -> Self {
150 Self {
151 fields: value.fields.to_vec(),
152 metadata: value.metadata,
153 }
154 }
155}
156
157impl Extend<FieldRef> for SchemaBuilder {
158 fn extend<T: IntoIterator<Item = FieldRef>>(&mut self, iter: T) {
159 let iter = iter.into_iter();
160 self.fields.reserve(iter.size_hint().0);
161 for f in iter {
162 self.push(f)
163 }
164 }
165}
166
167impl Extend<Field> for SchemaBuilder {
168 fn extend<T: IntoIterator<Item = Field>>(&mut self, iter: T) {
169 let iter = iter.into_iter();
170 self.fields.reserve(iter.size_hint().0);
171 for f in iter {
172 self.push(f)
173 }
174 }
175}
176
177pub type SchemaRef = Arc<Schema>;
179
180#[derive(Debug, Clone, PartialEq, Eq, Hash)]
185#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
186pub struct Schema {
187 pub fields: Fields,
189 pub metadata: Metadata,
191}
192
193impl Schema {
194 pub fn empty() -> Self {
196 Self {
197 fields: Default::default(),
198 metadata: Default::default(),
199 }
200 }
201
202 pub fn new(fields: impl Into<Fields>) -> Self {
214 Self::new_with_metadata(fields, Metadata::new())
215 }
216
217 #[inline]
230 pub fn new_with_metadata(fields: impl Into<Fields>, metadata: impl Into<Metadata>) -> Self {
231 Self {
232 fields: fields.into(),
233 metadata: metadata.into(),
234 }
235 }
236
237 pub fn with_metadata(mut self, metadata: impl Into<Metadata>) -> Self {
239 self.metadata = metadata.into();
240 self
241 }
242
243 pub fn project(&self, indices: &[usize]) -> Result<Schema, ArrowError> {
246 let new_fields = indices
247 .iter()
248 .map(|i| {
249 self.fields.get(*i).cloned().ok_or_else(|| {
250 ArrowError::SchemaError(format!(
251 "project index {} out of bounds, max field {}",
252 i,
253 self.fields().len()
254 ))
255 })
256 })
257 .collect::<Result<Vec<_>, _>>()?;
258 Ok(Self::new_with_metadata(new_fields, self.metadata.clone()))
259 }
260
261 pub fn try_merge(schemas: impl IntoIterator<Item = Self>) -> Result<Self, ArrowError> {
290 let mut out_meta = Metadata::new();
291 let mut out_fields = SchemaBuilder::new();
292 for schema in schemas {
293 let Schema { metadata, fields } = schema;
294
295 for (key, value) in metadata {
297 if let Some(old_val) = out_meta.get(&key)
298 && old_val != &value
299 {
300 return Err(ArrowError::SchemaError(format!(
301 "Fail to merge schema due to conflicting metadata. \
302 Key '{key}' has different values '{old_val}' and '{value}'"
303 )));
304 }
305 out_meta.insert(key, value);
306 }
307
308 fields.iter().try_for_each(|x| out_fields.try_merge(x))?
310 }
311
312 Ok(out_fields.finish().with_metadata(out_meta))
313 }
314
315 #[inline]
317 pub const fn fields(&self) -> &Fields {
318 &self.fields
319 }
320
321 #[inline]
358 pub fn flattened_fields(&self) -> Vec<&Field> {
359 self.fields.iter().flat_map(|f| f.fields()).collect()
360 }
361
362 pub fn field(&self, i: usize) -> &Field {
369 &self.fields[i]
370 }
371
372 pub fn field_with_name(&self, name: &str) -> Result<&Field, ArrowError> {
374 Ok(&self.fields[self.index_of(name)?])
375 }
376
377 #[deprecated(
380 since = "54.0.0",
381 note = "The ability to preserve dictionary IDs will be removed. With it, all functions related to it."
382 )]
383 pub fn fields_with_dict_id(&self, dict_id: i64) -> Vec<&Field> {
384 #[allow(deprecated)]
385 self.fields
386 .iter()
387 .flat_map(|f| f.fields_with_dict_id(dict_id))
388 .collect()
389 }
390
391 pub fn index_of(&self, name: &str) -> Result<usize, ArrowError> {
393 let (idx, _) = self.fields().find(name).ok_or_else(|| {
394 let valid_fields: Vec<_> = self.fields.iter().map(|f| f.name()).collect();
395 ArrowError::SchemaError(format!(
396 "Unable to get field named \"{name}\". Valid fields: {valid_fields:?}"
397 ))
398 })?;
399 Ok(idx)
400 }
401
402 #[inline]
404 pub const fn metadata(&self) -> &Metadata {
405 &self.metadata
406 }
407
408 pub fn normalize(&self, separator: &str, max_level: Option<usize>) -> Result<Self, ArrowError> {
452 let max_level = match max_level.unwrap_or(usize::MAX) {
453 0 => usize::MAX,
454 val => val,
455 };
456 let mut stack: Vec<(usize, Vec<&str>, &FieldRef)> = self
457 .fields()
458 .iter()
459 .rev()
460 .map(|f| {
461 let name_vec: Vec<&str> = vec![f.name()];
462 (0, name_vec, f)
463 })
464 .collect();
465 let mut fields: Vec<FieldRef> = Vec::new();
466
467 while let Some((depth, name, field_ref)) = stack.pop() {
468 match field_ref.data_type() {
469 DataType::Struct(ff) if depth < max_level => {
470 for fff in ff.into_iter().rev() {
472 let mut name = name.clone();
473 name.push(separator);
474 name.push(fff.name());
475 stack.push((depth + 1, name, fff))
476 }
477 }
478 _ => {
479 let updated_field = Field::new(
480 name.concat(),
481 field_ref.data_type().clone(),
482 field_ref.is_nullable(),
483 );
484 fields.push(Arc::new(updated_field));
485 }
486 }
487 }
488 Ok(Schema::new(fields))
489 }
490
491 pub fn column_with_name(&self, name: &str) -> Option<(usize, &Field)> {
494 let (idx, field) = self.fields.find(name)?;
495 Some((idx, field.as_ref()))
496 }
497
498 pub fn contains(&self, other: &Schema) -> bool {
505 self.fields.contains(&other.fields)
507 && other
508 .metadata
509 .iter()
510 .all(|(k, v1)| self.metadata.get(k).is_some_and(|v2| v1 == v2))
511 }
512}
513
514impl fmt::Display for Schema {
515 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
516 f.write_str(
517 &self
518 .fields
519 .iter()
520 .map(|c| c.to_string())
521 .collect::<Vec<String>>()
522 .join(", "),
523 )
524 }
525}
526
527impl AsRef<Schema> for Schema {
528 fn as_ref(&self) -> &Schema {
529 self
530 }
531}
532
533#[cfg(test)]
534mod tests {
535 use crate::datatype::DataType;
536 use crate::{TimeUnit, UnionMode};
537 use std::collections::HashMap;
538
539 use super::*;
540
541 #[test]
542 #[expect(clippy::needless_borrows_for_generic_args)] fn test_schema_as_ref() {
544 fn accept_ref(_: impl AsRef<Schema>) {}
545
546 let schema = Schema::new(vec![
547 Field::new("name", DataType::Utf8, false),
548 Field::new("address", DataType::Utf8, false),
549 Field::new("priority", DataType::UInt8, false),
550 ]);
551
552 accept_ref(schema.clone());
553 accept_ref(&schema.clone());
554 accept_ref(&&schema.clone());
555 accept_ref(Arc::new(schema.clone()));
556 accept_ref(&Arc::new(schema.clone()));
557 accept_ref(&&Arc::new(schema.clone()));
558 }
559
560 #[test]
561 #[cfg(feature = "serde")]
562 fn test_ser_de_metadata() {
563 let schema = Schema::new(vec![
565 Field::new("name", DataType::Utf8, false),
566 Field::new("address", DataType::Utf8, false),
567 Field::new("priority", DataType::UInt8, false),
568 ]);
569
570 let json = serde_json::to_string(&schema).unwrap();
571 let de_schema = serde_json::from_str(&json).unwrap();
572
573 assert_eq!(schema, de_schema);
574
575 let schema = schema.with_metadata([("key", "val")]);
577 let json = serde_json::to_string(&schema).unwrap();
578 let de_schema = serde_json::from_str(&json).unwrap();
579
580 assert_eq!(schema, de_schema);
581 }
582
583 #[test]
584 fn test_projection() {
585 let mut metadata = HashMap::new();
586 metadata.insert("meta".to_string(), "data".to_string());
587
588 let schema = Schema::new(vec![
589 Field::new("name", DataType::Utf8, false),
590 Field::new("address", DataType::Utf8, false),
591 Field::new("priority", DataType::UInt8, false),
592 ])
593 .with_metadata(metadata);
594
595 let projected: Schema = schema.project(&[0, 2]).unwrap();
596
597 assert_eq!(projected.fields().len(), 2);
598 assert_eq!(projected.fields()[0].name(), "name");
599 assert_eq!(projected.fields()[1].name(), "priority");
600 assert_eq!(projected.metadata.get("meta").unwrap(), "data")
601 }
602
603 #[test]
604 fn test_oob_projection() {
605 let mut metadata = HashMap::new();
606 metadata.insert("meta".to_string(), "data".to_string());
607
608 let schema = Schema::new(vec![
609 Field::new("name", DataType::Utf8, false),
610 Field::new("address", DataType::Utf8, false),
611 Field::new("priority", DataType::UInt8, false),
612 ])
613 .with_metadata(metadata);
614
615 let projected = schema.project(&[0, 3]);
616
617 assert!(projected.is_err());
618 if let Err(e) = projected {
619 assert_eq!(
620 e.to_string(),
621 "Schema error: project index 3 out of bounds, max field 3".to_string()
622 )
623 }
624 }
625
626 #[test]
627 fn test_schema_contains() {
628 let mut metadata1 = HashMap::new();
629 metadata1.insert("meta".to_string(), "data".to_string());
630
631 let schema1 = Schema::new(vec![
632 Field::new("name", DataType::Utf8, false),
633 Field::new("address", DataType::Utf8, false),
634 Field::new("priority", DataType::UInt8, false),
635 ])
636 .with_metadata(metadata1.clone());
637
638 let mut metadata2 = HashMap::new();
639 metadata2.insert("meta".to_string(), "data".to_string());
640 metadata2.insert("meta2".to_string(), "data".to_string());
641 let schema2 = Schema::new(vec![
642 Field::new("name", DataType::Utf8, false),
643 Field::new("address", DataType::Utf8, false),
644 Field::new("priority", DataType::UInt8, false),
645 ])
646 .with_metadata(metadata2);
647
648 assert!(schema1.contains(&schema1));
650 assert!(schema2.contains(&schema2));
651
652 assert!(!schema1.contains(&schema2));
653 assert!(schema2.contains(&schema1));
654 }
655
656 #[test]
657 fn schema_equality() {
658 let schema1 = Schema::new(vec![
659 Field::new("c1", DataType::Utf8, false),
660 Field::new("c2", DataType::Float64, true),
661 Field::new("c3", DataType::LargeBinary, true),
662 ]);
663 let schema2 = Schema::new(vec![
664 Field::new("c1", DataType::Utf8, false),
665 Field::new("c2", DataType::Float64, true),
666 Field::new("c3", DataType::LargeBinary, true),
667 ]);
668
669 assert_eq!(schema1, schema2);
670
671 let schema3 = Schema::new(vec![
672 Field::new("c1", DataType::Utf8, false),
673 Field::new("c2", DataType::Float32, true),
674 ]);
675 let schema4 = Schema::new(vec![
676 Field::new("C1", DataType::Utf8, false),
677 Field::new("C2", DataType::Float64, true),
678 ]);
679
680 assert_ne!(schema1, schema3);
681 assert_ne!(schema1, schema4);
682 assert_ne!(schema2, schema3);
683 assert_ne!(schema2, schema4);
684 assert_ne!(schema3, schema4);
685
686 let f = Field::new("c1", DataType::Utf8, false).with_metadata([("foo", "bar")]);
687 let schema5 = Schema::new(vec![
688 f,
689 Field::new("c2", DataType::Float64, true),
690 Field::new("c3", DataType::LargeBinary, true),
691 ]);
692 assert_ne!(schema1, schema5);
693 }
694
695 #[test]
696 fn create_schema_string() {
697 let schema = person_schema();
698 assert_eq!(
699 schema.to_string(),
700 "Field { \"first_name\": Utf8, metadata: {\"k\": \"v\"} }, \
701 Field { \"last_name\": Utf8 }, \
702 Field { \"address\": Struct(\"street\": non-null Utf8, \"zip\": non-null UInt16) }, \
703 Field { \"interests\": nullable Dictionary(Int32, Utf8), dict_id: 123, dict_is_ordered }"
704 )
705 }
706
707 #[test]
708 fn schema_field_accessors() {
709 let schema = person_schema();
710
711 assert_eq!(schema.fields().len(), 4);
713
714 let first_name = &schema.fields()[0];
716 assert_eq!(first_name.name(), "first_name");
717 assert_eq!(first_name.data_type(), &DataType::Utf8);
718 assert!(!first_name.is_nullable());
719 #[allow(deprecated)]
720 let dict_id = first_name.dict_id();
721 assert_eq!(dict_id, None);
722 assert_eq!(first_name.dict_is_ordered(), None);
723
724 let metadata = first_name.metadata();
725 assert!(!metadata.is_empty());
726 let md = &metadata;
727 assert_eq!(md.len(), 1);
728 let key = md.get("k");
729 assert!(key.is_some());
730 assert_eq!(key.unwrap(), "v");
731
732 let interests = &schema.fields()[3];
733 assert_eq!(interests.name(), "interests");
734 assert_eq!(
735 interests.data_type(),
736 &DataType::Dictionary(Box::new(DataType::Int32), Box::new(DataType::Utf8))
737 );
738 #[allow(deprecated)]
739 let dict_id = interests.dict_id();
740 assert_eq!(dict_id, Some(123));
741 assert_eq!(interests.dict_is_ordered(), Some(true));
742 }
743
744 #[test]
745 #[should_panic(
746 expected = "Unable to get field named \\\"nickname\\\". Valid fields: [\\\"first_name\\\", \\\"last_name\\\", \\\"address\\\", \\\"interests\\\"]"
747 )]
748 fn schema_index_of() {
749 let schema = person_schema();
750 assert_eq!(schema.index_of("first_name").unwrap(), 0);
751 assert_eq!(schema.index_of("last_name").unwrap(), 1);
752 schema.index_of("nickname").unwrap();
753 }
754
755 #[test]
756 fn normalize_simple() {
757 let schema = Schema::new(vec![
758 Field::new(
759 "a",
760 DataType::Struct(Fields::from(vec![
761 Arc::new(Field::new("animals", DataType::Utf8, true)),
762 Arc::new(Field::new("n_legs", DataType::Int64, true)),
763 Arc::new(Field::new("year", DataType::Int64, true)),
764 ])),
765 false,
766 ),
767 Field::new("month", DataType::Int64, true),
768 ])
769 .normalize(".", Some(0))
770 .expect("valid normalization");
771
772 let expected = Schema::new(vec![
773 Field::new("a.animals", DataType::Utf8, true),
774 Field::new("a.n_legs", DataType::Int64, true),
775 Field::new("a.year", DataType::Int64, true),
776 Field::new("month", DataType::Int64, true),
777 ]);
778
779 assert_eq!(schema, expected);
780
781 let schema = Schema::new(vec![
783 Field::new(
784 "a",
785 DataType::Struct(Fields::from(vec![
786 Arc::new(Field::new("animals", DataType::Utf8, true)),
787 Arc::new(Field::new("n_legs", DataType::Int64, true)),
788 Arc::new(Field::new("year", DataType::Int64, true)),
789 ])),
790 false,
791 ),
792 Field::new("month", DataType::Int64, true),
793 ])
794 .normalize(".", None)
795 .expect("valid normalization");
796
797 assert_eq!(schema, expected);
798 }
799
800 #[test]
801 fn normalize_nested() {
802 let a = Arc::new(Field::new("a", DataType::Utf8, true));
803 let b = Arc::new(Field::new("b", DataType::Int64, false));
804 let c = Arc::new(Field::new("c", DataType::Int64, true));
805
806 let d = Arc::new(Field::new("d", DataType::Utf8, true));
807 let e = Arc::new(Field::new("e", DataType::Int64, false));
808 let f = Arc::new(Field::new("f", DataType::Int64, true));
809
810 let one = Arc::new(Field::new(
811 "1",
812 DataType::Struct(Fields::from(vec![a.clone(), b.clone(), c.clone()])),
813 false,
814 ));
815 let two = Arc::new(Field::new(
816 "2",
817 DataType::Struct(Fields::from(vec![d.clone(), e.clone(), f.clone()])),
818 true,
819 ));
820
821 let exclamation = Arc::new(Field::new(
822 "!",
823 DataType::Struct(Fields::from(vec![one, two])),
824 false,
825 ));
826
827 let normalize_all = Schema::new(vec![exclamation.clone()])
828 .normalize(".", Some(0))
829 .expect("valid normalization");
830
831 let expected = Schema::new(vec![
832 Field::new("!.1.a", DataType::Utf8, true),
833 Field::new("!.1.b", DataType::Int64, false),
834 Field::new("!.1.c", DataType::Int64, true),
835 Field::new("!.2.d", DataType::Utf8, true),
836 Field::new("!.2.e", DataType::Int64, false),
837 Field::new("!.2.f", DataType::Int64, true),
838 ]);
839
840 assert_eq!(normalize_all, expected);
841
842 let normalize_depth_one = Schema::new(vec![exclamation])
843 .normalize(".", Some(1))
844 .expect("valid normalization");
845
846 let expected = Schema::new(vec![
847 Field::new("!.1", DataType::Struct(Fields::from(vec![a, b, c])), false),
848 Field::new("!.2", DataType::Struct(Fields::from(vec![d, e, f])), true),
849 ]);
850
851 assert_eq!(normalize_depth_one, expected);
852 }
853
854 #[test]
855 fn normalize_list() {
856 let a = Arc::new(Field::new("a", DataType::Utf8, true));
858 let b = Arc::new(Field::new("b", DataType::Int64, false));
859 let c = Arc::new(Field::new("c", DataType::Int64, true));
860 let d = Arc::new(Field::new("d", DataType::Utf8, true));
861 let e = Arc::new(Field::new("e", DataType::Int64, false));
862 let f = Arc::new(Field::new("f", DataType::Int64, true));
863
864 let one = Arc::new(Field::new(
865 "1",
866 DataType::Struct(Fields::from(vec![a.clone(), b.clone(), c.clone()])),
867 true,
868 ));
869
870 let two = Arc::new(Field::new(
871 "2",
872 DataType::List(Arc::new(Field::new_list_field(
873 DataType::Struct(Fields::from(vec![d.clone(), e.clone(), f.clone()])),
874 true,
875 ))),
876 false,
877 ));
878
879 let exclamation = Arc::new(Field::new(
880 "!",
881 DataType::Struct(Fields::from(vec![one.clone(), two.clone()])),
882 false,
883 ));
884
885 let normalize_all = Schema::new(vec![exclamation.clone()])
886 .normalize(".", None)
887 .expect("valid normalization");
888
889 let expected = Schema::new(vec![
891 Field::new("!.1.a", DataType::Utf8, true),
892 Field::new("!.1.b", DataType::Int64, false),
893 Field::new("!.1.c", DataType::Int64, true),
894 Field::new(
895 "!.2",
896 DataType::List(Arc::new(Field::new_list_field(
897 DataType::Struct(Fields::from(vec![d.clone(), e.clone(), f.clone()])),
898 true,
899 ))),
900 false,
901 ),
902 ]);
903
904 assert_eq!(normalize_all, expected);
905 assert_eq!(normalize_all.fields().len(), 4);
906
907 let two = Arc::new(Field::new(
909 "2",
910 DataType::FixedSizeList(
911 Arc::new(Field::new_fixed_size_list(
912 "3",
913 Arc::new(Field::new_list_field(
914 DataType::Struct(Fields::from(vec![d.clone(), e.clone(), f.clone()])),
915 true,
916 )),
917 1,
918 true,
919 )),
920 1,
921 ),
922 false,
923 ));
924
925 let exclamation = Arc::new(Field::new(
926 "!",
927 DataType::Struct(Fields::from(vec![one.clone(), two])),
928 false,
929 ));
930
931 let normalize_all = Schema::new(vec![exclamation.clone()])
932 .normalize(".", None)
933 .expect("valid normalization");
934
935 let expected = Schema::new(vec![
937 Field::new("!.1.a", DataType::Utf8, true),
938 Field::new("!.1.b", DataType::Int64, false),
939 Field::new("!.1.c", DataType::Int64, true),
940 Field::new(
941 "!.2",
942 DataType::FixedSizeList(
943 Arc::new(Field::new_fixed_size_list(
944 "3",
945 Arc::new(Field::new_list_field(
946 DataType::Struct(Fields::from(vec![d.clone(), e.clone(), f.clone()])),
947 true,
948 )),
949 1,
950 true,
951 )),
952 1,
953 ),
954 false,
955 ),
956 ]);
957
958 assert_eq!(normalize_all, expected);
959 assert_eq!(normalize_all.fields().len(), 4);
960
961 let two = Arc::new(Field::new(
963 "2",
964 DataType::FixedSizeList(
965 Arc::new(Field::new_large_list(
966 "3",
967 Arc::new(Field::new_list_field(
968 DataType::Struct(Fields::from(vec![d.clone(), e.clone(), f.clone()])),
969 true,
970 )),
971 true,
972 )),
973 1,
974 ),
975 false,
976 ));
977
978 let exclamation = Arc::new(Field::new(
979 "!",
980 DataType::Struct(Fields::from(vec![one.clone(), two])),
981 false,
982 ));
983
984 let normalize_all = Schema::new(vec![exclamation.clone()])
985 .normalize(".", None)
986 .expect("valid normalization");
987
988 let expected = Schema::new(vec![
990 Field::new("!.1.a", DataType::Utf8, true),
991 Field::new("!.1.b", DataType::Int64, false),
992 Field::new("!.1.c", DataType::Int64, true),
993 Field::new(
994 "!.2",
995 DataType::FixedSizeList(
996 Arc::new(Field::new_large_list(
997 "3",
998 Arc::new(Field::new_list_field(
999 DataType::Struct(Fields::from(vec![d.clone(), e.clone(), f.clone()])),
1000 true,
1001 )),
1002 true,
1003 )),
1004 1,
1005 ),
1006 false,
1007 ),
1008 ]);
1009
1010 assert_eq!(normalize_all, expected);
1011 assert_eq!(normalize_all.fields().len(), 4);
1012 }
1013
1014 #[test]
1015 fn normalize_deep_nested() {
1016 let a = Arc::new(Field::new("a", DataType::Utf8, true));
1018 let b = Arc::new(Field::new("b", DataType::Int64, false));
1019 let c = Arc::new(Field::new("c", DataType::Int64, true));
1020 let d = Arc::new(Field::new("d", DataType::Utf8, true));
1021 let e = Arc::new(Field::new("e", DataType::Int64, false));
1022 let f = Arc::new(Field::new("f", DataType::Int64, true));
1023
1024 let one = Arc::new(Field::new(
1025 "1",
1026 DataType::Struct(Fields::from(vec![a.clone(), b.clone(), c.clone()])),
1027 true,
1028 ));
1029
1030 let two = Arc::new(Field::new(
1031 "2",
1032 DataType::List(Arc::new(Field::new_list_field(
1033 DataType::Struct(Fields::from(vec![d.clone(), e.clone(), f.clone()])),
1034 true,
1035 ))),
1036 false,
1037 ));
1038
1039 let l10 = Arc::new(Field::new(
1040 "l10",
1041 DataType::List(Arc::new(Field::new_list_field(
1042 DataType::Struct(Fields::from(vec![one, two])),
1043 true,
1044 ))),
1045 false,
1046 ));
1047
1048 let l9 = Arc::new(Field::new(
1049 "l9",
1050 DataType::List(Arc::new(Field::new_list_field(
1051 DataType::Struct(Fields::from(vec![l10])),
1052 true,
1053 ))),
1054 false,
1055 ));
1056
1057 let l8 = Arc::new(Field::new(
1058 "l8",
1059 DataType::List(Arc::new(Field::new_list_field(
1060 DataType::Struct(Fields::from(vec![l9])),
1061 true,
1062 ))),
1063 false,
1064 ));
1065 let l7 = Arc::new(Field::new(
1066 "l7",
1067 DataType::List(Arc::new(Field::new_list_field(
1068 DataType::Struct(Fields::from(vec![l8])),
1069 true,
1070 ))),
1071 false,
1072 ));
1073 let l6 = Arc::new(Field::new(
1074 "l6",
1075 DataType::List(Arc::new(Field::new_list_field(
1076 DataType::Struct(Fields::from(vec![l7])),
1077 true,
1078 ))),
1079 false,
1080 ));
1081 let l5 = Arc::new(Field::new(
1082 "l5",
1083 DataType::List(Arc::new(Field::new_list_field(
1084 DataType::Struct(Fields::from(vec![l6])),
1085 true,
1086 ))),
1087 false,
1088 ));
1089 let l4 = Arc::new(Field::new(
1090 "l4",
1091 DataType::List(Arc::new(Field::new_list_field(
1092 DataType::Struct(Fields::from(vec![l5])),
1093 true,
1094 ))),
1095 false,
1096 ));
1097 let l3 = Arc::new(Field::new(
1098 "l3",
1099 DataType::List(Arc::new(Field::new_list_field(
1100 DataType::Struct(Fields::from(vec![l4])),
1101 true,
1102 ))),
1103 false,
1104 ));
1105 let l2 = Arc::new(Field::new(
1106 "l2",
1107 DataType::List(Arc::new(Field::new_list_field(
1108 DataType::Struct(Fields::from(vec![l3])),
1109 true,
1110 ))),
1111 false,
1112 ));
1113 let l1 = Arc::new(Field::new(
1114 "l1",
1115 DataType::List(Arc::new(Field::new_list_field(
1116 DataType::Struct(Fields::from(vec![l2])),
1117 true,
1118 ))),
1119 false,
1120 ));
1121
1122 let normalize_all = Schema::new(vec![l1])
1123 .normalize(".", None)
1124 .expect("valid normalization");
1125
1126 assert_eq!(normalize_all.fields().len(), 1);
1127 }
1128
1129 #[test]
1130 fn normalize_dictionary() {
1131 let a = Arc::new(Field::new("a", DataType::Utf8, true));
1132 let b = Arc::new(Field::new("b", DataType::Int64, false));
1133
1134 let one = Arc::new(Field::new(
1135 "1",
1136 DataType::Dictionary(
1137 Box::new(DataType::Int32),
1138 Box::new(DataType::Struct(Fields::from(vec![a.clone(), b.clone()]))),
1139 ),
1140 false,
1141 ));
1142
1143 let normalize_all = Schema::new(vec![one.clone()])
1144 .normalize(".", None)
1145 .expect("valid normalization");
1146
1147 let expected = Schema::new(vec![Field::new(
1148 "1",
1149 DataType::Dictionary(
1150 Box::new(DataType::Int32),
1151 Box::new(DataType::Struct(Fields::from(vec![a.clone(), b.clone()]))),
1152 ),
1153 false,
1154 )]);
1155
1156 assert_eq!(normalize_all, expected);
1157 }
1158
1159 #[test]
1160 #[should_panic(
1161 expected = "Unable to get field named \\\"nickname\\\". Valid fields: [\\\"first_name\\\", \\\"last_name\\\", \\\"address\\\", \\\"interests\\\"]"
1162 )]
1163 fn schema_field_with_name() {
1164 let schema = person_schema();
1165 assert_eq!(
1166 schema.field_with_name("first_name").unwrap().name(),
1167 "first_name"
1168 );
1169 assert_eq!(
1170 schema.field_with_name("last_name").unwrap().name(),
1171 "last_name"
1172 );
1173 schema.field_with_name("nickname").unwrap();
1174 }
1175
1176 #[test]
1177 fn schema_field_with_dict_id() {
1178 let schema = person_schema();
1179
1180 #[allow(deprecated)]
1181 let fields_dict_123: Vec<_> = schema
1182 .fields_with_dict_id(123)
1183 .iter()
1184 .map(|f| f.name())
1185 .collect();
1186 assert_eq!(fields_dict_123, vec!["interests"]);
1187
1188 #[allow(deprecated)]
1189 let is_empty = schema.fields_with_dict_id(456).is_empty();
1190 assert!(is_empty);
1191 }
1192
1193 fn person_schema() -> Schema {
1194 let kv_array = [("k".to_string(), "v".to_string())];
1195 let field_metadata: HashMap<String, String> = kv_array.iter().cloned().collect();
1196 let first_name =
1197 Field::new("first_name", DataType::Utf8, false).with_metadata(field_metadata);
1198
1199 Schema::new(vec![
1200 first_name,
1201 Field::new("last_name", DataType::Utf8, false),
1202 Field::new(
1203 "address",
1204 DataType::Struct(Fields::from(vec![
1205 Field::new("street", DataType::Utf8, false),
1206 Field::new("zip", DataType::UInt16, false),
1207 ])),
1208 false,
1209 ),
1210 #[allow(deprecated)]
1211 Field::new_dict(
1212 "interests",
1213 DataType::Dictionary(Box::new(DataType::Int32), Box::new(DataType::Utf8)),
1214 true,
1215 123,
1216 true,
1217 ),
1218 ])
1219 }
1220
1221 #[test]
1222 fn test_try_merge_field_with_metadata() {
1223 let metadata1: HashMap<String, String> = [("foo".to_string(), "bar".to_string())]
1225 .iter()
1226 .cloned()
1227 .collect();
1228 let f1 = Field::new("first_name", DataType::Utf8, false).with_metadata(metadata1);
1229
1230 let metadata2: HashMap<String, String> = [("foo".to_string(), "baz".to_string())]
1231 .iter()
1232 .cloned()
1233 .collect();
1234 let f2 = Field::new("first_name", DataType::Utf8, false).with_metadata(metadata2);
1235
1236 assert!(Schema::try_merge(vec![Schema::new(vec![f1]), Schema::new(vec![f2])]).is_err());
1237
1238 let mut f1 = Field::new("first_name", DataType::Utf8, false);
1240 let metadata2: HashMap<String, String> = [("missing".to_string(), "value".to_string())]
1241 .iter()
1242 .cloned()
1243 .collect();
1244 let f2 = Field::new("first_name", DataType::Utf8, false).with_metadata(metadata2);
1245
1246 assert!(f1.try_merge(&f2).is_ok());
1247 assert!(!f1.metadata().is_empty());
1248 assert_eq!(f1.metadata(), f2.metadata());
1249
1250 let mut f1 =
1252 Field::new("first_name", DataType::Utf8, false).with_metadata([("foo", "bar")]);
1253 let f2 = Field::new("first_name", DataType::Utf8, false).with_metadata([("foo2", "bar2")]);
1254
1255 assert!(f1.try_merge(&f2).is_ok());
1256 assert!(!f1.metadata().is_empty());
1257 assert_eq!(
1258 f1.metadata(),
1259 &Metadata::from([("foo", "bar"), ("foo2", "bar2")])
1260 );
1261
1262 let mut f1 =
1264 Field::new("first_name", DataType::Utf8, false).with_metadata([("foo", "bar")]);
1265 let f2 = Field::new("first_name", DataType::Utf8, false);
1266 assert!(f1.try_merge(&f2).is_ok());
1267 assert!(!f1.metadata().is_empty());
1268 assert_eq!(f1.metadata(), &Metadata::from([("foo", "bar")]));
1269
1270 let mut f1 = Field::new("first_name", DataType::Utf8, false);
1272 let f2 = Field::new("first_name", DataType::Utf8, false);
1273 assert!(f1.try_merge(&f2).is_ok());
1274 assert!(f1.metadata().is_empty());
1275 }
1276
1277 #[test]
1278 fn test_schema_merge() {
1279 let merged = Schema::try_merge(vec![
1280 Schema::new(vec![
1281 Field::new("first_name", DataType::Utf8, false),
1282 Field::new("last_name", DataType::Utf8, false),
1283 Field::new(
1284 "address",
1285 DataType::Struct(vec![Field::new("zip", DataType::UInt16, false)].into()),
1286 false,
1287 ),
1288 ]),
1289 Schema::new_with_metadata(
1290 vec![
1291 Field::new("last_name", DataType::Utf8, true),
1293 Field::new(
1294 "address",
1295 DataType::Struct(Fields::from(vec![
1296 Field::new("street", DataType::Utf8, false),
1298 Field::new("zip", DataType::UInt16, true),
1300 ])),
1301 false,
1302 ),
1303 Field::new("number", DataType::Utf8, true),
1305 ],
1306 [("foo".to_string(), "bar".to_string())]
1307 .iter()
1308 .cloned()
1309 .collect::<HashMap<String, String>>(),
1310 ),
1311 ])
1312 .unwrap();
1313
1314 assert_eq!(
1315 merged,
1316 Schema::new_with_metadata(
1317 vec![
1318 Field::new("first_name", DataType::Utf8, false),
1319 Field::new("last_name", DataType::Utf8, true),
1320 Field::new(
1321 "address",
1322 DataType::Struct(Fields::from(vec![
1323 Field::new("zip", DataType::UInt16, true),
1324 Field::new("street", DataType::Utf8, false),
1325 ])),
1326 false,
1327 ),
1328 Field::new("number", DataType::Utf8, true),
1329 ],
1330 [("foo".to_string(), "bar".to_string())]
1331 .iter()
1332 .cloned()
1333 .collect::<HashMap<String, String>>()
1334 )
1335 );
1336
1337 assert_eq!(
1339 Schema::try_merge(vec![
1340 Schema::new(vec![Field::new_union(
1341 "c1",
1342 vec![0, 1],
1343 vec![
1344 Field::new("c11", DataType::Utf8, true),
1345 Field::new("c12", DataType::Utf8, true),
1346 ],
1347 UnionMode::Dense
1348 ),]),
1349 Schema::new(vec![Field::new_union(
1350 "c1",
1351 vec![1, 2],
1352 vec![
1353 Field::new("c12", DataType::Utf8, true),
1354 Field::new("c13", DataType::Time64(TimeUnit::Second), true),
1355 ],
1356 UnionMode::Dense
1357 ),])
1358 ])
1359 .unwrap(),
1360 Schema::new(vec![Field::new_union(
1361 "c1",
1362 vec![0, 1, 2],
1363 vec![
1364 Field::new("c11", DataType::Utf8, true),
1365 Field::new("c12", DataType::Utf8, true),
1366 Field::new("c13", DataType::Time64(TimeUnit::Second), true),
1367 ],
1368 UnionMode::Dense
1369 ),]),
1370 );
1371
1372 assert!(
1374 Schema::try_merge(vec![
1375 Schema::new(vec![
1376 Field::new("first_name", DataType::Utf8, false),
1377 Field::new("last_name", DataType::Utf8, false),
1378 ]),
1379 Schema::new(vec![Field::new("last_name", DataType::Int64, false),])
1380 ])
1381 .is_err()
1382 );
1383
1384 let res = Schema::try_merge(vec![
1386 Schema::new_with_metadata(
1387 vec![Field::new("first_name", DataType::Utf8, false)],
1388 [("foo".to_string(), "bar".to_string())]
1389 .iter()
1390 .cloned()
1391 .collect::<HashMap<String, String>>(),
1392 ),
1393 Schema::new_with_metadata(
1394 vec![Field::new("last_name", DataType::Utf8, false)],
1395 [("foo".to_string(), "baz".to_string())]
1396 .iter()
1397 .cloned()
1398 .collect::<HashMap<String, String>>(),
1399 ),
1400 ])
1401 .unwrap_err();
1402
1403 let expected = "Fail to merge schema due to conflicting metadata. Key 'foo' has different values 'bar' and 'baz'";
1404 assert!(
1405 res.to_string().contains(expected),
1406 "Could not find expected string '{expected}' in '{res}'"
1407 );
1408 }
1409
1410 #[test]
1411 fn test_schema_builder_change_field() {
1412 let mut builder = SchemaBuilder::new();
1413 builder.push(Field::new("a", DataType::Int32, false));
1414 builder.push(Field::new("b", DataType::Utf8, false));
1415 *builder.field_mut(1) = Arc::new(Field::new("c", DataType::Int32, false));
1416 assert_eq!(
1417 builder.fields,
1418 vec![
1419 Arc::new(Field::new("a", DataType::Int32, false)),
1420 Arc::new(Field::new("c", DataType::Int32, false))
1421 ]
1422 );
1423 }
1424
1425 #[test]
1426 fn test_schema_builder_reverse() {
1427 let mut builder = SchemaBuilder::new();
1428 builder.push(Field::new("a", DataType::Int32, false));
1429 builder.push(Field::new("b", DataType::Utf8, true));
1430 builder.reverse();
1431 assert_eq!(
1432 builder.fields,
1433 vec![
1434 Arc::new(Field::new("b", DataType::Utf8, true)),
1435 Arc::new(Field::new("a", DataType::Int32, false))
1436 ]
1437 );
1438 }
1439
1440 #[test]
1441 fn test_schema_builder_metadata() {
1442 let mut metadata: HashMap<String, String> = HashMap::with_capacity(1);
1443 metadata.insert("key".to_string(), "value".to_string());
1444
1445 let fields = vec![Field::new("test", DataType::Int8, true)];
1446 let mut builder: SchemaBuilder = Schema::new(fields).with_metadata(metadata).into();
1447 builder.metadata_mut().insert("k", "v");
1448 let out = builder.finish();
1449 assert_eq!(out.metadata.len(), 2);
1450 assert_eq!(out.metadata["k"], "v");
1451 assert_eq!(out.metadata["key"], "value");
1452 }
1453}