From 8a2eb8fbcf5e168cf2a7459f1a58acf6da563646 Mon Sep 17 00:00:00 2001 From: Dayue Gao Date: Wed, 1 Apr 2020 18:39:04 +0800 Subject: [PATCH] [Bug][segment_v2] Fix a bug that NullBitmapBuilder is not reset when data page doesn't have null (#3240) This CL fixes a bug that could cause wrong answer for beta rowset with nullable column. The root cause is that NullBitmapBuilder is not reset when the current page doesn't contain NULL, which leads to wrong null map to be written for the next page. Added a test case to reproduce the problem. --- be/src/olap/rowset/segment_v2/column_writer.cpp | 4 +++- .../segment_v2/column_reader_writer_test.cpp | 15 +++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/be/src/olap/rowset/segment_v2/column_writer.cpp b/be/src/olap/rowset/segment_v2/column_writer.cpp index 62170aa4d0..1ba59bf2ad 100644 --- a/be/src/olap/rowset/segment_v2/column_writer.cpp +++ b/be/src/olap/rowset/segment_v2/column_writer.cpp @@ -332,9 +332,11 @@ Status ColumnWriter::_finish_current_page() { OwnedSlice nullmap; if (_is_nullable && _null_bitmap_builder->has_null()) { nullmap = _null_bitmap_builder->finish(); - _null_bitmap_builder->reset(); body.push_back(nullmap.slice()); } + if (_null_bitmap_builder != nullptr) { + _null_bitmap_builder->reset(); + } // prepare data page footer std::unique_ptr page(new Page()); diff --git a/be/test/olap/rowset/segment_v2/column_reader_writer_test.cpp b/be/test/olap/rowset/segment_v2/column_reader_writer_test.cpp index a67a4f6565..c8f6820cd9 100644 --- a/be/test/olap/rowset/segment_v2/column_reader_writer_test.cpp +++ b/be/test/olap/rowset/segment_v2/column_reader_writer_test.cpp @@ -313,6 +313,20 @@ TEST_F(ColumnReaderWriterTest, test_nullable) { test_nullable_data(val, is_null, num_uint8_rows / 8, "null_bigint_bs"); test_nullable_data(val, is_null, num_uint8_rows / 16, "null_largeint_bs"); + // test for the case where most values are not null + uint8_t* is_null_sparse = new uint8_t[num_uint8_rows]; + for (int i = 0; i < num_uint8_rows; ++i) { + bool v = false; + // in order to make some data pages not null, set the first half of values not null. + // for the second half, only 1/1024 of values are null + if (i >= (num_uint8_rows / 2)) { + v = (i % 1024) == 10; + } + BitmapChange(is_null_sparse, i, v); + } + test_nullable_data(val, is_null_sparse, num_uint8_rows, "sparse_null_tiny_bs"); + + float* float_vals = new float[num_uint8_rows]; for (int i = 0; i < num_uint8_rows; ++i) { float_vals[i] = i; @@ -330,6 +344,7 @@ TEST_F(ColumnReaderWriterTest, test_nullable) { // test_nullable_data(val, is_null, num_uint8_rows / 8, "null_double_bs"); delete[] val; delete[] is_null; + delete[] is_null_sparse; delete[] float_vals; delete[] double_vals; }