Compute the column projection based on the scan options
| 303 | |
| 304 | // Compute the column projection based on the scan options |
| 305 | Result<std::vector<int>> InferColumnProjection(const parquet::arrow::FileReader& reader, |
| 306 | const ScanOptions& options) { |
| 307 | auto manifest = reader.manifest(); |
| 308 | // Checks if the field is needed in either the projection or the filter. |
| 309 | auto field_refs = options.MaterializedFields(); |
| 310 | |
| 311 | // Build a lookup table from top level field name to field metadata. |
| 312 | // This is to avoid quadratic-time mapping of projected fields to |
| 313 | // column indices, in the common case of selecting top level |
| 314 | // columns. For nested fields, we will pay the cost of a linear scan |
| 315 | // assuming for now that this is relatively rare, but this can be |
| 316 | // optimized. (Also, we don't want to pay the cost of building all |
| 317 | // the lookup tables up front if they're rarely used.) |
| 318 | std::unordered_map<std::string, const SchemaField*> field_lookup; |
| 319 | std::unordered_set<std::string> duplicate_fields; |
| 320 | for (const auto& schema_field : manifest.schema_fields) { |
| 321 | const auto it = field_lookup.emplace(schema_field.field->name(), &schema_field); |
| 322 | if (!it.second) { |
| 323 | duplicate_fields.emplace(schema_field.field->name()); |
| 324 | } |
| 325 | } |
| 326 | |
| 327 | std::vector<int> columns_selection; |
| 328 | for (auto& ref : field_refs) { |
| 329 | // In the (unlikely) absence of a known dataset schema, we require that all |
| 330 | // materialized refs are named. |
| 331 | if (options.dataset_schema) { |
| 332 | ARROW_ASSIGN_OR_RAISE( |
| 333 | ref, MaybeConvertFieldRef(std::move(ref), *options.dataset_schema)); |
| 334 | } |
| 335 | RETURN_NOT_OK(ResolveOneFieldRef(manifest, ref, field_lookup, duplicate_fields, |
| 336 | &columns_selection)); |
| 337 | } |
| 338 | return columns_selection; |
| 339 | } |
| 340 | |
| 341 | Status WrapSourceError(const Status& status, const std::string& path) { |
| 342 | return status.WithMessage("Could not open Parquet input source '", path, |
nothing calls this directly
no test coverage detected