1 | #include <Interpreters/FillingRow.h> |
2 | |
3 | namespace DB |
4 | { |
5 | |
6 | bool less(const Field & lhs, const Field & rhs, int direction) |
7 | { |
8 | if (direction == -1) |
9 | return applyVisitor(FieldVisitorAccurateLess(), rhs, lhs); |
10 | |
11 | return applyVisitor(FieldVisitorAccurateLess(), lhs, rhs); |
12 | } |
13 | |
14 | bool equals(const Field & lhs, const Field & rhs) |
15 | { |
16 | return applyVisitor(FieldVisitorAccurateEquals(), lhs, rhs); |
17 | } |
18 | |
19 | |
20 | FillingRow::FillingRow(const SortDescription & description_) : description(description_) |
21 | { |
22 | row.resize(description.size()); |
23 | } |
24 | |
25 | bool FillingRow::operator<(const FillingRow & other) const |
26 | { |
27 | for (size_t i = 0; i < size(); ++i) |
28 | { |
29 | if (row[i].isNull() || other[i].isNull() || equals(row[i], other[i])) |
30 | continue; |
31 | return less(row[i], other[i], getDirection(i)); |
32 | } |
33 | return false; |
34 | } |
35 | |
36 | bool FillingRow::operator==(const FillingRow & other) const |
37 | { |
38 | for (size_t i = 0; i < size(); ++i) |
39 | if (!equals(row[i], other[i])) |
40 | return false; |
41 | return true; |
42 | } |
43 | |
44 | bool FillingRow::next(const FillingRow & to_row) |
45 | { |
46 | size_t pos = 0; |
47 | |
48 | /// Find position we need to increment for generating next row. |
49 | for (; pos < row.size(); ++pos) |
50 | if (!row[pos].isNull() && !to_row[pos].isNull() && !equals(row[pos], to_row[pos])) |
51 | break; |
52 | |
53 | if (pos == row.size() || less(to_row[pos], row[pos], getDirection(pos))) |
54 | return false; |
55 | |
56 | /// If we have any 'fill_to' value at position greater than 'pos', |
57 | /// we need to generate rows up to 'fill_to' value. |
58 | for (size_t i = row.size() - 1; i > pos; --i) |
59 | { |
60 | if (getFillDescription(i).fill_to.isNull() || row[i].isNull()) |
61 | continue; |
62 | |
63 | auto next_value = row[i]; |
64 | applyVisitor(FieldVisitorSum(getFillDescription(i).fill_step), next_value); |
65 | if (less(next_value, getFillDescription(i).fill_to, getDirection(i))) |
66 | { |
67 | row[i] = next_value; |
68 | initFromDefaults(i + 1); |
69 | return true; |
70 | } |
71 | } |
72 | |
73 | auto next_value = row[pos]; |
74 | applyVisitor(FieldVisitorSum(getFillDescription(pos).fill_step), next_value); |
75 | |
76 | if (less(to_row[pos], next_value, getDirection(pos))) |
77 | return false; |
78 | |
79 | row[pos] = next_value; |
80 | if (equals(row[pos], to_row[pos])) |
81 | { |
82 | bool is_less = false; |
83 | for (size_t i = pos + 1; i < size(); ++i) |
84 | { |
85 | const auto & fill_from = getFillDescription(i).fill_from; |
86 | if (!fill_from.isNull()) |
87 | row[i] = fill_from; |
88 | else |
89 | row[i] = to_row[i]; |
90 | is_less |= less(row[i], to_row[i], getDirection(i)); |
91 | } |
92 | |
93 | return is_less; |
94 | } |
95 | |
96 | initFromDefaults(pos + 1); |
97 | return true; |
98 | } |
99 | |
100 | void FillingRow::initFromDefaults(size_t from_pos) |
101 | { |
102 | for (size_t i = from_pos; i < row.size(); ++i) |
103 | row[i] = getFillDescription(i).fill_from; |
104 | } |
105 | |
106 | |
107 | void insertFromFillingRow(MutableColumns & filling_columns, MutableColumns & other_columns, const FillingRow & filling_row) |
108 | { |
109 | for (size_t i = 0; i < filling_columns.size(); ++i) |
110 | { |
111 | if (filling_row[i].isNull()) |
112 | filling_columns[i]->insertDefault(); |
113 | else |
114 | filling_columns[i]->insert(filling_row[i]); |
115 | } |
116 | |
117 | for (size_t i = 0; i < other_columns.size(); ++i) |
118 | other_columns[i]->insertDefault(); |
119 | } |
120 | |
121 | void copyRowFromColumns(MutableColumns & dest, const Columns & source, size_t row_num) |
122 | { |
123 | for (size_t i = 0; i < source.size(); ++i) |
124 | dest[i]->insertFrom(*source[i], row_num); |
125 | } |
126 | |
127 | } |
128 | |