Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions cpp/src/parquet/arrow/arrow_reader_writer_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5889,5 +5889,34 @@ TEST(TestArrowReadWrite, OperationsOnClosedWriter) {
ASSERT_RAISES(Invalid, writer->WriteTable(*table, 1));
}

TEST(TestArrowReadWrite, AllNulls) {
auto schema = ::arrow::schema({::arrow::field("all_nulls", ::arrow::int8())});

constexpr int64_t length = 3;
ASSERT_OK_AND_ASSIGN(auto null_bitmap, ::arrow::AllocateEmptyBitmap(length));
auto array_data = ::arrow::ArrayData::Make(
::arrow::int8(), length, {null_bitmap, /*values=*/nullptr}, /*null_count=*/length);
auto array = ::arrow::MakeArray(array_data);
auto record_batch = ::arrow::RecordBatch::Make(schema, length, {array});

auto sink = CreateOutputStream();
ASSERT_OK_AND_ASSIGN(auto writer, parquet::arrow::FileWriter::Open(
*schema, ::arrow::default_memory_pool(), sink,
parquet::default_writer_properties(),
parquet::default_arrow_writer_properties()));
ASSERT_OK(writer->WriteRecordBatch(*record_batch));
ASSERT_OK(writer->Close());
ASSERT_OK_AND_ASSIGN(auto buffer, sink->Finish());

std::shared_ptr<::arrow::Table> read_table;
ASSERT_OK_AND_ASSIGN(auto reader,
parquet::arrow::OpenFile(std::make_shared<BufferReader>(buffer),
::arrow::default_memory_pool()));
ASSERT_OK(reader->ReadTable(&read_table));
auto expected_table = ::arrow::Table::Make(
schema, {::arrow::ArrayFromJSON(::arrow::int8(), R"([null, null, null])")});
ASSERT_TRUE(expected_table->Equals(*read_table));
}

} // namespace arrow
} // namespace parquet
7 changes: 6 additions & 1 deletion cpp/src/parquet/column_writer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2099,7 +2099,12 @@ Status TypedColumnWriterImpl<ParquetType>::WriteArrowSerialize(
PARQUET_THROW_NOT_OK(ctx->GetScratchData<ParquetCType>(array.length(), &buffer));

SerializeFunctor<ParquetType, ArrowType> functor;
RETURN_NOT_OK(functor.Serialize(checked_cast<const ArrayType&>(array), ctx, buffer));
// The value buffer could be empty if all values are nulls.
// The output buffer will then remain uninitialized, but that's ok since
// null value slots are not written in Parquet.
if (array.null_count() != array.length()) {
RETURN_NOT_OK(functor.Serialize(checked_cast<const ArrayType&>(array), ctx, buffer));
}
bool no_nulls =
this->descr()->schema_node()->is_required() || (array.null_count() == 0);
if (!maybe_parent_nulls && no_nulls) {
Expand Down
Loading