| 202 | } |
| 203 | |
| 204 | Status ResolveOneFieldRef( |
| 205 | const SchemaManifest& manifest, const FieldRef& field_ref, |
| 206 | const std::unordered_map<std::string, const SchemaField*>& field_lookup, |
| 207 | const std::unordered_set<std::string>& duplicate_fields, |
| 208 | std::vector<int>* columns_selection) { |
| 209 | if (const std::string* name = field_ref.name()) { |
| 210 | auto it = field_lookup.find(*name); |
| 211 | if (it != field_lookup.end()) { |
| 212 | AddColumnIndices(*it->second, columns_selection); |
| 213 | } else if (duplicate_fields.find(*name) != duplicate_fields.end()) { |
| 214 | // We shouldn't generally get here because SetProjection will reject such references |
| 215 | return Status::Invalid("Ambiguous reference to column '", *name, |
| 216 | "' which occurs more than once"); |
| 217 | } |
| 218 | // "Virtual" column: field is not in file but is in the ScanOptions. |
| 219 | // Ignore it here, as projection will pad the batch with a null column. |
| 220 | return Status::OK(); |
| 221 | } |
| 222 | |
| 223 | const SchemaField* toplevel = nullptr; |
| 224 | const SchemaField* field = nullptr; |
| 225 | if (const std::vector<FieldRef>* refs = field_ref.nested_refs()) { |
| 226 | // Only supports a sequence of names |
| 227 | for (const auto& ref : *refs) { |
| 228 | if (const std::string* name = ref.name()) { |
| 229 | if (!field) { |
| 230 | // First lookup, top-level field |
| 231 | auto it = field_lookup.find(*name); |
| 232 | if (it != field_lookup.end()) { |
| 233 | field = it->second; |
| 234 | toplevel = field; |
| 235 | } else if (duplicate_fields.find(*name) != duplicate_fields.end()) { |
| 236 | return Status::Invalid("Ambiguous reference to column '", *name, |
| 237 | "' which occurs more than once"); |
| 238 | } else { |
| 239 | // Virtual column |
| 240 | return Status::OK(); |
| 241 | } |
| 242 | } else { |
| 243 | const SchemaField* result = nullptr; |
| 244 | for (const auto& child : field->children) { |
| 245 | if (child.field->name() == *name) { |
| 246 | if (!result) { |
| 247 | result = &child; |
| 248 | } else { |
| 249 | return Status::Invalid("Ambiguous nested reference to column '", *name, |
| 250 | "' which occurs more than once in field ", |
| 251 | field->field->ToString()); |
| 252 | } |
| 253 | } |
| 254 | } |
| 255 | if (!result) { |
| 256 | // Virtual column |
| 257 | return Status::OK(); |
| 258 | } |
| 259 | field = result; |
| 260 | } |
| 261 | continue; |
no test coverage detected