| 1700 | |
| 1701 | #[test] |
| 1702 | fn struct_nullability() { |
| 1703 | let do_test = |child: DataType| { |
| 1704 | // Test correctly enforced nullability |
| 1705 | let non_null = r#"{"foo": {}}"#; |
| 1706 | let schema = Arc::new(Schema::new(vec![Field::new_struct( |
| 1707 | "foo", |
| 1708 | vec![Field::new("bar", child, false)], |
| 1709 | true, |
| 1710 | )])); |
| 1711 | let mut reader = ReaderBuilder::new(schema.clone()) |
| 1712 | .build(Cursor::new(non_null.as_bytes())) |
| 1713 | .unwrap(); |
| 1714 | assert!(reader.next().unwrap().is_err()); // Should error as not nullable |
| 1715 | |
| 1716 | let null = r#"{"foo": {bar: null}}"#; |
| 1717 | let mut reader = ReaderBuilder::new(schema.clone()) |
| 1718 | .build(Cursor::new(null.as_bytes())) |
| 1719 | .unwrap(); |
| 1720 | assert!(reader.next().unwrap().is_err()); // Should error as not nullable |
| 1721 | |
| 1722 | // Test nulls in nullable parent can mask nulls in non-nullable child |
| 1723 | let null = r#"{"foo": null}"#; |
| 1724 | let mut reader = ReaderBuilder::new(schema) |
| 1725 | .build(Cursor::new(null.as_bytes())) |
| 1726 | .unwrap(); |
| 1727 | let batch = reader.next().unwrap().unwrap(); |
| 1728 | assert_eq!(batch.num_columns(), 1); |
| 1729 | let foo = batch.column(0).as_struct(); |
| 1730 | assert_eq!(foo.len(), 1); |
| 1731 | assert!(foo.is_null(0)); |
| 1732 | assert_eq!(foo.num_columns(), 1); |
| 1733 | |
| 1734 | let bar = foo.column(0); |
| 1735 | assert_eq!(bar.len(), 1); |
| 1736 | // Non-nullable child can still contain null as masked by parent |
| 1737 | assert!(bar.is_null(0)); |
| 1738 | }; |
| 1739 | |
| 1740 | do_test(DataType::Boolean); |
| 1741 | do_test(DataType::Int32); |
| 1742 | do_test(DataType::Utf8); |
| 1743 | do_test(DataType::Decimal128(2, 1)); |
| 1744 | do_test(DataType::Timestamp( |
| 1745 | TimeUnit::Microsecond, |
| 1746 | Some("+00:00".into()), |
| 1747 | )); |
| 1748 | } |
| 1749 | |
| 1750 | #[test] |
| 1751 | fn test_truncation() { |