|
24 | 24 | import java.time.Instant; |
25 | 25 | import java.time.LocalDate; |
26 | 26 | import java.util.*; |
| 27 | +import javax.annotation.Nonnull; |
27 | 28 |
|
28 | 29 | import org.apache.spark.sql.streaming.GroupStateTimeout; |
29 | 30 | import org.apache.spark.sql.streaming.OutputMode; |
@@ -823,6 +824,75 @@ public int hashCode() { |
823 | 824 | } |
824 | 825 | } |
825 | 826 |
|
| 827 | + public static class NestedSmallBeanWithNonNullField implements Serializable { |
| 828 | + private SmallBean nonNull_f; |
| 829 | + private SmallBean nullable_f; |
| 830 | + private Map<String, SmallBean> childMap; |
| 831 | + |
| 832 | + @Nonnull |
| 833 | + public SmallBean getNonNull_f() { |
| 834 | + return nonNull_f; |
| 835 | + } |
| 836 | + |
| 837 | + public void setNonNull_f(SmallBean f) { |
| 838 | + this.nonNull_f = f; |
| 839 | + } |
| 840 | + |
| 841 | + public SmallBean getNullable_f() { |
| 842 | + return nullable_f; |
| 843 | + } |
| 844 | + |
| 845 | + public void setNullable_f(SmallBean f) { |
| 846 | + this.nullable_f = f; |
| 847 | + } |
| 848 | + |
| 849 | + @Nonnull |
| 850 | + public Map<String, SmallBean> getChildMap() { return childMap; } |
| 851 | + public void setChildMap(Map<String, SmallBean> childMap) { |
| 852 | + this.childMap = childMap; |
| 853 | + } |
| 854 | + |
| 855 | + @Override |
| 856 | + public boolean equals(Object o) { |
| 857 | + if (this == o) return true; |
| 858 | + if (o == null || getClass() != o.getClass()) return false; |
| 859 | + NestedSmallBeanWithNonNullField that = (NestedSmallBeanWithNonNullField) o; |
| 860 | + return Objects.equal(nullable_f, that.nullable_f) && |
| 861 | + Objects.equal(nonNull_f, that.nonNull_f) && Objects.equal(childMap, that.childMap); |
| 862 | + } |
| 863 | + |
| 864 | + @Override |
| 865 | + public int hashCode() { |
| 866 | + return Objects.hashCode(nullable_f, nonNull_f, childMap); |
| 867 | + } |
| 868 | + } |
| 869 | + |
| 870 | + public static class NestedSmallBean2 implements Serializable { |
| 871 | + private NestedSmallBeanWithNonNullField f; |
| 872 | + |
| 873 | + @Nonnull |
| 874 | + public NestedSmallBeanWithNonNullField getF() { |
| 875 | + return f; |
| 876 | + } |
| 877 | + |
| 878 | + public void setF(NestedSmallBeanWithNonNullField f) { |
| 879 | + this.f = f; |
| 880 | + } |
| 881 | + |
| 882 | + @Override |
| 883 | + public boolean equals(Object o) { |
| 884 | + if (this == o) return true; |
| 885 | + if (o == null || getClass() != o.getClass()) return false; |
| 886 | + NestedSmallBean2 that = (NestedSmallBean2) o; |
| 887 | + return Objects.equal(f, that.f); |
| 888 | + } |
| 889 | + |
| 890 | + @Override |
| 891 | + public int hashCode() { |
| 892 | + return Objects.hashCode(f); |
| 893 | + } |
| 894 | + } |
| 895 | + |
826 | 896 | @Rule |
827 | 897 | public transient ExpectedException nullabilityCheck = ExpectedException.none(); |
828 | 898 |
|
@@ -1504,6 +1574,54 @@ public void testSerializeNull() { |
1504 | 1574 | Assert.assertEquals(beans, ds2.collectAsList()); |
1505 | 1575 | } |
1506 | 1576 |
|
| 1577 | + @Test |
| 1578 | + public void testNonNullField() { |
| 1579 | + NestedSmallBeanWithNonNullField bean1 = new NestedSmallBeanWithNonNullField(); |
| 1580 | + SmallBean smallBean = new SmallBean(); |
| 1581 | + bean1.setNonNull_f(smallBean); |
| 1582 | + Map<String, SmallBean> map = new HashMap<>(); |
| 1583 | + bean1.setChildMap(map); |
| 1584 | + |
| 1585 | + Encoder<NestedSmallBeanWithNonNullField> encoder1 = |
| 1586 | + Encoders.bean(NestedSmallBeanWithNonNullField.class); |
| 1587 | + List<NestedSmallBeanWithNonNullField> beans1 = Arrays.asList(bean1); |
| 1588 | + Dataset<NestedSmallBeanWithNonNullField> ds1 = spark.createDataset(beans1, encoder1); |
| 1589 | + |
| 1590 | + StructType schema = ds1.schema(); |
| 1591 | + Assert.assertFalse(schema.apply("nonNull_f").nullable()); |
| 1592 | + Assert.assertTrue(schema.apply("nullable_f").nullable()); |
| 1593 | + Assert.assertFalse(schema.apply("childMap").nullable()); |
| 1594 | + |
| 1595 | + Assert.assertEquals(beans1, ds1.collectAsList()); |
| 1596 | + Dataset<NestedSmallBeanWithNonNullField> ds2 = ds1.map( |
| 1597 | + (MapFunction<NestedSmallBeanWithNonNullField, NestedSmallBeanWithNonNullField>) b -> b, |
| 1598 | + encoder1); |
| 1599 | + Assert.assertEquals(beans1, ds2.collectAsList()); |
| 1600 | + |
| 1601 | + // Nonnull nested fields |
| 1602 | + NestedSmallBean2 bean2 = new NestedSmallBean2(); |
| 1603 | + bean2.setF(bean1); |
| 1604 | + |
| 1605 | + Encoder<NestedSmallBean2> encoder2 = |
| 1606 | + Encoders.bean(NestedSmallBean2.class); |
| 1607 | + List<NestedSmallBean2> beans2 = Arrays.asList(bean2); |
| 1608 | + Dataset<NestedSmallBean2> ds3 = spark.createDataset(beans2, encoder2); |
| 1609 | + |
| 1610 | + StructType nestedSchema = (StructType) ds3.schema() |
| 1611 | + .fields()[ds3.schema().fieldIndex("f")] |
| 1612 | + .dataType(); |
| 1613 | + Assert.assertFalse(nestedSchema.apply("nonNull_f").nullable()); |
| 1614 | + Assert.assertTrue(nestedSchema.apply("nullable_f").nullable()); |
| 1615 | + Assert.assertFalse(nestedSchema.apply("childMap").nullable()); |
| 1616 | + |
| 1617 | + Assert.assertEquals(beans2, ds3.collectAsList()); |
| 1618 | + |
| 1619 | + Dataset<NestedSmallBean2> ds4 = ds3.map( |
| 1620 | + (MapFunction<NestedSmallBean2, NestedSmallBean2>) b -> b, |
| 1621 | + encoder2); |
| 1622 | + Assert.assertEquals(beans2, ds4.collectAsList()); |
| 1623 | + } |
| 1624 | + |
1507 | 1625 | @Test |
1508 | 1626 | public void testSpecificLists() { |
1509 | 1627 | SpecificListsBean bean = new SpecificListsBean(); |
|
0 commit comments