@@ -10,6 +10,8 @@ namespace
10
10
using namespace clickhouse ;
11
11
}
12
12
13
+ #define DBMS_MIN_REVISION_WITH_CUSTOM_SERIALIZATION 54454
14
+
13
15
static const auto localHostEndpoint = ClientOptions()
14
16
.SetHost( getEnvOrDefault(" CLICKHOUSE_HOST" , " localhost" ))
15
17
.SetPort( getEnvOrDefault<size_t >(" CLICKHOUSE_PORT" , " 9000" ))
@@ -30,19 +32,31 @@ class SparseCase : public testing::Test {
30
32
}
31
33
32
34
template <typename T>
33
- std::shared_ptr<T> createTableWithOneColumn ( )
35
+ bool createTable ( std::shared_ptr<T> col )
34
36
{
35
- auto col = std::make_shared<T>();
36
37
const auto type_name = col->GetType ().GetName ();
37
38
38
39
client_->Execute (" DROP TABLE IF EXISTS " + table_name + " ;" );
39
- client_->Execute (" CREATE TABLE IF NOT EXISTS " + table_name + " ( id UInt64," + column_name + " " + type_name + " )"
40
- " ENGINE = MergeTree ORDER BY id "
41
- " SETTINGS index_granularity = 32, "
42
- " ratio_of_defaults_for_sparse_serialization = 0.1;" );
40
+ try {
41
+ client_->Execute (" CREATE TABLE IF NOT EXISTS " + table_name + " ( id UInt64," + column_name + " " + type_name + " )"
42
+ " ENGINE = MergeTree ORDER BY id "
43
+ " SETTINGS index_granularity = 32, "
44
+ " ratio_of_defaults_for_sparse_serialization = 0.1;" );
45
+ } catch (const std::exception & e) {
46
+ std::cerr << " Got error while create table: " << e.what () << std::endl;
47
+ // DB::Exception: clickhouse_cpp_cicd: Cannot execute query in readonly mode
48
+ if (std::string (e.what ()).find (" Cannot execute query in readonly mode" ) != std::string::npos) {
49
+ return false ;
50
+ }
51
+ // DB::Exception: clickhouse_cpp_cicd: Not enough privileges. To execute this query it's necessary to have grant CREATE TABLE ON default.test_clickhouse_cpp_test_ut_sparse_table
52
+ if (std::string (e.what ()).find (" Not enough privileges" ) != std::string::npos) {
53
+ return false ;
54
+ }
55
+ throw ;
56
+ }
43
57
44
58
client_->Execute (" SYSTEM STOP MERGES test_clickhouse_sparse_table;" );
45
- return col ;
59
+ return true ;
46
60
}
47
61
48
62
std::string getOneColumnSelectQuery () const
@@ -77,9 +91,15 @@ class SparseCase : public testing::Test {
77
91
78
92
TEST_F (SparseCase, UInt64_Load) {
79
93
80
- createTableWithOneColumn<ColumnUInt64>();
94
+ if (client_->GetServerInfo ().revision < DBMS_MIN_REVISION_WITH_CUSTOM_SERIALIZATION) {
95
+ GTEST_SKIP ();
96
+ }
97
+
98
+ if (!createTable (std::make_shared<ColumnUInt64>())) {
99
+ GTEST_SKIP ();
100
+ }
81
101
82
- client_->Execute (" INSERT INTO " + table_name +" "
102
+ client_->Execute (" INSERT INTO " + table_name +
83
103
" SELECT number, "
84
104
" if (number % 10 = 0, number, 0)"
85
105
" FROM numbers(1000);" );
@@ -95,6 +115,7 @@ TEST_F(SparseCase, UInt64_Load) {
95
115
ASSERT_EQ (1U , block.GetColumnCount ());
96
116
ASSERT_TRUE (block[0 ]->GetType ().IsEqual (Type::CreateSimple<uint64_t >()));
97
117
auto cl = block[0 ]->AsStrict <ColumnUInt64>();
118
+ ASSERT_EQ (cl->GetSerialization ()->GetKind (), Serialization::Kind::SPARSE);
98
119
for (size_t i = 0 ; i < 1000 ; ++i) {
99
120
if (i % 10 == 0 ) {
100
121
EXPECT_EQ (cl->At (i), i);
@@ -103,6 +124,128 @@ TEST_F(SparseCase, UInt64_Load) {
103
124
}
104
125
}
105
126
});
127
+ }
128
+
129
+ TEST_F (SparseCase, String_Load) {
130
+
131
+ if (client_->GetServerInfo ().revision < DBMS_MIN_REVISION_WITH_CUSTOM_SERIALIZATION) {
132
+ GTEST_SKIP ();
133
+ }
134
+
135
+ if (!createTable (std::make_shared<ColumnString>())) {
136
+ GTEST_SKIP ();
137
+ }
138
+
139
+ client_->Execute (" INSERT INTO " + table_name +
140
+ " SELECT number, "
141
+ " if (number % 10 = 0, toString(number), '')"
142
+ " FROM numbers(1000);" );
143
+
144
+ checkSerializationKind ();
145
+
146
+ client_->Select (getOneColumnSelectQuery (),
147
+ [&](const Block& block) {
148
+ // std::cerr << PrettyPrintBlock{block} << std::endl;
149
+ if (block.GetRowCount () == 0 )
150
+ return ;
151
+ EXPECT_EQ (1000u , block.GetRowCount ());
152
+ ASSERT_EQ (1U , block.GetColumnCount ());
153
+ ASSERT_TRUE (block[0 ]->GetType ().IsEqual (Type::CreateString ()));
154
+ auto cl = block[0 ]->AsStrict <ColumnString>();
155
+ ASSERT_EQ (cl->GetSerialization ()->GetKind (), Serialization::Kind::SPARSE);
156
+ for (size_t i = 0 ; i < 1000 ; ++i) {
157
+ if (i % 10 == 0 ) {
158
+ EXPECT_EQ (cl->At (i), std::to_string (i));
159
+ } else {
160
+ EXPECT_EQ (cl->At (i), " " );
161
+ }
162
+ }
163
+ });
164
+ }
165
+
166
+ TEST_F (SparseCase, FixedString_Load) {
167
+ const size_t FixedStringSize = 10 ;
168
+
169
+ if (client_->GetServerInfo ().revision < DBMS_MIN_REVISION_WITH_CUSTOM_SERIALIZATION) {
170
+ GTEST_SKIP ();
171
+ }
172
+
173
+ if (!createTable (std::make_shared<ColumnFixedString>(FixedStringSize))) {
174
+ GTEST_SKIP ();
175
+ }
176
+
177
+ client_->Execute (" INSERT INTO " + table_name +
178
+ " SELECT number, "
179
+ " if (number % 10 = 0, toString(number), '')"
180
+ " FROM numbers(1000);" );
181
+
182
+ checkSerializationKind ();
183
+
184
+ auto rpad = [](const std::string& val) {
185
+ std::string res = val;
186
+ res.append (std::string (FixedStringSize - res.size (), ' \0 ' ));
187
+ return res;
188
+ };
189
+
190
+ client_->Select (getOneColumnSelectQuery (),
191
+ [&](const Block& block) {
192
+ // std::cerr << PrettyPrintBlock{block} << std::endl;
193
+ if (block.GetRowCount () == 0 )
194
+ return ;
195
+ EXPECT_EQ (1000u , block.GetRowCount ());
196
+ ASSERT_EQ (1U , block.GetColumnCount ());
197
+ ASSERT_TRUE (block[0 ]->GetType ().IsEqual (Type::CreateString (FixedStringSize)));
198
+ auto cl = block[0 ]->AsStrict <ColumnFixedString>();
199
+ EXPECT_EQ (cl->GetSerialization ()->GetKind (), Serialization::Kind::SPARSE);
200
+ for (size_t i = 0 ; i < 1000 ; ++i) {
201
+ if (i % 10 == 0 ) {
202
+ EXPECT_EQ (cl->At (i), rpad (std::to_string (i)));
203
+ } else {
204
+ EXPECT_EQ (cl->At (i), rpad (" " ));
205
+ }
206
+ }
207
+ });
208
+ }
106
209
107
210
211
+ TEST_F (SparseCase, Tuple_Load) {
212
+
213
+ if (client_->GetServerInfo ().revision < DBMS_MIN_REVISION_WITH_CUSTOM_SERIALIZATION) {
214
+ GTEST_SKIP ();
215
+ }
216
+
217
+ auto tuple = std::make_shared<ColumnTuple>(std::vector<ColumnRef>({
218
+ std::make_shared<ColumnUInt64>(),
219
+ std::make_shared<ColumnString>()
220
+ }));
221
+
222
+ if (!createTable (tuple)) {
223
+ GTEST_SKIP ();
224
+ }
225
+
226
+ client_->Execute (" INSERT INTO " + table_name +
227
+ " SELECT number, "
228
+ " (if (number % 10 = 0, number, 0), repeat('a', number % 10 + 1))"
229
+ " FROM numbers(1000);" );
230
+
231
+ client_->Select (getOneColumnSelectQuery (),
232
+ [&](const Block& block) {
233
+ // std::cerr << PrettyPrintBlock{block} << std::endl;
234
+ if (block.GetRowCount () == 0 )
235
+ return ;
236
+ EXPECT_EQ (1000u , block.GetRowCount ());
237
+ ASSERT_EQ (1U , block.GetColumnCount ());
238
+ auto cl = block[0 ]->AsStrict <ColumnTuple>();
239
+ ASSERT_EQ (2U , cl->TupleSize ());
240
+ EXPECT_EQ ((*cl)[0 ]->GetSerialization ()->GetKind (), Serialization::Kind::SPARSE);
241
+ EXPECT_EQ ((*cl)[1 ]->GetSerialization ()->GetKind (), Serialization::Kind::DEFAULT);
242
+ auto cl_int = (*cl)[0 ]->AsStrict <ColumnUInt64>();
243
+ for (size_t i = 0 ; i < 1000 ; ++i) {
244
+ if (i % 10 == 0 ) {
245
+ EXPECT_EQ (cl_int->At (i), i);
246
+ } else {
247
+ EXPECT_EQ (cl_int->At (i), 0u );
248
+ }
249
+ }
250
+ });
108
251
}
0 commit comments