|
14 | 14 | // KIND, either express or implied. See the License for the
|
15 | 15 | // specific language governing permissions and limitations
|
16 | 16 | // under the License.
|
| 17 | + |
17 | 18 | use crate::decoder::{map_bytes_to_offsets, OffsetSizeBytes};
|
18 | 19 | use crate::utils::{
|
19 | 20 | first_byte_from_slice, overflow_error, slice_from_slice, try_binary_search_range_by,
|
20 | 21 | };
|
21 | 22 | use crate::variant::{Variant, VariantMetadata};
|
| 23 | +use std::collections::HashMap; |
22 | 24 |
|
23 | 25 | use arrow_schema::ArrowError;
|
24 | 26 |
|
@@ -114,7 +116,7 @@ impl VariantObjectHeader {
|
114 | 116 | ///
|
115 | 117 | /// [valid]: VariantMetadata#Validation
|
116 | 118 | /// [Variant spec]: https://github.com/apache/parquet-format/blob/master/VariantEncoding.md#value-data-for-object-basic_type2
|
117 |
| -#[derive(Debug, Clone, PartialEq)] |
| 119 | +#[derive(Debug, Clone)] |
118 | 120 | pub struct VariantObject<'m, 'v> {
|
119 | 121 | pub metadata: VariantMetadata<'m>,
|
120 | 122 | pub value: &'v [u8],
|
@@ -387,6 +389,31 @@ impl<'m, 'v> VariantObject<'m, 'v> {
|
387 | 389 | }
|
388 | 390 | }
|
389 | 391 |
|
| 392 | +impl<'m, 'v> PartialEq for VariantObject<'m, 'v> { |
| 393 | + fn eq(&self, other: &Self) -> bool { |
| 394 | + let mut is_equal = self.metadata == other.metadata |
| 395 | + && self.header == other.header |
| 396 | + && self.num_elements == other.num_elements |
| 397 | + && self.first_field_offset_byte == other.first_field_offset_byte |
| 398 | + && self.first_value_byte == other.first_value_byte |
| 399 | + && self.validated == other.validated; |
| 400 | + |
| 401 | + // value validation |
| 402 | + let other_fields: HashMap<&str, Variant> = HashMap::from_iter(other.iter()); |
| 403 | + |
| 404 | + for (field_name, variant) in self.iter() { |
| 405 | + match other_fields.get(field_name as &str) { |
| 406 | + Some(other_variant) => { |
| 407 | + is_equal = is_equal && variant == *other_variant; |
| 408 | + } |
| 409 | + None => return false, |
| 410 | + } |
| 411 | + } |
| 412 | + |
| 413 | + is_equal |
| 414 | + } |
| 415 | +} |
| 416 | + |
390 | 417 | #[cfg(test)]
|
391 | 418 | mod tests {
|
392 | 419 | use crate::VariantBuilder;
|
@@ -718,4 +745,176 @@ mod tests {
|
718 | 745 | test_variant_object_with_large_data(16777216 + 1, OffsetSizeBytes::Four);
|
719 | 746 | // 2^24
|
720 | 747 | }
|
| 748 | + |
| 749 | + #[test] |
| 750 | + fn test_objects_with_same_fields_are_equal() { |
| 751 | + let mut b = VariantBuilder::new(); |
| 752 | + let mut o = b.new_object(); |
| 753 | + |
| 754 | + o.insert("b", ()); |
| 755 | + o.insert("c", ()); |
| 756 | + o.insert("a", ()); |
| 757 | + |
| 758 | + o.finish().unwrap(); |
| 759 | + |
| 760 | + let (m, v) = b.finish(); |
| 761 | + |
| 762 | + let v1 = Variant::try_new(&m, &v).unwrap(); |
| 763 | + let v2 = Variant::try_new(&m, &v).unwrap(); |
| 764 | + |
| 765 | + assert_eq!(v1, v2); |
| 766 | + } |
| 767 | + |
| 768 | + #[test] |
| 769 | + fn test_same_objects_with_different_builder_are_equal() { |
| 770 | + let mut b = VariantBuilder::new(); |
| 771 | + let mut o = b.new_object(); |
| 772 | + |
| 773 | + o.insert("a", ()); |
| 774 | + o.insert("b", false); |
| 775 | + |
| 776 | + o.finish().unwrap(); |
| 777 | + let (m, v) = b.finish(); |
| 778 | + |
| 779 | + let v1 = Variant::try_new(&m, &v).unwrap(); |
| 780 | + |
| 781 | + let mut b = VariantBuilder::new(); |
| 782 | + let mut o = b.new_object(); |
| 783 | + |
| 784 | + o.insert("a", ()); |
| 785 | + o.insert("b", false); |
| 786 | + |
| 787 | + o.finish().unwrap(); |
| 788 | + let (m, v) = b.finish(); |
| 789 | + |
| 790 | + let v2 = Variant::try_new(&m, &v).unwrap(); |
| 791 | + |
| 792 | + assert_eq!(v1, v2); |
| 793 | + } |
| 794 | + |
| 795 | + #[test] |
| 796 | + fn test_objects_with_different_values_are_not_equal() { |
| 797 | + let mut b = VariantBuilder::new(); |
| 798 | + let mut o = b.new_object(); |
| 799 | + |
| 800 | + o.insert("a", ()); |
| 801 | + o.insert("b", 4.3); |
| 802 | + |
| 803 | + o.finish().unwrap(); |
| 804 | + |
| 805 | + let (m, v) = b.finish(); |
| 806 | + |
| 807 | + let v1 = Variant::try_new(&m, &v).unwrap(); |
| 808 | + |
| 809 | + // second object, same field name but different values |
| 810 | + let mut b = VariantBuilder::new(); |
| 811 | + let mut o = b.new_object(); |
| 812 | + |
| 813 | + o.insert("a", ()); |
| 814 | + let mut inner_o = o.new_object("b"); |
| 815 | + inner_o.insert("c", 3.3); |
| 816 | + inner_o.finish().unwrap(); |
| 817 | + o.finish().unwrap(); |
| 818 | + |
| 819 | + let (m, v) = b.finish(); |
| 820 | + let v2 = Variant::try_new(&m, &v).unwrap(); |
| 821 | + |
| 822 | + assert_ne!(v1, v2); |
| 823 | + } |
| 824 | + |
| 825 | + #[test] |
| 826 | + fn test_objects_with_different_field_names_are_not_equal() { |
| 827 | + let mut b = VariantBuilder::new(); |
| 828 | + let mut o = b.new_object(); |
| 829 | + |
| 830 | + o.insert("a", ()); |
| 831 | + o.insert("b", 4.3); |
| 832 | + |
| 833 | + o.finish().unwrap(); |
| 834 | + |
| 835 | + let (m, v) = b.finish(); |
| 836 | + |
| 837 | + let v1 = Variant::try_new(&m, &v).unwrap(); |
| 838 | + |
| 839 | + // second object, same field name but different values |
| 840 | + let mut b = VariantBuilder::new(); |
| 841 | + let mut o = b.new_object(); |
| 842 | + |
| 843 | + o.insert("aardvark", ()); |
| 844 | + o.insert("barracuda", 3.3); |
| 845 | + |
| 846 | + o.finish().unwrap(); |
| 847 | + |
| 848 | + let (m, v) = b.finish(); |
| 849 | + let v2 = Variant::try_new(&m, &v).unwrap(); |
| 850 | + |
| 851 | + assert_ne!(v1, v2); |
| 852 | + } |
| 853 | + |
| 854 | + #[test] |
| 855 | + fn test_objects_with_different_insertion_order_are_equal() { |
| 856 | + let mut b = VariantBuilder::new(); |
| 857 | + let mut o = b.new_object(); |
| 858 | + |
| 859 | + o.insert("b", false); |
| 860 | + o.insert("a", ()); |
| 861 | + |
| 862 | + o.finish().unwrap(); |
| 863 | + |
| 864 | + let (m, v) = b.finish(); |
| 865 | + |
| 866 | + let v1 = Variant::try_new(&m, &v).unwrap(); |
| 867 | + assert!(!v1.metadata().unwrap().is_sorted()); |
| 868 | + |
| 869 | + // create another object pre-filled with field names, b and a |
| 870 | + // but insert the fields in the order of a, b |
| 871 | + let mut b = VariantBuilder::new().with_field_names(["b", "a"].into_iter()); |
| 872 | + let mut o = b.new_object(); |
| 873 | + |
| 874 | + o.insert("a", ()); |
| 875 | + o.insert("b", false); |
| 876 | + |
| 877 | + o.finish().unwrap(); |
| 878 | + |
| 879 | + let (m, v) = b.finish(); |
| 880 | + |
| 881 | + let v2 = Variant::try_new(&m, &v).unwrap(); |
| 882 | + |
| 883 | + // v2 should also have a unsorted dictionary |
| 884 | + assert!(!v2.metadata().unwrap().is_sorted()); |
| 885 | + |
| 886 | + assert_eq!(v1, v2); |
| 887 | + } |
| 888 | + |
| 889 | + #[test] |
| 890 | + fn test_objects_with_differing_metadata_are_not_equal() { |
| 891 | + let mut b = VariantBuilder::new(); |
| 892 | + let mut o = b.new_object(); |
| 893 | + |
| 894 | + o.insert("a", ()); |
| 895 | + o.insert("b", 4.3); |
| 896 | + |
| 897 | + o.finish().unwrap(); |
| 898 | + |
| 899 | + let (m, v) = b.finish(); |
| 900 | + |
| 901 | + let v1 = Variant::try_new(&m, &v).unwrap(); |
| 902 | + assert!(v1.metadata().unwrap().is_sorted()); |
| 903 | + |
| 904 | + // create a second object with different insertion order |
| 905 | + let mut b = VariantBuilder::new(); |
| 906 | + let mut o = b.new_object(); |
| 907 | + |
| 908 | + o.insert("b", 4.3); |
| 909 | + o.insert("a", ()); |
| 910 | + |
| 911 | + o.finish().unwrap(); |
| 912 | + |
| 913 | + let (m, v) = b.finish(); |
| 914 | + |
| 915 | + let v2 = Variant::try_new(&m, &v).unwrap(); |
| 916 | + assert!(!v2.metadata().unwrap().is_sorted()); |
| 917 | + |
| 918 | + assert_ne!(v1, v2); |
| 919 | + } |
721 | 920 | }
|
0 commit comments