| 304 | /// with the sole ancestor `t`, never the unrelated path `t.p`. |
| 305 | template <typename LeafCallback> |
| 306 | static void flattenTupleRecursiveImpl( |
| 307 | const ColumnPtr & column, |
| 308 | const DataTypePtr & data_type, |
| 309 | LeafCallback && emit_leaf, |
| 310 | const String & name_prefix, |
| 311 | const Strings & ancestors) |
| 312 | { |
| 313 | const auto * tuple_type = tryGetFlattenableTuple(data_type); |
| 314 | if (!tuple_type) |
| 315 | { |
| 316 | emit_leaf(column, data_type, name_prefix, ancestors); |
| 317 | return; |
| 318 | } |
| 319 | |
| 320 | /// If the column is ColumnConst, expand it to a full column first, |
| 321 | /// so that all leaf columns are always non-const after flattening. |
| 322 | ColumnPtr materialized_column = column->convertToFullColumnIfConst(); |
| 323 | const auto * column_tuple = assert_cast<const ColumnTuple *>(materialized_column.get()); |
| 324 | |
| 325 | const DataTypes & element_types = tuple_type->getElements(); |
| 326 | const Strings & element_names = tuple_type->getElementNames(); |
| 327 | const auto & sub_columns = column_tuple->getColumns(); |
| 328 | |
| 329 | /// `name_prefix` is empty only on the column-only flattening path (flattenTupleColumnsRecursive), |
| 330 | /// where leaf names and ancestors are unused, so skip building them there. |
| 331 | const bool build_metadata = !name_prefix.empty(); |
| 332 | |
| 333 | Strings element_ancestors = ancestors; |
| 334 | if (build_metadata) |
| 335 | element_ancestors.push_back(name_prefix); |
| 336 | |
| 337 | for (size_t i = 0; i < element_types.size(); ++i) |
| 338 | { |
| 339 | String element_name = build_metadata ? concatenateName(name_prefix, element_names[i]) : String{}; |
| 340 | flattenTupleRecursiveImpl(sub_columns[i], element_types[i], emit_leaf, element_name, element_ancestors); |
| 341 | } |
| 342 | } |
| 343 | |
| 344 | Block flattenTupleRecursive(const Block & block, std::vector<Strings> * flattened_ancestors) |
| 345 | { |
no test coverage detected