|
17 | 17 | * under the License. |
18 | 18 | */ |
19 | 19 |
|
| 20 | +#include <map> |
20 | 21 | #include <memory> |
21 | 22 | #include <string> |
| 23 | +#include <unordered_map> |
22 | 24 | #include <utility> |
23 | 25 | #include <vector> |
24 | 26 |
|
@@ -314,8 +316,129 @@ Result<std::vector<std::shared_ptr<FileScanTask>>> FileScanTasksFromJson( |
314 | 316 | return file_scan_tasks; |
315 | 317 | } |
316 | 318 |
|
| 319 | +nlohmann::json ToJson(const DataFile& df) { |
| 320 | + nlohmann::json json; |
| 321 | + json[kContent] = ToString(df.content); |
| 322 | + json[kFilePath] = df.file_path; |
| 323 | + json[kFileFormat] = ToString(df.file_format); |
| 324 | + |
| 325 | + if (df.partition_spec_id.has_value()) { |
| 326 | + json[kSpecId] = df.partition_spec_id.value(); |
| 327 | + } |
| 328 | + |
| 329 | + json[kRecordCount] = df.record_count; |
| 330 | + json[kFileSizeInBytes] = df.file_size_in_bytes; |
| 331 | + |
| 332 | + auto write_int_map = [&](std::string_view key, |
| 333 | + const std::map<int32_t, int64_t>& m) { |
| 334 | + if (!m.empty()) { |
| 335 | + std::vector<int32_t> keys; |
| 336 | + std::vector<int64_t> values; |
| 337 | + for (const auto& [k, v] : m) { |
| 338 | + keys.push_back(k); |
| 339 | + values.push_back(v); |
| 340 | + } |
| 341 | + json[key] = {{"keys", std::move(keys)}, {"values", std::move(values)}}; |
| 342 | + } |
| 343 | + }; |
| 344 | + |
| 345 | + write_int_map(kColumnSizes, df.column_sizes); |
| 346 | + write_int_map(kValueCounts, df.value_counts); |
| 347 | + write_int_map(kNullValueCounts, df.null_value_counts); |
| 348 | + write_int_map(kNanValueCounts, df.nan_value_counts); |
| 349 | + |
| 350 | + auto write_binary_map = [&](std::string_view key, |
| 351 | + const std::map<int32_t, std::vector<uint8_t>>& m) { |
| 352 | + if (!m.empty()) { |
| 353 | + std::vector<int32_t> keys; |
| 354 | + std::vector<std::vector<uint8_t>> values; |
| 355 | + for (const auto& [k, v] : m) { |
| 356 | + keys.push_back(k); |
| 357 | + values.push_back(v); |
| 358 | + } |
| 359 | + json[key] = {{"keys", std::move(keys)}, {"values", std::move(values)}}; |
| 360 | + } |
| 361 | + }; |
| 362 | + |
| 363 | + write_binary_map(kLowerBounds, df.lower_bounds); |
| 364 | + write_binary_map(kUpperBounds, df.upper_bounds); |
| 365 | + |
| 366 | + if (!df.key_metadata.empty()) { |
| 367 | + json[kKeyMetadata] = df.key_metadata; |
| 368 | + } |
| 369 | + if (!df.split_offsets.empty()) { |
| 370 | + json[kSplitOffsets] = df.split_offsets; |
| 371 | + } |
| 372 | + if (!df.equality_ids.empty()) { |
| 373 | + json[kEqualityIds] = df.equality_ids; |
| 374 | + } |
| 375 | + if (df.sort_order_id.has_value()) { |
| 376 | + json[kSortOrderId] = df.sort_order_id.value(); |
| 377 | + } |
| 378 | + if (df.first_row_id.has_value()) { |
| 379 | + json[kFirstRowId] = df.first_row_id.value(); |
| 380 | + } |
| 381 | + if (df.referenced_data_file.has_value()) { |
| 382 | + json[kReferencedDataFile] = df.referenced_data_file.value(); |
| 383 | + } |
| 384 | + if (df.content_offset.has_value()) { |
| 385 | + json[kContentOffset] = df.content_offset.value(); |
| 386 | + } |
| 387 | + if (df.content_size_in_bytes.has_value()) { |
| 388 | + json[kContentSizeInBytes] = df.content_size_in_bytes.value(); |
| 389 | + } |
| 390 | + |
| 391 | + return json; |
| 392 | +} |
| 393 | + |
317 | 394 | namespace { |
318 | 395 |
|
| 396 | +nlohmann::json BaseScanTaskResponseToJson(const BaseScanTaskResponse& response) { |
| 397 | + nlohmann::json json; |
| 398 | + |
| 399 | + SetContainerField(json, kPlanTasks, response.plan_tasks); |
| 400 | + |
| 401 | + // Build delete_files array and a pointer-to-index map for reference lookup. |
| 402 | + std::unordered_map<const DataFile*, int32_t> delete_file_index; |
| 403 | + nlohmann::json delete_files_json = nlohmann::json::array(); |
| 404 | + for (size_t i = 0; i < response.delete_files.size(); ++i) { |
| 405 | + if (response.delete_files[i]) { |
| 406 | + delete_files_json.push_back(ToJson(*response.delete_files[i])); |
| 407 | + delete_file_index[response.delete_files[i].get()] = static_cast<int32_t>(i); |
| 408 | + } |
| 409 | + } |
| 410 | + if (!delete_files_json.empty()) { |
| 411 | + json[kDeleteFiles] = std::move(delete_files_json); |
| 412 | + } |
| 413 | + |
| 414 | + nlohmann::json tasks_json = nlohmann::json::array(); |
| 415 | + for (const auto& task : response.file_scan_tasks) { |
| 416 | + if (!task) continue; |
| 417 | + nlohmann::json task_json; |
| 418 | + if (task->data_file()) { |
| 419 | + task_json[kDataFile] = ToJson(*task->data_file()); |
| 420 | + } |
| 421 | + if (!task->delete_files().empty()) { |
| 422 | + std::vector<int32_t> refs; |
| 423 | + for (const auto& df : task->delete_files()) { |
| 424 | + auto it = delete_file_index.find(df.get()); |
| 425 | + if (it != delete_file_index.end()) { |
| 426 | + refs.push_back(it->second); |
| 427 | + } |
| 428 | + } |
| 429 | + if (!refs.empty()) { |
| 430 | + task_json[kDeleteFileReferences] = std::move(refs); |
| 431 | + } |
| 432 | + } |
| 433 | + tasks_json.push_back(std::move(task_json)); |
| 434 | + } |
| 435 | + if (!tasks_json.empty()) { |
| 436 | + json[kFileScanTasks] = std::move(tasks_json); |
| 437 | + } |
| 438 | + |
| 439 | + return json; |
| 440 | +} |
| 441 | + |
319 | 442 | Status BaseScanTaskResponseFromJson( |
320 | 443 | const nlohmann::json& json, BaseScanTaskResponse* response, |
321 | 444 | const std::unordered_map<int32_t, std::shared_ptr<PartitionSpec>>& |
@@ -853,6 +976,25 @@ Result<FetchScanTasksResponse> FetchScanTasksResponseFromJson( |
853 | 976 | return response; |
854 | 977 | } |
855 | 978 |
|
| 979 | +nlohmann::json ToJson(const PlanTableScanResponse& response) { |
| 980 | + nlohmann::json json = BaseScanTaskResponseToJson(response); |
| 981 | + json[kPlanStatus] = ToString(response.plan_status); |
| 982 | + if (!response.plan_id.empty()) { |
| 983 | + json[kPlanId] = response.plan_id; |
| 984 | + } |
| 985 | + return json; |
| 986 | +} |
| 987 | + |
| 988 | +nlohmann::json ToJson(const FetchPlanningResultResponse& response) { |
| 989 | + nlohmann::json json = BaseScanTaskResponseToJson(response); |
| 990 | + json[kPlanStatus] = ToString(response.plan_status); |
| 991 | + return json; |
| 992 | +} |
| 993 | + |
| 994 | +nlohmann::json ToJson(const FetchScanTasksResponse& response) { |
| 995 | + return BaseScanTaskResponseToJson(response); |
| 996 | +} |
| 997 | + |
856 | 998 | #define ICEBERG_DEFINE_FROM_JSON(Model) \ |
857 | 999 | template <> \ |
858 | 1000 | Result<Model> FromJson<Model>(const nlohmann::json& json) { \ |
|
0 commit comments