diff --git a/python/pyarrow/table.pxi b/python/pyarrow/table.pxi index 931677f9848..30352bf3950 100644 --- a/python/pyarrow/table.pxi +++ b/python/pyarrow/table.pxi @@ -3401,6 +3401,9 @@ cdef class Table(_PandasConvertible): .format(self.schema.names, target_schema.names)) for column, field in zip(self.itercolumns(), target_schema): + if not field.nullable and column.null_count > 0: + raise ValueError("Casting field {!r} with null values to non-nullable" + .format(field.name)) casted = column.cast(field.type, safe=safe, options=options) newcols.append(casted) diff --git a/python/pyarrow/tests/test_table.py b/python/pyarrow/tests/test_table.py index c0c60da6272..fad1c0acb24 100644 --- a/python/pyarrow/tests/test_table.py +++ b/python/pyarrow/tests/test_table.py @@ -2192,3 +2192,15 @@ def test_table_join_many_columns(): "col6": ["A", "B", None, "Z"], "col7": ["A", "B", None, "Z"], }) + + +def test_table_cast_invalid(): + # Casting a nullable field to non-nullable should be invalid! + table = pa.table({'a': [None, 1], 'b': [None, True]}) + new_schema = pa.schema([pa.field("a", "int64", nullable=True), + pa.field("b", "bool", nullable=False)]) + with pytest.raises(ValueError): + table.cast(new_schema) + + table = pa.table({'a': [None, 1], 'b': [False, True]}) + assert table.cast(new_schema).schema == new_schema