Skip to content

Commit f449a9f

Browse files
authored
fix(blob): allow blob files across schema IDs (alibaba#460)
1 parent 7a5e4f8 commit f449a9f

2 files changed

Lines changed: 57 additions & 3 deletions

File tree

src/paimon/core/operation/data_evolution_split_read.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,7 @@ Status DataEvolutionSplitRead::BlobBunch::Add(const std::shared_ptr<DataFileMeta
9494
}
9595
}
9696
if (!files_.empty()) {
97-
if (file->schema_id != files_[0]->schema_id) {
98-
return Status::Invalid("All files in a blob bunch should have the same schema id.");
99-
}
97+
// Blob files for the same field may span schema ids.
10098
if (file->write_cols != files_[0]->write_cols) {
10199
return Status::Invalid(
102100
"All files in a blob bunch should have the same write columns.");

test/inte/blob_table_inte_test.cpp

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -872,6 +872,62 @@ TEST_P(BlobTableInteTest, TestBasic) {
872872
expected_row_tracking_array));
873873
}
874874

875+
TEST_P(BlobTableInteTest, TestBlobFilesAcrossSchemaIds) {
876+
std::map<std::string, std::string> options = {{Options::MANIFEST_FORMAT, "orc"},
877+
{Options::FILE_FORMAT, GetParam()},
878+
{Options::FILE_SYSTEM, "local"},
879+
{Options::ROW_TRACKING_ENABLED, "true"},
880+
{Options::DATA_EVOLUTION_ENABLED, "true"}};
881+
CreateTable(/*partition_keys=*/{}, options);
882+
std::string table_path = PathUtil::JoinPath(dir_->Str(), "foo.db/bar");
883+
884+
// Simulate the post-compaction layout: one normal file bridges blob files across schema ids.
885+
std::vector<std::string> write_cols0 = {"f0", "f2"};
886+
auto src_array0 = std::dynamic_pointer_cast<arrow::StructArray>(
887+
arrow::ipc::internal::json::ArrayFromJSON(arrow::struct_({fields_[0], fields_[2]}), R"([
888+
[1, "a"],
889+
[2, "b"]
890+
])")
891+
.ValueOrDie());
892+
ASSERT_OK_AND_ASSIGN(auto commit_msgs0, WriteArray(table_path, {}, write_cols0, {src_array0}));
893+
ASSERT_OK(Commit(table_path, commit_msgs0));
894+
895+
std::vector<std::string> blob_write_cols = {"f1"};
896+
auto src_array1 = std::dynamic_pointer_cast<arrow::StructArray>(
897+
arrow::ipc::internal::json::ArrayFromJSON(arrow::struct_({fields_[1]}), R"([
898+
["c"]
899+
])")
900+
.ValueOrDie());
901+
ASSERT_OK_AND_ASSIGN(auto commit_msgs1,
902+
WriteArray(table_path, {}, blob_write_cols, {src_array1}));
903+
SetFirstRowId(0, commit_msgs1);
904+
ASSERT_OK(Commit(table_path, commit_msgs1));
905+
906+
auto f3 = arrow::field("f3", arrow::int64());
907+
ASSERT_OK(WriteNextSchema(table_path,
908+
{DataField(0, fields_[0]), DataField(1, fields_[1]),
909+
DataField(2, fields_[2]), DataField(3, f3)},
910+
/*highest_field_id=*/3, options));
911+
912+
auto src_array2 = std::dynamic_pointer_cast<arrow::StructArray>(
913+
arrow::ipc::internal::json::ArrayFromJSON(arrow::struct_({fields_[1]}), R"([
914+
["d"]
915+
])")
916+
.ValueOrDie());
917+
ASSERT_OK_AND_ASSIGN(auto commit_msgs2,
918+
WriteArray(table_path, {}, blob_write_cols, {src_array2}));
919+
SetFirstRowId(1, commit_msgs2);
920+
ASSERT_OK(Commit(table_path, commit_msgs2));
921+
922+
auto expected_array = std::dynamic_pointer_cast<arrow::StructArray>(
923+
arrow::ipc::internal::json::ArrayFromJSON(arrow::struct_(fields_), R"([
924+
[1, "c", "a"],
925+
[2, "d", "b"]
926+
])")
927+
.ValueOrDie());
928+
ASSERT_OK(ScanAndRead(table_path, arrow::schema(fields_)->field_names(), expected_array));
929+
}
930+
875931
TEST_P(BlobTableInteTest, TestMultipleAppends) {
876932
CreateTable();
877933
std::string table_path = PathUtil::JoinPath(dir_->Str(), "foo.db/bar");

0 commit comments

Comments
 (0)