1#pragma once
2
3#include <vector>
4#include <list>
5#include <set>
6#include <map>
7#include <initializer_list>
8
9#include <Core/BlockInfo.h>
10#include <Core/NamesAndTypes.h>
11#include <Core/ColumnWithTypeAndName.h>
12#include <Core/ColumnsWithTypeAndName.h>
13
14
15
16namespace DB
17{
18
19/** Container for set of columns for bunch of rows in memory.
20 * This is unit of data processing.
21 * Also contains metadata - data types of columns and their names
22 * (either original names from a table, or generated names during temporary calculations).
23 * Allows to insert, remove columns in arbitrary position, to change order of columns.
24 */
25
26class Context;
27
28class Block
29{
30private:
31 using Container = ColumnsWithTypeAndName;
32 using IndexByName = std::map<String, size_t>;
33
34 Container data;
35 IndexByName index_by_name;
36
37public:
38 BlockInfo info;
39
40 Block() = default;
41 Block(std::initializer_list<ColumnWithTypeAndName> il);
42 Block(const ColumnsWithTypeAndName & data_);
43
44 /// insert the column at the specified position
45 void insert(size_t position, const ColumnWithTypeAndName & elem);
46 void insert(size_t position, ColumnWithTypeAndName && elem);
47 /// insert the column to the end
48 void insert(const ColumnWithTypeAndName & elem);
49 void insert(ColumnWithTypeAndName && elem);
50 /// insert the column to the end, if there is no column with that name yet
51 void insertUnique(const ColumnWithTypeAndName & elem);
52 void insertUnique(ColumnWithTypeAndName && elem);
53 /// remove the column at the specified position
54 void erase(size_t position);
55 /// remove the columns at the specified positions
56 void erase(const std::set<size_t> & positions);
57 /// remove the column with the specified name
58 void erase(const String & name);
59
60 /// References are invalidated after calling functions above.
61
62 ColumnWithTypeAndName & getByPosition(size_t position) { return data[position]; }
63 const ColumnWithTypeAndName & getByPosition(size_t position) const { return data[position]; }
64
65 ColumnWithTypeAndName & safeGetByPosition(size_t position);
66 const ColumnWithTypeAndName & safeGetByPosition(size_t position) const;
67
68 ColumnWithTypeAndName & getByName(const std::string & name);
69 const ColumnWithTypeAndName & getByName(const std::string & name) const;
70
71 Container::iterator begin() { return data.begin(); }
72 Container::iterator end() { return data.end(); }
73 Container::const_iterator begin() const { return data.begin(); }
74 Container::const_iterator end() const { return data.end(); }
75 Container::const_iterator cbegin() const { return data.cbegin(); }
76 Container::const_iterator cend() const { return data.cend(); }
77
78 bool has(const std::string & name) const;
79
80 size_t getPositionByName(const std::string & name) const;
81
82 const ColumnsWithTypeAndName & getColumnsWithTypeAndName() const;
83 NamesAndTypesList getNamesAndTypesList() const;
84 Names getNames() const;
85 DataTypes getDataTypes() const;
86
87 /// Returns number of rows from first column in block, not equal to nullptr. If no columns, returns 0.
88 size_t rows() const;
89
90 size_t columns() const { return data.size(); }
91
92 /// Checks that every column in block is not nullptr and has same number of elements.
93 void checkNumberOfRows(bool allow_null_columns = false) const;
94
95 /// Approximate number of bytes in memory - for profiling and limits.
96 size_t bytes() const;
97
98 /// Approximate number of allocated bytes in memory - for profiling and limits.
99 size_t allocatedBytes() const;
100
101 operator bool() const { return !!columns(); }
102 bool operator!() const { return !this->operator bool(); }
103
104 /** Get a list of column names separated by commas. */
105 std::string dumpNames() const;
106
107 /** List of names, types and lengths of columns. Designed for debugging. */
108 std::string dumpStructure() const;
109
110 /** Get the same block, but empty. */
111 Block cloneEmpty() const;
112
113 Columns getColumns() const;
114 void setColumns(const Columns & columns);
115 Block cloneWithColumns(const Columns & columns) const;
116 Block cloneWithoutColumns() const;
117
118 /** Get empty columns with the same types as in block. */
119 MutableColumns cloneEmptyColumns() const;
120
121 /** Get columns from block for mutation. Columns in block will be nullptr. */
122 MutableColumns mutateColumns();
123
124 /** Replace columns in a block */
125 void setColumns(MutableColumns && columns);
126 Block cloneWithColumns(MutableColumns && columns) const;
127
128 /** Get a block with columns that have been rearranged in the order of their names. */
129 Block sortColumns() const;
130
131 void clear();
132 void swap(Block & other) noexcept;
133
134 /** Updates SipHash of the Block, using update method of columns.
135 * Returns hash for block, that could be used to differentiate blocks
136 * with same structure, but different data.
137 */
138 void updateHash(SipHash & hash) const;
139
140private:
141 void eraseImpl(size_t position);
142 void initializeIndexByName();
143};
144
145using Blocks = std::vector<Block>;
146using BlocksList = std::list<Block>;
147using BlocksPtr = std::shared_ptr<Blocks>;
148using BlocksPtrs = std::shared_ptr<std::vector<BlocksPtr>>;
149
150/// Compare number of columns, data types, column types, column names, and values of constant columns.
151bool blocksHaveEqualStructure(const Block & lhs, const Block & rhs);
152
153/// Throw exception when blocks are different.
154void assertBlocksHaveEqualStructure(const Block & lhs, const Block & rhs, const std::string & context_description);
155
156/// Calculate difference in structure of blocks and write description into output strings. NOTE It doesn't compare values of constant columns.
157void getBlocksDifference(const Block & lhs, const Block & rhs, std::string & out_lhs_diff, std::string & out_rhs_diff);
158
159}
160