OmniSciDB  cde582ebc3
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
QueryHint.h
Go to the documentation of this file.
1 /*
2  * Copyright 2022 HEAVY.AI, 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 
17 #ifndef OMNISCI_QUERYHINT_H
18 #define OMNISCI_QUERYHINT_H
19 
20 #include <algorithm>
21 #include <optional>
22 
23 #include <boost/algorithm/string.hpp>
24 
26 
27 // we expect query hint enum val starts with zero,
28 // and let remaining enum value to be auto-incremented
29 enum QueryHint {
30  kCpuMode = 0,
41  kHintCount, // should be at the last elem before INVALID enum value to count #
42  // supported hints correctly
43  kInvalidHint // this should be the last elem of this enum
44 };
45 
46 static const std::unordered_map<std::string, QueryHint> SupportedQueryHints = {
47  {"cpu_mode", QueryHint::kCpuMode},
48  {"columnar_output", QueryHint::kColumnarOutput},
49  {"rowwise_output", QueryHint::kRowwiseOutput},
50  {"overlaps_bucket_threshold", QueryHint::kOverlapsBucketThreshold},
51  {"overlaps_max_size", QueryHint::kOverlapsMaxSize},
52  {"overlaps_allow_gpu_build", QueryHint::kOverlapsAllowGpuBuild},
53  {"overlaps_no_cache", QueryHint::kOverlapsNoCache},
54  {"overlaps_keys_per_bin", QueryHint::kOverlapsKeysPerBin},
55  {"keep_result", QueryHint::kKeepResult},
56  {"keep_table_function_result", QueryHint::kKeepTableFuncResult},
57  {"aggregate_tree_fanout", QueryHint::kAggregateTreeFanout}};
58 
61  std::string hint_name;
62 
63  HintIdentifier(bool global_hint, const std::string& hint_name)
64  : global_hint(global_hint), hint_name(hint_name){};
65 };
66 
68  // this class represents parsed query hint's specification
69  // our query AST analyzer translates query hint string to understandable form which we
70  // called "ExplainedQueryHint"
71  public:
73  bool global_hint,
74  bool is_marker,
75  bool has_kv_type_options)
76  : hint_(hint)
77  , global_hint_(global_hint)
78  , is_marker_(is_marker)
79  , has_kv_type_options_(has_kv_type_options) {}
80 
82  bool global_hint,
83  bool is_marker,
84  bool has_kv_type_options,
85  std::vector<std::string>& list_options)
86  : hint_(hint)
87  , global_hint_(global_hint)
88  , is_marker_(is_marker)
89  , has_kv_type_options_(has_kv_type_options)
90  , list_options_(std::move(list_options)) {}
91 
93  bool global_hint,
94  bool is_marker,
95  bool has_kv_type_options,
96  std::unordered_map<std::string, std::string>& kv_options)
97  : hint_(hint)
98  , global_hint_(global_hint)
99  , is_marker_(is_marker)
100  , has_kv_type_options_(has_kv_type_options)
101  , kv_options_(std::move(kv_options)) {}
102 
103  void setListOptions(std::vector<std::string>& list_options) {
104  list_options_ = list_options;
105  }
106 
107  void setKVOptions(std::unordered_map<std::string, std::string>& kv_options) {
108  kv_options_ = kv_options;
109  }
110 
111  void setInheritPaths(std::vector<int>& interit_paths) {
112  inherit_paths_ = interit_paths;
113  }
114 
115  const std::vector<std::string>& getListOptions() { return list_options_; }
116 
117  const std::vector<int>& getInteritPath() { return inherit_paths_; }
118 
119  const std::unordered_map<std::string, std::string>& getKVOptions() {
120  return kv_options_;
121  }
122 
123  const QueryHint getHint() const { return hint_; }
124 
125  bool isGlobalHint() const { return global_hint_; }
126 
127  bool hasOptions() const { return is_marker_; }
128 
129  bool hasKvOptions() const { return has_kv_type_options_; }
130 
131  private:
133  // Set true if this hint affects globally
134  // Otherwise it just affects the node which this hint is included (aka table hint)
136  // set true if this has no extra options (neither list_options nor kv_options)
138  // Set true if it is not a marker and has key-value type options
139  // Otherwise (it is not a marker but has list type options), we set this be false
141  std::vector<int> inherit_paths_; // currently not used
142  std::vector<std::string> list_options_;
143  std::unordered_map<std::string, std::string> kv_options_;
144 };
145 
147  // for each query hint, we first translate the raw query hint info
148  // to understandable form called "ExplainedQueryHint"
149  // and we get all necessary info from it and organize it into "RegisteredQueryHint"
150  // so by using "RegisteredQueryHint", we can know and access which query hint is
151  // registered and its detailed info such as the hint's parameter values given by user
153  : cpu_mode(false)
157  , overlaps_bucket_threshold(std::numeric_limits<double>::max())
163 
165  CHECK_EQ(registered_hint.size(), global_hints.registered_hint.size());
166  // apply registered global hint to the local hint if necessary
167  // we prioritize global hint when both side of hints are enabled simultaneously
168  RegisteredQueryHint updated_query_hints(*this);
169 
170  int num_hints = static_cast<int>(QueryHint::kHintCount);
171  for (int i = 0; i < num_hints; ++i) {
172  if (global_hints.registered_hint.at(i)) {
173  updated_query_hints.registered_hint.at(i) = global_hints.registered_hint[i];
174  switch (i) {
175  case static_cast<int>(QueryHint::kCpuMode): {
176  updated_query_hints.cpu_mode = true;
177  break;
178  }
179  case static_cast<int>(QueryHint::kColumnarOutput): {
180  updated_query_hints.columnar_output = true;
181  break;
182  }
183  case static_cast<int>(QueryHint::kRowwiseOutput): {
184  updated_query_hints.rowwise_output = true;
185  break;
186  }
187  case static_cast<int>(QueryHint::kOverlapsBucketThreshold): {
188  updated_query_hints.overlaps_bucket_threshold =
189  global_hints.overlaps_bucket_threshold;
190  break;
191  }
192  case static_cast<int>(QueryHint::kOverlapsMaxSize): {
193  updated_query_hints.overlaps_max_size = global_hints.overlaps_max_size;
194  break;
195  }
196  case static_cast<int>(QueryHint::kOverlapsAllowGpuBuild): {
197  updated_query_hints.overlaps_allow_gpu_build = true;
198  break;
199  }
200  case static_cast<int>(QueryHint::kOverlapsNoCache): {
201  updated_query_hints.overlaps_no_cache = true;
202  break;
203  }
204  case static_cast<int>(QueryHint::kOverlapsKeysPerBin): {
205  updated_query_hints.overlaps_keys_per_bin =
206  global_hints.overlaps_keys_per_bin;
207  break;
208  }
209  case static_cast<int>(QueryHint::kKeepResult): {
210  updated_query_hints.keep_result = global_hints.keep_result;
211  break;
212  }
213  case static_cast<int>(QueryHint::kKeepTableFuncResult): {
214  updated_query_hints.keep_table_function_result =
215  global_hints.keep_table_function_result;
216  break;
217  }
218  case static_cast<int>(QueryHint::kAggregateTreeFanout): {
219  updated_query_hints.aggregate_tree_fanout =
220  global_hints.aggregate_tree_fanout;
221  }
222  }
223  }
224  }
225  return updated_query_hints;
226  }
227 
228  // general query execution
229  bool cpu_mode;
234 
235  // window function framing
237 
238  // overlaps hash join
239  double overlaps_bucket_threshold; // defined in "OverlapsJoinHashTable.h"
244 
245  std::vector<bool> registered_hint;
246 
248 
249  public:
250  static QueryHint translateQueryHint(const std::string& hint_name) {
251  const auto lowered_hint_name = boost::algorithm::to_lower_copy(hint_name);
252  auto it = SupportedQueryHints.find(lowered_hint_name);
253  return it == SupportedQueryHints.end() ? QueryHint::kInvalidHint : it->second;
254  }
255 
256  bool isAnyQueryHintDelivered() const {
257  const auto identity = [](const bool b) { return b; };
258  return std::any_of(registered_hint.begin(), registered_hint.end(), identity);
259  }
260 
261  void registerHint(const QueryHint hint) {
262  const auto hint_class = static_cast<int>(hint);
263  registered_hint.at(hint_class) = true;
264  }
265 
266  bool isHintRegistered(const QueryHint hint) const {
267  const auto hint_class = static_cast<int>(hint);
268  return registered_hint.at(hint_class);
269  }
270 };
271 
272 // a map from hint_name to its detailed info
273 using Hints = std::unordered_map<QueryHint, ExplainedQueryHint>;
274 
275 #endif // OMNISCI_QUERYHINT_H
std::unordered_map< std::string, std::string > kv_options_
Definition: QueryHint.h:143
#define CHECK_EQ(x, y)
Definition: Logger.h:230
bool isGlobalHint() const
Definition: QueryHint.h:125
const std::vector< int > & getInteritPath()
Definition: QueryHint.h:117
bool overlaps_allow_gpu_build
Definition: QueryHint.h:241
void setListOptions(std::vector< std::string > &list_options)
Definition: QueryHint.h:103
double overlaps_keys_per_bin
Definition: QueryHint.h:243
ExplainedQueryHint(QueryHint hint, bool global_hint, bool is_marker, bool has_kv_type_options)
Definition: QueryHint.h:72
std::vector< bool > registered_hint
Definition: QueryHint.h:245
void setKVOptions(std::unordered_map< std::string, std::string > &kv_options)
Definition: QueryHint.h:107
ExplainedQueryHint(QueryHint hint, bool global_hint, bool is_marker, bool has_kv_type_options, std::vector< std::string > &list_options)
Definition: QueryHint.h:81
bool hasKvOptions() const
Definition: QueryHint.h:129
bool keep_table_function_result
Definition: QueryHint.h:233
static const std::unordered_map< std::string, QueryHint > SupportedQueryHints
Definition: QueryHint.h:46
static QueryHint translateQueryHint(const std::string &hint_name)
Definition: QueryHint.h:250
std::vector< std::string > list_options_
Definition: QueryHint.h:142
void registerHint(const QueryHint hint)
Definition: QueryHint.h:261
bool hasOptions() const
Definition: QueryHint.h:127
HintIdentifier(bool global_hint, const std::string &hint_name)
Definition: QueryHint.h:63
const std::vector< std::string > & getListOptions()
Definition: QueryHint.h:115
double g_overlaps_target_entries_per_bin
Definition: Execute.cpp:106
size_t g_overlaps_max_table_size_bytes
Definition: Execute.cpp:105
static RegisteredQueryHint defaults()
Definition: QueryHint.h:247
size_t overlaps_max_size
Definition: QueryHint.h:240
bool isHintRegistered(const QueryHint hint) const
Definition: QueryHint.h:266
std::unordered_map< QueryHint, ExplainedQueryHint > Hints
Definition: QueryHint.h:273
QueryHint
Definition: QueryHint.h:29
const std::unordered_map< std::string, std::string > & getKVOptions()
Definition: QueryHint.h:119
RegisteredQueryHint operator||(const RegisteredQueryHint &global_hints) const
Definition: QueryHint.h:164
bool g_enable_watchdog false
Definition: Execute.cpp:79
bool global_hint
Definition: QueryHint.h:60
std::vector< int > inherit_paths_
Definition: QueryHint.h:141
bool has_kv_type_options_
Definition: QueryHint.h:140
double overlaps_bucket_threshold
Definition: QueryHint.h:239
QueryHint hint_
Definition: QueryHint.h:132
size_t aggregate_tree_fanout
Definition: QueryHint.h:236
const QueryHint getHint() const
Definition: QueryHint.h:123
std::string hint_name
Definition: QueryHint.h:61
void setInheritPaths(std::vector< int > &interit_paths)
Definition: QueryHint.h:111
ExplainedQueryHint(QueryHint hint, bool global_hint, bool is_marker, bool has_kv_type_options, std::unordered_map< std::string, std::string > &kv_options)
Definition: QueryHint.h:92
bool isAnyQueryHintDelivered() const
Definition: QueryHint.h:256