| 217 | } |
| 218 | |
| 219 | arrow::Status AddMetadataFromDots(SEXP lst, int num_fields, |
| 220 | std::shared_ptr<arrow::Schema>& schema) { |
| 221 | // Preallocate the r_metadata object: list(attributes=list(), columns=namedList(fields)) |
| 222 | |
| 223 | cpp11::writable::list metadata(2); |
| 224 | metadata.names() = arrow::r::data::names_metadata; |
| 225 | |
| 226 | bool has_top_level_metadata = false; |
| 227 | |
| 228 | // "top level" attributes, only relevant if the first object is not named and a data |
| 229 | // frame |
| 230 | cpp11::strings names = Rf_getAttrib(lst, R_NamesSymbol); |
| 231 | if (names[0] == "" && Rf_inherits(VECTOR_ELT(lst, 0), "data.frame") && |
| 232 | Rf_xlength(lst) == 1) { |
| 233 | SEXP top_level = metadata[0] = arrow_attributes(VECTOR_ELT(lst, 0), true); |
| 234 | if (!Rf_isNull(top_level) && XLENGTH(top_level) > 0) { |
| 235 | has_top_level_metadata = true; |
| 236 | } |
| 237 | } |
| 238 | |
| 239 | // recurse to get all columns metadata |
| 240 | cpp11::writable::list metadata_columns = CollectColumnMetadata(lst, num_fields); |
| 241 | |
| 242 | // Remove metadata for ExtensionType columns, because these have their own mechanism for |
| 243 | // preserving R type information |
| 244 | for (int i = 0; i < schema->num_fields(); i++) { |
| 245 | if (schema->field(i)->type()->id() == Type::EXTENSION) { |
| 246 | metadata_columns[i] = R_NilValue; |
| 247 | } |
| 248 | } |
| 249 | |
| 250 | // If all metadata_columns are NULL and there is no top-level metadata, set has_metadata |
| 251 | // to false |
| 252 | bool has_metadata = has_top_level_metadata; |
| 253 | for (R_xlen_t i = 0; i < metadata_columns.size(); i++) { |
| 254 | if (metadata_columns[i] != R_NilValue) { |
| 255 | has_metadata = true; |
| 256 | break; |
| 257 | } |
| 258 | } |
| 259 | |
| 260 | // Assign to the output metadata |
| 261 | metadata[1] = metadata_columns; |
| 262 | |
| 263 | if (has_metadata) { |
| 264 | SEXP serialise_call = |
| 265 | PROTECT(Rf_lang2(arrow::r::symbols::serialize_arrow_r_metadata, metadata)); |
| 266 | SEXP serialised = PROTECT(Rf_eval(serialise_call, arrow::r::ns::arrow)); |
| 267 | |
| 268 | schema = schema->WithMetadata( |
| 269 | arrow::key_value_metadata({"r"}, {CHAR(STRING_ELT(serialised, 0))})); |
| 270 | |
| 271 | UNPROTECT(2); |
| 272 | } |
| 273 | |
| 274 | return arrow::Status::OK(); |
| 275 | } |
| 276 |
no test coverage detected