| 74 | class PivotLongerNode : public ExecNode, public TracedNode { |
| 75 | public: |
| 76 | static Result<std::shared_ptr<Schema>> MakeOutputSchema( |
| 77 | const PivotLongerNodeOptions& options, |
| 78 | const std::shared_ptr<Schema>& input_schema) { |
| 79 | // Some of this is pure validation and not strictly needed to create the output schema |
| 80 | // but it's simpler to just do all validation here than to try and split between this |
| 81 | // method and PivotLongerNode::Make |
| 82 | if (options.row_templates.empty()) { |
| 83 | return Status::Invalid("There must be at least one row template"); |
| 84 | } |
| 85 | if (options.feature_field_names.empty() || options.measurement_field_names.empty()) { |
| 86 | return Status::Invalid( |
| 87 | "There must be at least one feature column and one measurement column and they " |
| 88 | "must " |
| 89 | "have names"); |
| 90 | } |
| 91 | |
| 92 | for (const auto& row_template : options.row_templates) { |
| 93 | if (row_template.feature_values.size() != options.feature_field_names.size()) { |
| 94 | return Status::Invalid("There were names given for ", |
| 95 | options.feature_field_names.size(), |
| 96 | " feature columns but one of the row templates only had ", |
| 97 | row_template.feature_values.size(), " feature values"); |
| 98 | } |
| 99 | if (row_template.measurement_values.size() != |
| 100 | options.measurement_field_names.size()) { |
| 101 | return Status::Invalid( |
| 102 | "There were names given for ", options.measurement_field_names.size(), |
| 103 | " measurement columns but one of the row templates only had ", |
| 104 | row_template.measurement_values.size(), " field references"); |
| 105 | } |
| 106 | } |
| 107 | |
| 108 | std::vector<std::shared_ptr<Field>> fields(input_schema->fields()); |
| 109 | for (const auto& name : options.feature_field_names) { |
| 110 | fields.push_back(field(name, utf8())); |
| 111 | } |
| 112 | std::vector<std::shared_ptr<DataType>> measurement_types( |
| 113 | options.measurement_field_names.size()); |
| 114 | for (const auto& row_template : options.row_templates) { |
| 115 | for (std::size_t i = 0; i < row_template.measurement_values.size(); i++) { |
| 116 | if (!row_template.measurement_values[i].has_value()) { |
| 117 | continue; |
| 118 | } |
| 119 | ARROW_ASSIGN_OR_RAISE(FieldPath meas_path, |
| 120 | row_template.measurement_values[i]->FindOne(*input_schema)); |
| 121 | ARROW_ASSIGN_OR_RAISE(std::shared_ptr<Field> meas_field, |
| 122 | meas_path.Get(*input_schema)); |
| 123 | if (measurement_types[i]) { |
| 124 | if (!measurement_types[i]->Equals(meas_field->type())) { |
| 125 | return Status::Invalid( |
| 126 | "Mixed measurement types at measurement index ", i, |
| 127 | ". Some row templates had the type ", measurement_types[i]->ToString(), |
| 128 | " but later row templates had the type ", meas_field->type()->ToString(), |
| 129 | ". All row templates must reference the same type for a measurement " |
| 130 | "column."); |
| 131 | } |
| 132 | } else { |
| 133 | measurement_types[i] = meas_field->type(); |
nothing calls this directly
no test coverage detected