Skip to content

Commit 049f588

Browse files
zhangweilstXeon Liu
authored andcommitted
fix review comments
1 parent 91f599c commit 049f588

13 files changed

Lines changed: 117 additions & 4 deletions

File tree

‎src/paimon/common/predicate/literal_converter.h‎

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -134,10 +134,6 @@ class PAIMON_EXPORT LiteralConverter {
134134
literals.emplace_back(literal_type);
135135
} else {
136136
int64_t dict_index = indices->Value(i);
137-
if (dictionary->IsNull(dict_index)) {
138-
literals.emplace_back(literal_type);
139-
continue;
140-
}
141137
auto value = dictionary->GetView(dict_index);
142138
literals.emplace_back(literal_type, value.data(), value.size(), own_data);
143139
}

‎src/paimon/core/casting/casting_utils.cpp‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ Result<std::shared_ptr<arrow::Array>> CastingUtils::DecodeDictionary(
3030
}
3131
const auto& dictionary_type = checked_cast<const arrow::DictionaryType&>(*array->type());
3232
std::shared_ptr<arrow::DataType> value_type = dictionary_type.value_type();
33+
/// We're not casting `LARGE_BINARY` to `BINARY` since `BLOB` specifically expects
34+
/// `LARGE_BINARY`. See also in `src/paimon/common/utils/field_type_utils.h`.
3335
if (value_type->id() == arrow::Type::LARGE_STRING) {
3436
value_type = arrow::utf8();
3537
}

‎src/paimon/format/parquet/parquet_read_type_adapter.cpp‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "arrow/type.h"
2626
#include "fmt/format.h"
2727
#include "paimon/common/data/blob_utils.h"
28+
#include "paimon/common/utils/arrow/arrow_utils.h"
2829
#include "paimon/common/utils/arrow/status_utils.h"
2930
#include "paimon/common/utils/checked_cast.h"
3031
#include "paimon/common/utils/date_time_utils.h"
@@ -100,6 +101,17 @@ Result<bool> ParquetReadTypeAdapter::NeedsArrayConversionImpl(
100101
const std::shared_ptr<arrow::DataType>& src_data_type = src_field->type();
101102
const std::shared_ptr<arrow::DataType>& target_data_type = target_field->type();
102103
arrow::Type::type type = src_data_type->id();
104+
if (type == arrow::Type::DICTIONARY) {
105+
// ARROW:schema may restore a Parquet leaf as a dictionary even though the Paimon schema
106+
// describes its logical value type. Keep the encoded representation when its value
107+
// layout is supported and already matches that logical type.
108+
const auto& dictionary_type = checked_cast<const arrow::DictionaryType&>(*src_data_type);
109+
const std::shared_ptr<arrow::DataType>& value_type = dictionary_type.value_type();
110+
if (ArrowUtils::IsDictionaryLayoutRecoverableValueType(*value_type) &&
111+
value_type->Equals(target_data_type)) {
112+
return false;
113+
}
114+
}
103115
if (type != target_data_type->id()) {
104116
return Status::Invalid(fmt::format("source type {} and target type {} mismatch",
105117
src_data_type->ToString(),

‎src/paimon/format/parquet/parquet_read_type_adapter_test.cpp‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,24 @@ TEST(ParquetReadTypeAdapterTest, TestAlreadyLogicalBlobCompatibility) {
109109
"source type large_binary and target type binary mismatch");
110110
}
111111

112+
TEST(ParquetReadTypeAdapterTest, TestDictionaryBinaryCompatibility) {
113+
std::shared_ptr<arrow::DataType> dictionary_type =
114+
arrow::dictionary(arrow::int32(), arrow::binary());
115+
116+
ASSERT_OK_AND_ASSIGN(bool needs_conversion, ParquetReadTypeAdapter::NeedsArrayConversion(
117+
dictionary_type, arrow::binary()));
118+
ASSERT_FALSE(needs_conversion);
119+
120+
ASSERT_NOK_WITH_MSG(
121+
ParquetReadTypeAdapter::NeedsArrayConversion(dictionary_type, arrow::utf8()),
122+
"source type dictionary<values=binary, indices=int32, ordered=0> and target type string "
123+
"mismatch");
124+
ASSERT_NOK_WITH_MSG(ParquetReadTypeAdapter::NeedsArrayConversion(
125+
arrow::dictionary(arrow::int32(), arrow::int32()), arrow::int32()),
126+
"source type dictionary<values=int32, indices=int32, ordered=0> and "
127+
"target type int32 mismatch");
128+
}
129+
112130
TEST(ParquetReadTypeAdapterTest, TestAdaptArray) {
113131
auto timezone = DateTimeUtils::GetLocalTimezoneName();
114132
arrow::FieldVector fields = {

‎test/inte/scan_and_read_inte_test.cpp‎

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3424,6 +3424,41 @@ TEST_P(ScanAndReadInteTest, TestCastTimestampType) {
34243424
ASSERT_TRUE(expected->Equals(read_result)) << read_result->ToString();
34253425
}
34263426

3427+
TEST_F(ScanAndReadInteTest, TestParquetDictionaryBinaryStoredArrowSchema) {
3428+
const std::string table_path = GetDataDir() +
3429+
"/parquet/append_dictionary_binary.db/"
3430+
"append_dictionary_binary";
3431+
3432+
ScanContextBuilder scan_context_builder(table_path);
3433+
ASSERT_OK_AND_ASSIGN(std::unique_ptr<ScanContext> scan_context, scan_context_builder.Finish());
3434+
ASSERT_OK_AND_ASSIGN(std::unique_ptr<TableScan> table_scan,
3435+
TableScan::Create(std::move(scan_context)));
3436+
ASSERT_OK_AND_ASSIGN(std::shared_ptr<Plan> plan, table_scan->CreatePlan());
3437+
ASSERT_EQ(1, plan->SnapshotId().value());
3438+
ASSERT_EQ(1, plan->Splits().size());
3439+
3440+
ReadContextBuilder read_context_builder(table_path);
3441+
ASSERT_OK_AND_ASSIGN(std::unique_ptr<ReadContext> read_context, read_context_builder.Finish());
3442+
ASSERT_OK_AND_ASSIGN(std::unique_ptr<TableRead> table_read,
3443+
TableRead::Create(std::move(read_context)));
3444+
ASSERT_OK_AND_ASSIGN(std::unique_ptr<BatchReader> reader,
3445+
table_read->CreateReader(plan->Splits()));
3446+
ASSERT_OK_AND_ASSIGN(std::shared_ptr<arrow::ChunkedArray> actual,
3447+
ReadResultCollector::CollectResult(std::move(reader)));
3448+
3449+
std::shared_ptr<arrow::DataType> expected_type = arrow::struct_({
3450+
arrow::field("_VALUE_KIND", arrow::int8()),
3451+
arrow::field("payload", arrow::binary()),
3452+
});
3453+
std::shared_ptr<arrow::Array> expected_array =
3454+
arrow::ipc::internal::json::ArrayFromJSON(
3455+
expected_type, R"([[0, "alpha"], [0, null], [0, "beta"], [0, "alpha"]])")
3456+
.ValueOrDie();
3457+
std::shared_ptr<arrow::ChunkedArray> expected =
3458+
std::make_shared<arrow::ChunkedArray>(expected_array);
3459+
ASSERT_TRUE(expected->Equals(actual)) << actual->ToString();
3460+
}
3461+
34273462
#ifdef PAIMON_ENABLE_LANCE
34283463
TEST_F(ScanAndReadInteTest, TestLanceJavaCompatibility) {
34293464
TimezoneGuard timezone_guard("UTC");
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
Paimon schema:
2+
payload: BYTES
3+
4+
The Parquet file was written from an Arrow dictionary<int32, binary> array with
5+
ArrowWriterProperties::store_schema enabled. Its serialized ARROW:schema metadata therefore
6+
restores payload as dictionary<int32, binary>, while the Paimon table schema remains BYTES.
7+
8+
Rows:
9+
alpha
10+
null
11+
beta
12+
alpha

0 commit comments

Comments
 (0)