1616
1717#include " paimon/global_index/global_index_write_task.h"
1818
19+ #include < set>
20+
1921#include " arrow/c/bridge.h"
22+ #include " arrow/c/helpers.h"
2023#include " paimon/common/table/special_fields.h"
2124#include " paimon/common/types/data_field.h"
2225#include " paimon/common/utils/arrow/status_utils.h"
3538#include " paimon/table/source/table_read.h"
3639namespace paimon {
3740namespace {
41+ Result<std::unique_ptr<GlobalIndexer>> CreateGlobalIndexer (const std::string& index_type,
42+ const CoreOptions& core_options) {
43+ PAIMON_ASSIGN_OR_RAISE (std::unique_ptr<GlobalIndexer> indexer,
44+ GlobalIndexerFactory::Get (index_type, core_options.ToMap ()));
45+ if (!indexer) {
46+ return Status::Invalid (
47+ fmt::format (" Unknown index type {}, may not registered" , index_type));
48+ }
49+ return indexer;
50+ }
51+
3852Result<std::shared_ptr<GlobalIndexFileManager>> CreateGlobalIndexFileManager (
3953 const std::string& table_path, const std::shared_ptr<TableSchema>& table_schema,
4054 const CoreOptions& core_options, const std::shared_ptr<MemoryPool>& pool) {
@@ -58,43 +72,95 @@ Result<std::shared_ptr<GlobalIndexFileManager>> CreateGlobalIndexFileManager(
5872}
5973
6074Result<std::shared_ptr<GlobalIndexWriter>> CreateGlobalIndexWriter (
61- const std::string& index_type, const DataField& field,
75+ const GlobalIndexer& indexer, const DataField& field,
76+ const std::vector<DataField>& extra_fields,
6277 const std::shared_ptr<GlobalIndexFileManager>& index_file_manager,
63- const CoreOptions& core_options, const std::shared_ptr<MemoryPool>& pool) {
64- PAIMON_ASSIGN_OR_RAISE (std::unique_ptr<GlobalIndexer> indexer,
65- GlobalIndexerFactory::Get (index_type, core_options. ToMap ()) );
66- if (!indexer) {
67- return Status::Invalid (
68- fmt::format ( " Unknown index type {}, may not registered " , index_type ));
78+ const std::shared_ptr<MemoryPool>& pool) {
79+ arrow::FieldVector arrow_fields;
80+ arrow_fields. reserve (extra_fields. size () + 1 );
81+ arrow_fields. push_back ( DataField::ConvertDataFieldToArrowField (field));
82+ for ( const auto & extra_field : extra_fields) {
83+ arrow_fields. push_back ( DataField::ConvertDataFieldToArrowField (extra_field ));
6984 }
70- // TODO(xinyu.lxy): may add additional fields to read for index write
71- auto arrow_field = DataField::ConvertDataFieldToArrowField (field);
72- auto arrow_schema = arrow::schema ({arrow_field});
85+ auto arrow_schema = arrow::schema (arrow_fields);
7386 ArrowSchema c_arrow_schema;
7487 PAIMON_RETURN_NOT_OK_FROM_ARROW (arrow::ExportSchema (*arrow_schema, &c_arrow_schema));
75- return indexer->CreateWriter (field.Name (), &c_arrow_schema, index_file_manager, pool);
88+ ScopeGuard guard ([&]() { ArrowSchemaRelease (&c_arrow_schema); });
89+ return indexer.CreateWriter (field.Name (), &c_arrow_schema, index_file_manager, pool);
90+ }
91+
92+ Result<std::vector<DataField>> GetExtraFields (const TableSchema& table_schema,
93+ const std::string& field_name,
94+ const std::vector<std::string>& extra_field_names) {
95+ std::vector<DataField> extra_fields;
96+ extra_fields.reserve (extra_field_names.size ());
97+ std::set<std::string> dedup_field_names;
98+ for (const auto & extra_field_name : extra_field_names) {
99+ if (extra_field_name == field_name || !dedup_field_names.insert (extra_field_name).second ) {
100+ continue ;
101+ }
102+ PAIMON_ASSIGN_OR_RAISE (DataField extra_field, table_schema.GetField (extra_field_name));
103+ extra_fields.push_back (extra_field);
104+ }
105+ return extra_fields;
106+ }
107+
108+ std::vector<std::string> BuildReadFieldNames (const std::string& field_name,
109+ const std::vector<DataField>& extra_fields) {
110+ std::vector<std::string> read_field_names;
111+ read_field_names.reserve (extra_fields.size () + 2 );
112+ read_field_names.push_back (field_name);
113+ for (const auto & extra_field : extra_fields) {
114+ read_field_names.push_back (extra_field.Name ());
115+ }
116+ read_field_names.push_back (SpecialFields::RowId ().Name ());
117+ return read_field_names;
118+ }
119+
120+ std::vector<std::string> BuildWriterFieldNames (const std::string& field_name,
121+ const std::vector<DataField>& extra_fields) {
122+ std::vector<std::string> writer_field_names;
123+ writer_field_names.reserve (extra_fields.size () + 1 );
124+ writer_field_names.push_back (field_name);
125+ for (const auto & extra_field : extra_fields) {
126+ writer_field_names.push_back (extra_field.Name ());
127+ }
128+ return writer_field_names;
129+ }
130+
131+ std::optional<std::vector<int32_t >> GetExtraFieldIds (const std::vector<DataField>& extra_fields) {
132+ if (extra_fields.empty ()) {
133+ return std::nullopt ;
134+ }
135+ std::vector<int32_t > extra_field_ids;
136+ extra_field_ids.reserve (extra_fields.size ());
137+ for (const auto & extra_field : extra_fields) {
138+ extra_field_ids.push_back (extra_field.Id ());
139+ }
140+ return extra_field_ids;
76141}
77142
78143Result<std::unique_ptr<BatchReader>> CreateBatchReader (
79- const std::string& table_path, const std::string& field_name ,
144+ const std::string& table_path, const std::vector<std:: string>& read_field_names ,
80145 const std::shared_ptr<IndexedSplit>& indexed_split, const CoreOptions& core_options,
81146 const std::shared_ptr<MemoryPool>& pool) {
82147 ReadContextBuilder read_context_builder (table_path);
83148 read_context_builder.SetOptions (core_options.ToMap ())
84149 .WithFileSystem (core_options.GetFileSystem ())
85150 .EnablePrefetch (true )
86151 .WithMemoryPool (pool)
87- .SetReadFieldNames ({field_name, SpecialFields::RowId (). Name ()} );
152+ .SetReadFieldNames (read_field_names );
88153 PAIMON_ASSIGN_OR_RAISE (std::unique_ptr<ReadContext> read_context,
89154 read_context_builder.Finish ());
90155 PAIMON_ASSIGN_OR_RAISE (std::unique_ptr<TableRead> table_read,
91156 TableRead::Create (std::move (read_context)));
92157 return table_read->CreateReader (indexed_split);
93158}
94159
95- Result<std::vector<GlobalIndexIOMeta>> BuildIndex (const std::string& field_name, const Range& range,
96- BatchReader* batch_reader,
97- GlobalIndexWriter* global_index_writer) {
160+ Result<std::vector<GlobalIndexIOMeta>> BuildIndex (
161+ const std::string& field_name, const Range& range,
162+ const std::vector<std::string>& writer_field_names, BatchReader* batch_reader,
163+ GlobalIndexWriter* global_index_writer) {
98164 while (true ) {
99165 PAIMON_ASSIGN_OR_RAISE (BatchReader::ReadBatch read_batch, batch_reader->NextBatch ());
100166 if (BatchReader::IsEofBatch (read_batch)) {
@@ -131,8 +197,20 @@ Result<std::vector<GlobalIndexIOMeta>> BuildIndex(const std::string& field_name,
131197 }
132198 relative_row_ids.push_back (row_id - range.from );
133199 }
134- PAIMON_ASSIGN_OR_RAISE_FROM_ARROW (std::shared_ptr<arrow::StructArray> new_array,
135- arrow::StructArray::Make ({indexed_array}, {field_name}));
200+ std::vector<std::shared_ptr<arrow::Array>> writer_arrays;
201+ writer_arrays.reserve (writer_field_names.size ());
202+ for (const auto & writer_field_name : writer_field_names) {
203+ auto writer_array = struct_array->GetFieldByName (writer_field_name);
204+ if (!writer_array) {
205+ return Status::Invalid (
206+ fmt::format (" read array does not contain {} field in GlobalIndexWriteTask" ,
207+ writer_field_name));
208+ }
209+ writer_arrays.push_back (writer_array);
210+ }
211+ PAIMON_ASSIGN_OR_RAISE_FROM_ARROW (
212+ std::shared_ptr<arrow::StructArray> new_array,
213+ arrow::StructArray::Make (writer_arrays, writer_field_names));
136214 ::ArrowArray c_new_array;
137215 PAIMON_RETURN_NOT_OK_FROM_ARROW (arrow::ExportArray (*new_array, &c_new_array));
138216 PAIMON_RETURN_NOT_OK (
@@ -157,8 +235,8 @@ Result<std::shared_ptr<CommitMessage>> ToCommitMessage(
157235 index_file_metas.push_back (std::make_shared<IndexFileMeta>(
158236 index_type, PathUtil::GetName (io_meta.file_path ), io_meta.file_size , range.Count (),
159237 /* dv_ranges=*/ std::nullopt , external_path,
160- GlobalIndexMeta (range.from , range.to , field_id,
161- /* extra_field_ids= */ std:: nullopt , io_meta.metadata )));
238+ GlobalIndexMeta (range.from , range.to , field_id, io_meta. extra_field_ids ,
239+ io_meta.metadata )));
162240 }
163241 DataIncrement data_increment (std::move (index_file_metas));
164242 return std::make_shared<CommitMessageImpl>(partition, bucket,
@@ -199,6 +277,17 @@ Result<std::shared_ptr<CommitMessage>> GlobalIndexWriteTask::WriteIndex(
199277 }
200278 PAIMON_ASSIGN_OR_RAISE (CoreOptions core_options,
201279 CoreOptions::FromMap (final_options, file_system));
280+ PAIMON_ASSIGN_OR_RAISE (std::unique_ptr<GlobalIndexer> indexer,
281+ CreateGlobalIndexer (index_type, core_options));
282+ PAIMON_ASSIGN_OR_RAISE (std::optional<std::vector<std::string>> extra_field_names,
283+ indexer->GetExtraFieldNames ());
284+ PAIMON_ASSIGN_OR_RAISE (DataField field, table_schema->GetField (field_name));
285+ PAIMON_ASSIGN_OR_RAISE (std::vector<DataField> extra_fields,
286+ GetExtraFields (*table_schema, field_name,
287+ extra_field_names.value_or (std::vector<std::string>())));
288+ std::optional<std::vector<int32_t >> extra_field_ids = GetExtraFieldIds (extra_fields);
289+ std::vector<std::string> writer_field_names = BuildWriterFieldNames (field_name, extra_fields);
290+ std::vector<std::string> read_field_names = BuildReadFieldNames (field_name, extra_fields);
202291
203292 // create index file manager
204293 PAIMON_ASSIGN_OR_RAISE (
@@ -208,23 +297,25 @@ Result<std::shared_ptr<CommitMessage>> GlobalIndexWriteTask::WriteIndex(
208297 // create batch reader
209298 PAIMON_ASSIGN_OR_RAISE (
210299 std::unique_ptr<BatchReader> batch_reader,
211- CreateBatchReader (table_path, field_name , indexed_split, core_options, pool));
300+ CreateBatchReader (table_path, read_field_names , indexed_split, core_options, pool));
212301
213302 // create global index writer
214- PAIMON_ASSIGN_OR_RAISE (DataField field, table_schema->GetField (field_name));
215303 PAIMON_ASSIGN_OR_RAISE (
216304 std::shared_ptr<GlobalIndexWriter> global_index_writer,
217- CreateGlobalIndexWriter (index_type , field, index_file_manager, core_options , pool));
305+ CreateGlobalIndexWriter (*indexer , field, extra_fields, index_file_manager , pool));
218306
219307 ScopeGuard guard ([&]() {
220308 global_index_writer.reset ();
221309 batch_reader.reset ();
222310 });
223311
224312 // read from data split and write to index writer
225- PAIMON_ASSIGN_OR_RAISE (
226- std::vector<GlobalIndexIOMeta> global_index_io_metas,
227- BuildIndex (field_name, range, batch_reader.get (), global_index_writer.get ()));
313+ PAIMON_ASSIGN_OR_RAISE (std::vector<GlobalIndexIOMeta> global_index_io_metas,
314+ BuildIndex (field_name, range, writer_field_names, batch_reader.get (),
315+ global_index_writer.get ()));
316+ for (auto & io_meta : global_index_io_metas) {
317+ io_meta.extra_field_ids = extra_field_ids;
318+ }
228319
229320 // generate commit message
230321 return ToCommitMessage (index_type, field.Id (), range, global_index_io_metas,
0 commit comments