1#include <Interpreters/FillingRow.h>
2
3namespace DB
4{
5
6bool 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
14bool equals(const Field & lhs, const Field & rhs)
15{
16 return applyVisitor(FieldVisitorAccurateEquals(), lhs, rhs);
17}
18
19
20FillingRow::FillingRow(const SortDescription & description_) : description(description_)
21{
22 row.resize(description.size());
23}
24
25bool 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
36bool 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
44bool 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
100void 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
107void 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
121void 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