| 1140 | } |
| 1141 | |
| 1142 | Result<bool> ApplyOriginalMetadata(const Field& origin_field, SchemaField* inferred) { |
| 1143 | bool modified = false; |
| 1144 | |
| 1145 | auto& origin_type = origin_field.type(); |
| 1146 | |
| 1147 | // The origin was an extension type. This occurs when the ARROW:extension:name field |
| 1148 | // was present when the schema was written and that extension is registered when |
| 1149 | // the schema is read. |
| 1150 | if (origin_type->id() == ::arrow::Type::EXTENSION) { |
| 1151 | const auto& origin_extension_type = |
| 1152 | checked_cast<const ::arrow::ExtensionType&>(*origin_type); |
| 1153 | |
| 1154 | // (Recursively) Apply the original storage metadata from the original storage field |
| 1155 | // This applies extension types to child elements, if any. |
| 1156 | auto origin_storage_field = |
| 1157 | origin_field.WithType(origin_extension_type.storage_type()); |
| 1158 | RETURN_NOT_OK(ApplyOriginalStorageMetadata(*origin_storage_field, inferred)); |
| 1159 | |
| 1160 | // Use the inferred type after child updates for below checks to see if |
| 1161 | // we can restore an extension type on the output. |
| 1162 | const auto& inferred_type = inferred->field->type(); |
| 1163 | |
| 1164 | // Whether or not the inferred type is also an extension type. This can occur when |
| 1165 | // arrow_extensions_enabled is true in the ArrowReaderProperties. Extension types |
| 1166 | // are not currently inferred for any other reason. |
| 1167 | bool arrow_extension_inferred = inferred_type->id() == ::arrow::Type::EXTENSION; |
| 1168 | |
| 1169 | // Check if the inferred storage type is compatible with the extension type |
| 1170 | // we're hoping to apply. We assume that if an extension type was inferred |
| 1171 | // that it was constructed with a valid storage type. Otherwise, we check with |
| 1172 | // extension types that we know about for valid storage, falling back to |
| 1173 | // storage type equality for extension types that we don't know about. |
| 1174 | std::string origin_extension_name = origin_extension_type.extension_name(); |
| 1175 | bool extension_supports_inferred_storage; |
| 1176 | |
| 1177 | if (origin_extension_name == "arrow.json") { |
| 1178 | extension_supports_inferred_storage = |
| 1179 | arrow_extension_inferred || |
| 1180 | ::arrow::extension::JsonExtensionType::IsSupportedStorageType( |
| 1181 | inferred_type->id()); |
| 1182 | } else if (origin_extension_name == "arrow.uuid") { |
| 1183 | extension_supports_inferred_storage = |
| 1184 | arrow_extension_inferred || |
| 1185 | ::arrow::extension::UuidType::IsSupportedStorageType(inferred_type); |
| 1186 | } else if (origin_extension_name == "arrow.parquet.variant") { |
| 1187 | extension_supports_inferred_storage = |
| 1188 | arrow_extension_inferred || |
| 1189 | ::arrow::extension::VariantExtensionType::IsSupportedStorageType(inferred_type); |
| 1190 | } else { |
| 1191 | extension_supports_inferred_storage = |
| 1192 | origin_extension_type.storage_type()->Equals(*inferred_type); |
| 1193 | } |
| 1194 | |
| 1195 | // If the origin extension of the metadata we are about to apply supports |
| 1196 | // the Arrow storage type we would otherwise return, we restore the extension |
| 1197 | // type to the output. |
| 1198 | if (extension_supports_inferred_storage) { |
| 1199 | inferred->field = inferred->field->WithType(origin_type); |
no test coverage detected