1#include <Interpreters/addMissingDefaults.h>
2
3#include <Common/typeid_cast.h>
4#include <DataTypes/NestedUtils.h>
5#include <DataTypes/DataTypeArray.h>
6#include <Columns/ColumnArray.h>
7#include <Interpreters/evaluateMissingDefaults.h>
8#include <Core/Block.h>
9#include <Storages/ColumnDefault.h>
10
11
12namespace DB
13{
14
15Block addMissingDefaults(const Block & block,
16 const NamesAndTypesList & required_columns,
17 const ColumnDefaults & column_defaults,
18 const Context & context)
19{
20 /// For missing columns of nested structure, you need to create not a column of empty arrays, but a column of arrays of correct lengths.
21 /// First, remember the offset columns for all arrays in the block.
22 std::map<String, ColumnPtr> offset_columns;
23
24 for (size_t i = 0, size = block.columns(); i < size; ++i)
25 {
26 const auto & elem = block.getByPosition(i);
27
28 if (const ColumnArray * array = typeid_cast<const ColumnArray *>(&*elem.column))
29 {
30 String offsets_name = Nested::extractTableName(elem.name);
31 auto & offsets_column = offset_columns[offsets_name];
32
33 /// If for some reason there are different offset columns for one nested structure, then we take nonempty.
34 if (!offsets_column || offsets_column->empty())
35 offsets_column = array->getOffsetsPtr();
36 }
37 }
38
39 const size_t rows = block.rows();
40 Block res;
41
42 /// We take given columns from input block and missed columns without default value
43 /// (default and materialized will be computed later).
44 for (const auto & column : required_columns)
45 {
46 if (block.has(column.name))
47 {
48 res.insert(block.getByName(column.name));
49 continue;
50 }
51
52 if (column_defaults.count(column.name))
53 continue;
54
55 String offsets_name = Nested::extractTableName(column.name);
56 if (offset_columns.count(offsets_name))
57 {
58 ColumnPtr offsets_column = offset_columns[offsets_name];
59 DataTypePtr nested_type = typeid_cast<const DataTypeArray &>(*column.type).getNestedType();
60 UInt64 nested_rows = rows ? get<UInt64>((*offsets_column)[rows - 1]) : 0;
61
62 ColumnPtr nested_column = nested_type->createColumnConstWithDefaultValue(nested_rows)->convertToFullColumnIfConst();
63 auto new_column = ColumnArray::create(nested_column, offsets_column);
64 res.insert(ColumnWithTypeAndName(std::move(new_column), column.type, column.name));
65 continue;
66 }
67
68 /** It is necessary to turn a constant column into a full column, since in part of blocks (from other parts),
69 * it can be full (or the interpreter may decide that it is constant everywhere).
70 */
71 auto new_column = column.type->createColumnConstWithDefaultValue(rows)->convertToFullColumnIfConst();
72 res.insert(ColumnWithTypeAndName(std::move(new_column), column.type, column.name));
73 }
74
75 /// Computes explicitly specified values (in column_defaults) by default and materialized columns.
76 evaluateMissingDefaults(res, required_columns, column_defaults, context);
77 return res;
78}
79
80}
81