Creates data type and column from tree of subcolumns.
| 650 | |
| 651 | /// Creates data type and column from tree of subcolumns. |
| 652 | ColumnWithTypeAndDimensions createTypeFromNode(const Node & node) |
| 653 | { |
| 654 | auto collect_tuple_elemets = [](const auto & children) |
| 655 | { |
| 656 | if (children.empty()) |
| 657 | throw Exception(ErrorCodes::LOGICAL_ERROR, "Cannot create type from empty Tuple or Nested node"); |
| 658 | |
| 659 | std::vector<std::tuple<String, ColumnWithTypeAndDimensions>> tuple_elements; |
| 660 | tuple_elements.reserve(children.size()); |
| 661 | for (const auto & [name, child] : children) |
| 662 | { |
| 663 | assert(child); |
| 664 | auto column = createTypeFromNode(*child); |
| 665 | tuple_elements.emplace_back(name, std::move(column)); |
| 666 | } |
| 667 | |
| 668 | /// Sort to always create the same type for the same set of subcolumns. |
| 669 | std::sort(tuple_elements.begin(), tuple_elements.end(), |
| 670 | [](const auto & lhs, const auto & rhs) { return std::get<0>(lhs) < std::get<0>(rhs); }); |
| 671 | |
| 672 | auto tuple_names = extractVector<0>(tuple_elements); |
| 673 | auto tuple_columns = extractVector<1>(tuple_elements); |
| 674 | |
| 675 | return std::make_tuple(std::move(tuple_names), std::move(tuple_columns)); |
| 676 | }; |
| 677 | |
| 678 | if (node.kind == Node::SCALAR) |
| 679 | { |
| 680 | return node.data; |
| 681 | } |
| 682 | else if (node.kind == Node::NESTED) |
| 683 | { |
| 684 | auto [tuple_names, tuple_columns] = collect_tuple_elemets(node.children); |
| 685 | |
| 686 | Columns offsets_columns; |
| 687 | offsets_columns.reserve(tuple_columns[0].array_dimensions + 1); |
| 688 | |
| 689 | /// If we have a Nested node and child node with anonymous array levels |
| 690 | /// we need to push a Nested type through all array levels. |
| 691 | /// Example: { "k1": [[{"k2": 1, "k3": 2}] } should be parsed as |
| 692 | /// `k1 Array(Nested(k2 Int, k3 Int))` and k1 is marked as Nested |
| 693 | /// and `k2` and `k3` has anonymous_array_level = 1 in that case. |
| 694 | |
| 695 | const auto & current_array = assert_cast<const ColumnArray &>(*node.data.column); |
| 696 | offsets_columns.push_back(current_array.getOffsetsPtr()); |
| 697 | |
| 698 | auto first_column = tuple_columns[0].column; |
| 699 | for (size_t i = 0; i < tuple_columns[0].array_dimensions; ++i) |
| 700 | { |
| 701 | const auto & column_array = assert_cast<const ColumnArray &>(*first_column); |
| 702 | offsets_columns.push_back(column_array.getOffsetsPtr()); |
| 703 | first_column = column_array.getDataPtr(); |
| 704 | } |
| 705 | |
| 706 | size_t num_elements = tuple_columns.size(); |
| 707 | Columns tuple_elements_columns(num_elements); |
| 708 | DataTypes tuple_elements_types(num_elements); |
| 709 |
no test coverage detected