OmniSciDB  c07336695a
ColumnarResultsTest.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2019 OmniSci, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
23 #include "../QueryEngine/ColumnarResults.h"
24 #include "../QueryEngine/Descriptors/RowSetMemoryOwner.h"
25 #include "../QueryEngine/ResultSet.h"
26 #include "../QueryEngine/TargetValue.h"
27 #include "../Shared/TargetInfo.h"
28 #include "ResultSetTestUtils.h"
29 #include "TestHelpers.h"
30 
31 #include <gtest/gtest.h>
32 
33 void test_perfect_hash_columnar_conversion(const std::vector<TargetInfo>& target_infos,
34  const QueryMemoryDescriptor& query_mem_desc,
35  const size_t non_empty_step_size,
36  const bool is_parallel_conversion = false) {
37  auto row_set_mem_owner = std::make_shared<RowSetMemoryOwner>();
38  ResultSet result_set(
39  target_infos, ExecutorDeviceType::CPU, query_mem_desc, row_set_mem_owner, nullptr);
40 
41  // fill the storage
42  const auto storage = result_set.allocateStorage();
43  EvenNumberGenerator generator;
44  fill_storage_buffer(storage->getUnderlyingBuffer(),
45  target_infos,
46  query_mem_desc,
47  generator,
48  non_empty_step_size);
49 
50  // Columnar Conversion:
51  std::vector<SQLTypeInfo> col_types;
52  for (size_t i = 0; i < result_set.colCount(); ++i) {
53  col_types.push_back(get_logical_type_info(result_set.getColType(i)));
54  }
55  ColumnarResults columnar_results(
56  row_set_mem_owner, result_set, col_types.size(), col_types);
57  columnar_results.setParallelConversion(is_parallel_conversion);
58 
59  // Validate the results:
60  for (size_t rs_row_idx = 0, cr_row_idx = 0; rs_row_idx < query_mem_desc.getEntryCount();
61  rs_row_idx++) {
62  if (result_set.isRowAtEmpty(rs_row_idx)) {
63  // empty entries should be filtered out for conversion:
64  continue;
65  }
66  const auto row = result_set.getRowAt(rs_row_idx);
67  if (row.empty()) {
68  break;
69  }
70  CHECK_EQ(target_infos.size(), row.size());
71  for (size_t target_idx = 0; target_idx < target_infos.size(); ++target_idx) {
72  const auto& target_info = target_infos[target_idx];
73  const auto& ti = target_info.agg_kind == kAVG ? SQLTypeInfo{kDOUBLE, false}
74  : target_info.sql_type;
75  switch (ti.get_type()) {
76  case kBIGINT: {
77  const auto ival_result_set = v<int64_t>(row[target_idx]);
78  const auto ival_converted =
79  columnar_results.getEntryAt<int64_t>(cr_row_idx, target_idx);
80  ASSERT_EQ(ival_converted, ival_result_set);
81  break;
82  }
83  case kINT: {
84  const auto ival_result_set = v<int64_t>(row[target_idx]);
85  const auto ival_converted =
86  columnar_results.getEntryAt<int32_t>(cr_row_idx, target_idx);
87  ASSERT_EQ(ival_converted, ival_result_set);
88  break;
89  }
90  case kSMALLINT: {
91  const auto ival_result_set = v<int64_t>(row[target_idx]);
92  const auto ival_converted =
93  columnar_results.getEntryAt<int16_t>(cr_row_idx, target_idx);
94  ASSERT_EQ(ival_converted, ival_result_set);
95  break;
96  }
97  case kTINYINT: {
98  const auto ival_result_set = v<int64_t>(row[target_idx]);
99  const auto ival_converted =
100  columnar_results.getEntryAt<int8_t>(cr_row_idx, target_idx);
101  ASSERT_EQ(ival_converted, ival_result_set);
102  break;
103  }
104  case kFLOAT: {
105  const auto fval_result_set = v<float>(row[target_idx]);
106  const auto fval_converted =
107  columnar_results.getEntryAt<float>(cr_row_idx, target_idx);
108  ASSERT_FLOAT_EQ(fval_result_set, fval_converted);
109  break;
110  }
111  case kDOUBLE: {
112  const auto dval_result_set = v<double>(row[target_idx]);
113  const auto dval_converted =
114  columnar_results.getEntryAt<double>(cr_row_idx, target_idx);
115  ASSERT_FLOAT_EQ(dval_result_set, dval_converted);
116  break;
117  }
118  default:
119  UNREACHABLE() << "Invalid type info encountered.";
120  }
121  }
122  cr_row_idx++;
123  }
124 }
125 
126 TEST(Construct, Empty) {
127  std::vector<TargetInfo> target_infos;
128  std::vector<SQLTypeInfo> sql_type_infos;
129  QueryMemoryDescriptor query_mem_desc;
130  auto row_set_mem_owner = std::make_shared<RowSetMemoryOwner>();
131  ResultSet result_set(
132  target_infos, ExecutorDeviceType::CPU, query_mem_desc, row_set_mem_owner, nullptr);
133  ColumnarResults columnar_results(
134  row_set_mem_owner, result_set, sql_type_infos.size(), sql_type_infos);
135 }
136 
137 // Projections:
138 // TODO(Saman): add tests for Projections
139 
140 // Perfect Hash:
141 TEST(PerfectHash, RowWise_64Key_64Agg) {
142  std::vector<int8_t> key_column_widths{8};
143  const int8_t suggested_agg_width = 8;
144  std::vector<TargetInfo> target_infos = generate_custom_agg_target_infos(
145  key_column_widths,
146  {kSUM, kSUM, kCOUNT, kAVG, kMAX, kMIN},
147  {kBIGINT, kBIGINT, kBIGINT, kDOUBLE, kBIGINT, kBIGINT},
148  {kBIGINT, kBIGINT, kBIGINT, kBIGINT, kBIGINT, kBIGINT});
149  auto query_mem_desc =
150  perfect_hash_one_col_desc(target_infos, suggested_agg_width, 0, 118);
151  for (auto is_parallel : {false, true}) {
152  for (auto step_size : {1, 2, 13, 67, 127}) {
154  target_infos, query_mem_desc, step_size, is_parallel);
155  }
156  }
157 }
158 
159 TEST(PerfectHash, RowWise_32Key_64Agg) {
160  std::vector<int8_t> key_column_widths{4};
161  const int8_t suggested_agg_width = 8;
162  std::vector<TargetInfo> target_infos = generate_custom_agg_target_infos(
163  key_column_widths,
164  {kSUM, kSUM, kCOUNT, kAVG, kMAX, kMIN},
165  {kBIGINT, kBIGINT, kBIGINT, kDOUBLE, kBIGINT, kBIGINT},
166  {kBIGINT, kBIGINT, kBIGINT, kBIGINT, kBIGINT, kBIGINT});
167  auto query_mem_desc =
168  perfect_hash_one_col_desc(target_infos, suggested_agg_width, 0, 118);
169  for (auto is_parallel : {false, true}) {
170  for (auto step_size : {1, 3, 17, 33, 117}) {
172  target_infos, query_mem_desc, step_size, is_parallel);
173  }
174  }
175 }
176 
177 TEST(PerfectHash, RowWise_64Key_MixedAggs) {
178  std::vector<int8_t> key_column_widths{8};
179  const int8_t suggested_agg_width = 8;
180  std::vector<TargetInfo> target_infos = generate_custom_agg_target_infos(
181  key_column_widths,
182  {kMAX, kMAX, kMAX, kMAX, kMAX, kMAX},
184  {kTINYINT, kSMALLINT, kINT, kBIGINT, kFLOAT, kDOUBLE});
185  auto query_mem_desc =
186  perfect_hash_one_col_desc(target_infos, suggested_agg_width, 0, 118);
187  for (auto is_parallel : {false, true}) {
188  for (auto step_size : {2, 13, 67, 127}) {
190  target_infos, query_mem_desc, step_size, is_parallel);
191  }
192  }
193 }
194 
195 TEST(PerfectHash, RowWise_32Key_MixedAggs) {
196  std::vector<int8_t> key_column_widths{4};
197  const int8_t suggested_agg_width = 8;
198  std::vector<TargetInfo> target_infos = generate_custom_agg_target_infos(
199  key_column_widths,
200  {kMAX, kMAX, kMAX, kMAX, kMAX, kMAX},
202  {kDOUBLE, kFLOAT, kBIGINT, kINT, kSMALLINT, kTINYINT});
203  auto query_mem_desc =
204  perfect_hash_one_col_desc(target_infos, suggested_agg_width, 0, 118);
205  for (auto is_parallel : {false, true}) {
206  for (auto step_size : {3, 7, 17, 33, 117}) {
208  target_infos, query_mem_desc, step_size, is_parallel);
209  }
210  }
211 }
212 
213 TEST(PerfectHash, Columnar_64Key_64Agg) {
214  std::vector<int8_t> key_column_widths{8};
215  const int8_t suggested_agg_width = 8;
216  std::vector<TargetInfo> target_infos = generate_custom_agg_target_infos(
217  key_column_widths,
218  {kSUM, kSUM, kCOUNT, kAVG, kMAX, kMIN},
219  {kBIGINT, kBIGINT, kBIGINT, kDOUBLE, kBIGINT, kBIGINT},
220  {kBIGINT, kBIGINT, kBIGINT, kBIGINT, kBIGINT, kBIGINT});
221  auto query_mem_desc =
222  perfect_hash_one_col_desc(target_infos, suggested_agg_width, 0, 118);
223  query_mem_desc.setOutputColumnar(true);
224  for (auto is_parallel : {false, true}) {
225  for (auto step_size : {1, 2, 13, 67, 127}) {
227  target_infos, query_mem_desc, step_size, is_parallel);
228  }
229  }
230 }
231 
232 TEST(PerfectHash, Columnar_64Key_MixedAggs) {
233  std::vector<int8_t> key_column_widths{8};
234  const int8_t suggested_agg_width = 1;
235  std::vector<TargetInfo> target_infos = generate_custom_agg_target_infos(
236  key_column_widths,
237  {kMAX, kMAX, kMAX, kMAX, kMAX, kMAX, kAVG},
240  auto query_mem_desc =
241  perfect_hash_one_col_desc(target_infos, suggested_agg_width, 0, 118);
242  query_mem_desc.setOutputColumnar(true);
243  for (auto is_parallel : {false, true}) {
244  for (auto step_size : {3, 7, 16, 37, 127}) {
246  target_infos, query_mem_desc, step_size, is_parallel);
247  }
248  }
249 }
250 
251 TEST(PerfectHash, Columnar_32Key_MixedAggs) {
252  std::vector<int8_t> key_column_widths{4};
253  const int8_t suggested_agg_width = 1;
254  std::vector<TargetInfo> target_infos = generate_custom_agg_target_infos(
255  key_column_widths,
256  {kMAX, kMAX, kMAX, kMAX, kMAX, kMAX, kAVG},
259  auto query_mem_desc =
260  perfect_hash_one_col_desc(target_infos, suggested_agg_width, 0, 118);
261  query_mem_desc.setOutputColumnar(true);
262  for (auto is_parallel : {false, true}) {
263  for (auto step_size : {3, 7, 16, 37, 127}) {
265  target_infos, query_mem_desc, step_size, is_parallel);
266  }
267  }
268 }
269 
270 TEST(PerfectHash, Columnar_16Key_MixedAggs) {
271  std::vector<int8_t> key_column_widths{2};
272  const int8_t suggested_agg_width = 1;
273  std::vector<TargetInfo> target_infos = generate_custom_agg_target_infos(
274  key_column_widths,
275  {kMAX, kMAX, kMAX, kMAX, kMAX, kMAX, kAVG},
278  auto query_mem_desc =
279  perfect_hash_one_col_desc(target_infos, suggested_agg_width, 0, 118);
280  query_mem_desc.setOutputColumnar(true);
281  for (auto is_parallel : {false, true}) {
282  for (auto step_size : {3, 7, 16, 37, 127}) {
284  target_infos, query_mem_desc, step_size, is_parallel);
285  }
286  }
287 }
288 
289 TEST(PerfectHash, Columnar_8Key_MixedAggs) {
290  std::vector<int8_t> key_column_widths{1};
291  const int8_t suggested_agg_width = 1;
292  std::vector<TargetInfo> target_infos = generate_custom_agg_target_infos(
293  key_column_widths,
294  {kMAX, kMAX, kMAX, kMAX, kMAX, kMAX, kAVG},
297  auto query_mem_desc =
298  perfect_hash_one_col_desc(target_infos, suggested_agg_width, 0, 118);
299  query_mem_desc.setOutputColumnar(true);
300  for (auto is_parallel : {false, true}) {
301  for (auto step_size : {3, 7, 16, 37, 127}) {
303  target_infos, query_mem_desc, step_size, is_parallel);
304  }
305  }
306 }
307 
308 // TODO(Saman): add tests for multi-column perfect hash
309 // Baseline Hash:
310 // TODO(Saman): add tests for baseline hash
311 int main(int argc, char** argv) {
313  testing::InitGoogleTest(&argc, argv);
314 
315  int err{0};
316  try {
317  err = RUN_ALL_TESTS();
318  } catch (const std::exception& e) {
319  LOG(ERROR) << e.what();
320  }
321  return err;
322 }
#define CHECK_EQ(x, y)
Definition: Logger.h:195
#define LOG(tag)
Definition: Logger.h:182
void test_perfect_hash_columnar_conversion(const std::vector< TargetInfo > &target_infos, const QueryMemoryDescriptor &query_mem_desc, const size_t non_empty_step_size, const bool is_parallel_conversion=false)
#define UNREACHABLE()
Definition: Logger.h:231
SQLTypeInfo get_logical_type_info(const SQLTypeInfo &type_info)
Definition: sqltypes.h:836
void setParallelConversion(const bool is_parallel)
Definition: sqldefs.h:71
QueryMemoryDescriptor perfect_hash_one_col_desc(const std::vector< TargetInfo > &target_infos, const int8_t num_bytes, const size_t min_val, const size_t max_val, std::vector< int8_t > group_column_widths)
Definition: sqldefs.h:71
TEST(Construct, Empty)
Definition: sqldefs.h:71
void init_logger_stderr_only(int argc, char const *const *argv)
Definition: TestHelpers.h:194
Definition: sqltypes.h:47
int main(int argc, char **argv)
Definition: sqldefs.h:71
Definition: sqldefs.h:71
std::vector< TargetInfo > generate_custom_agg_target_infos(std::vector< int8_t > group_columns, std::vector< SQLAgg > sql_aggs, std::vector< SQLTypes > agg_types, std::vector< SQLTypes > arg_types)
void fill_storage_buffer(int8_t *buff, const std::vector< TargetInfo > &target_infos, const QueryMemoryDescriptor &query_mem_desc, NumberGenerator &generator, const size_t step)