OmniSciDB  72c90bc290
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
StringOps.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 #pragma once
18 
19 #include "Logger/Logger.h"
21 #include "Shared/sqldefs.h"
22 #include "Shared/sqltypes.h"
23 #include "StringOpInfo.h"
24 
25 #include <algorithm>
26 #include <bitset>
27 #include <cctype>
28 #include <cmath>
29 #include <map>
30 #include <memory>
31 #include <optional>
32 #include <string>
33 #include <string_view>
34 #include <utility>
35 #include <vector>
36 
37 namespace StringOps_Namespace {
38 
39 struct NullableStrType {
40  NullableStrType(const std::string& str) : str(str), is_null(str.empty()) {}
41  NullableStrType(const std::string_view sv) : str(sv), is_null(sv.empty()) {}
42  NullableStrType() : is_null(true) {}
43 
44  std::pair<std::string, bool> toPair() const { return {str, is_null}; }
45 
46  std::string str;
47  bool is_null;
48 };
49 
50 struct StringOp {
51  public:
52  StringOp(const SqlStringOpKind op_kind,
53  const std::optional<std::string>& var_str_optional_literal)
54  : op_kind_(op_kind)
55  , return_ti_(SQLTypeInfo(kTEXT))
56  , has_var_str_literal_(var_str_optional_literal.has_value())
57  , var_str_literal_(!var_str_optional_literal.has_value()
58  ? NullableStrType()
59  : NullableStrType(var_str_optional_literal.value())) {}
60 
61  StringOp(const SqlStringOpKind op_kind,
62  const SQLTypeInfo& return_ti,
63  const std::optional<std::string>& var_str_optional_literal)
64  : op_kind_(op_kind)
65  , return_ti_(return_ti)
66  , has_var_str_literal_(var_str_optional_literal.has_value())
67  , var_str_literal_(!var_str_optional_literal.has_value()
68  ? NullableStrType()
69  : NullableStrType(var_str_optional_literal.value())) {}
70 
71  virtual ~StringOp() = default;
72 
73  virtual NullableStrType operator()(std::string const&) const = 0;
74 
75  virtual NullableStrType operator()(const std::string& str1,
76  const std::string& str2) const {
77  UNREACHABLE() << "operator(str1, str2) not allowed for this method";
78  // Make compiler happy
79  return NullableStrType();
80  }
81 
82  virtual NullableStrType operator()() const {
83  CHECK(hasVarStringLiteral());
84  if (var_str_literal_.is_null) {
85  return var_str_literal_;
86  }
87  return operator()(var_str_literal_.str);
88  }
89 
90  virtual Datum numericEval(const std::string_view str) const {
91  UNREACHABLE() << "numericEval not allowed for this method";
92  // Make compiler happy
93  return NullDatum(SQLTypeInfo());
94  }
95 
96  virtual Datum numericEval(const std::string_view str1,
97  const std::string_view str2) const {
98  UNREACHABLE() << "numericEval not allowed for this method";
99  // Make compiler happy
100  return NullDatum(SQLTypeInfo());
101  }
102 
103  virtual Datum numericEval() const {
104  CHECK(hasVarStringLiteral());
105  if (var_str_literal_.is_null) {
106  return NullDatum(return_ti_);
107  }
108  return numericEval(var_str_literal_.str);
109  }
110 
111  virtual const SQLTypeInfo& getReturnType() const { return return_ti_; }
112 
113  const std::string& getVarStringLiteral() const {
114  CHECK(hasVarStringLiteral());
115  return var_str_literal_.str;
116  }
117 
118  bool hasVarStringLiteral() const { return has_var_str_literal_; }
119 
120  protected:
121  static boost::regex generateRegex(const std::string& op_name,
122  const std::string& regex_pattern,
123  const std::string& regex_params,
124  const bool supports_sub_matches);
125 
126  const SqlStringOpKind op_kind_;
127  const SQLTypeInfo return_ti_;
128  const bool has_var_str_literal_{false};
129  const NullableStrType var_str_literal_;
130 };
131 
132 struct TryStringCast : public StringOp {
133  public:
134  TryStringCast(const SQLTypeInfo& return_ti,
135  const std::optional<std::string>& var_str_optional_literal)
136  : StringOp(SqlStringOpKind::TRY_STRING_CAST, return_ti, var_str_optional_literal) {}
137 
138  NullableStrType operator()(const std::string& str) const override;
139  Datum numericEval(const std::string_view str) const override;
140 };
141 
142 struct Position : public StringOp {
143  public:
144  Position(const std::optional<std::string>& var_str_optional_literal,
145  const std::string& search_str)
146  : StringOp(SqlStringOpKind::POSITION,
148  var_str_optional_literal)
149  , search_str_(search_str)
150  , start_(0) {}
151 
152  Position(const std::optional<std::string>& var_str_optional_literal,
153  const std::string& search_str,
154  const int64_t start)
155  : StringOp(SqlStringOpKind::POSITION,
157  var_str_optional_literal)
158  , search_str_(search_str)
159  , start_(start > 0 ? start - 1 : start) {}
160 
161  NullableStrType operator()(const std::string& str) const override;
162  Datum numericEval(const std::string_view str) const override;
163 
164  private:
165  const std::string search_str_;
166  const int64_t start_;
167 };
168 
169 struct JarowinklerSimilarity : public StringOp {
170  JarowinklerSimilarity(const std::optional<std::string>& var_str_optional_literal,
171  const std::string& str_literal)
174  var_str_optional_literal)
175  , str_literal_(str_literal) {}
176 
177  JarowinklerSimilarity(const std::optional<std::string>& var_str_optional_literal)
178  : StringOp(SqlStringOpKind::JAROWINKLER_SIMILARITY, var_str_optional_literal) {}
179 
180  NullableStrType operator()(const std::string& str) const override;
181 
182  Datum numericEval(const std::string_view str) const override;
183  Datum numericEval(const std::string_view str1,
184  const std::string_view str2) const override;
185 
186  const std::string str_literal_;
187 };
188 
189 struct LevenshteinDistance : public StringOp {
190  LevenshteinDistance(const std::optional<std::string>& var_str_optional_literal,
191  const std::string& str_literal)
194  var_str_optional_literal)
195  , str_literal_(str_literal) {}
196 
197  LevenshteinDistance(const std::optional<std::string>& var_str_optional_literal)
198  : StringOp(SqlStringOpKind::LEVENSHTEIN_DISTANCE, var_str_optional_literal) {}
199 
200  NullableStrType operator()(const std::string& str) const override;
201 
202  Datum numericEval(const std::string_view str) const override;
203  Datum numericEval(const std::string_view str1,
204  const std::string_view str2) const override;
205 
206  const std::string str_literal_;
207 };
208 
209 struct Lower : public StringOp {
210  Lower(const std::optional<std::string>& var_str_optional_literal)
211  : StringOp(SqlStringOpKind::LOWER, var_str_optional_literal) {}
212 
213  NullableStrType operator()(const std::string& str) const override;
214 };
215 
216 struct Upper : public StringOp {
217  Upper(const std::optional<std::string>& var_str_optional_literal)
218  : StringOp(SqlStringOpKind::UPPER, var_str_optional_literal) {}
219  NullableStrType operator()(const std::string& str) const override;
220 };
221 
222 inline std::bitset<256> build_char_bitmap(const std::string& chars_to_set) {
223  std::bitset<256> char_bitmap;
224  for (const auto& str_char : chars_to_set) {
225  char_bitmap.set(str_char);
226  }
227  return char_bitmap;
228 }
229 
230 struct InitCap : public StringOp {
231  InitCap(const std::optional<std::string>& var_str_optional_literal)
232  : StringOp(SqlStringOpKind::INITCAP, var_str_optional_literal)
233  , delimiter_bitmap_(build_char_bitmap(InitCap::delimiter_chars)) {}
234 
235  NullableStrType operator()(const std::string& str) const override;
236 
237  private:
238  static constexpr char const* delimiter_chars = R"(!?@"^#$&~_,.:;+-*%/|\[](){}<>)";
239  const std::bitset<256> delimiter_bitmap_;
240 };
241 
242 struct Reverse : public StringOp {
243  Reverse(const std::optional<std::string>& var_str_optional_literal)
244  : StringOp(SqlStringOpKind::REVERSE, var_str_optional_literal) {}
245 
246  NullableStrType operator()(const std::string& str) const override;
247 };
248 
249 struct Repeat : public StringOp {
250  public:
251  Repeat(const std::optional<std::string>& var_str_optional_literal, const int64_t n)
252  : StringOp(SqlStringOpKind::REPEAT, var_str_optional_literal)
253  , n_(n >= 0 ? n : 0UL) {
254  if (n < 0) {
255  throw std::runtime_error("Number of repeats must be >= 0");
256  }
257  }
258 
259  NullableStrType operator()(const std::string& str) const override;
260 
261  private:
262  const size_t n_;
263 };
264 
265 struct Concat : public StringOp {
266  Concat(const std::optional<std::string>& var_str_optional_literal,
267  const std::string& str_literal,
268  const bool reverse_order)
269  : StringOp(reverse_order ? SqlStringOpKind::RCONCAT : SqlStringOpKind::CONCAT,
270  var_str_optional_literal)
271  , str_literal_(str_literal)
272  , reverse_order_(reverse_order) {}
273 
274  Concat(const std::optional<std::string>& var_str_optional_literal)
275  : StringOp(SqlStringOpKind::CONCAT, var_str_optional_literal)
276  , reverse_order_(false) {}
277 
278  NullableStrType operator()(const std::string& str) const override;
279 
280  NullableStrType operator()(const std::string& str1,
281  const std::string& str2) const override;
282 
283  const std::string str_literal_;
284  const bool reverse_order_;
285 };
286 
287 struct Pad : public StringOp {
288  public:
289  enum class PadMode { LEFT, RIGHT };
290 
291  Pad(const std::optional<std::string>& var_str_optional_literal,
292  const SqlStringOpKind op_kind,
293  const int64_t padded_length,
294  const std::string& padding_string)
295  : StringOp(op_kind, var_str_optional_literal)
296  , pad_mode_(Pad::op_kind_to_pad_mode(op_kind))
297  , padded_length_(static_cast<size_t>(padded_length))
298  , padding_string_(padding_string.empty() ? " " : padding_string)
299  , padding_string_length_(padding_string.size())
300  , padding_char_(padding_string.empty() ? ' ' : padding_string[0]) {}
301 
302  NullableStrType operator()(const std::string& str) const override;
303 
304  private:
305  std::string lpad(const std::string& str) const;
306 
307  std::string rpad(const std::string& str) const;
308 
309  static PadMode op_kind_to_pad_mode(const SqlStringOpKind op_kind);
310 
311  const PadMode pad_mode_;
312  const size_t padded_length_;
313  const std::string padding_string_;
314  const size_t padding_string_length_;
315  const char padding_char_;
316 };
317 
318 struct Trim : public StringOp {
319  public:
320  enum class TrimMode { LEFT, RIGHT, BOTH };
321 
322  Trim(const std::optional<std::string>& var_str_optional_literal,
323  const SqlStringOpKind op_kind,
324  const std::string& trim_chars)
325  : StringOp(op_kind, var_str_optional_literal)
326  , trim_mode_(Trim::op_kind_to_trim_mode(op_kind))
327  , trim_char_bitmap_(build_char_bitmap(trim_chars.empty() ? " " : trim_chars)) {}
328 
329  NullableStrType operator()(const std::string& str) const override;
330 
331  private:
332  static TrimMode op_kind_to_trim_mode(const SqlStringOpKind op_kind);
333 
334  const TrimMode trim_mode_;
335  const std::bitset<256> trim_char_bitmap_;
336 };
337 
338 struct Substring : public StringOp {
339  // First constructor is for CALCITE SUBSTRING(str FROM start_pos),
340  // which returns the substring of str from start_pos
341  // until the end of the string
342  // Note start_pos is 1-indexed, unless input is 0
343 
344  Substring(const std::optional<std::string>& var_str_optional_literal,
345  const int64_t start)
346  : StringOp(SqlStringOpKind::SUBSTRING, var_str_optional_literal)
347  , start_(start > 0 ? start - 1 : start)
348  , length_(std::string::npos) {}
349 
350  // Second constructor is for CALCITE
351  // SUBSTRING(str FROM start_pos FOR length),
352  // which copies from start_pos for length characters
353  // Note start_pos is 1-indexed, unless input is 0
354  Substring(const std::optional<std::string>& var_str_optional_literal,
355  const int64_t start,
356  const int64_t length)
357  : StringOp(SqlStringOpKind::SUBSTRING, var_str_optional_literal)
358  , start_(start > 0 ? start - 1 : start)
359  , length_(static_cast<size_t>(length >= 0 ? length : 0)) {}
360 
361  NullableStrType operator()(const std::string& str) const override;
362 
363  // Make string_view version?
364  const int64_t start_;
365  const size_t length_;
366 };
367 
368 struct Overlay : public StringOp {
369  Overlay(const std::optional<std::string>& var_str_optional_literal,
370  const std::string& insert_str,
371  const int64_t start)
372  : StringOp(SqlStringOpKind::OVERLAY, var_str_optional_literal)
373  , insert_str_(insert_str)
374  , start_(start > 0 ? start - 1 : start)
375  , replacement_length_(insert_str_.size()) {}
376 
377  Overlay(const std::optional<std::string>& var_str_optional_literal,
378  const std::string& insert_str,
379  const int64_t start,
380  const int64_t replacement_length)
381  : StringOp(SqlStringOpKind::OVERLAY, var_str_optional_literal)
382  , insert_str_(insert_str)
383  , start_(start > 0 ? start - 1 : start)
384  , replacement_length_(
385  static_cast<size_t>(replacement_length >= 0 ? replacement_length : 0)) {}
386 
387  NullableStrType operator()(const std::string& base_str) const override;
388 
389  // Make string_view version?
390  const std::string insert_str_;
391  const int64_t start_;
392  const size_t replacement_length_;
393 };
394 
395 struct Replace : public StringOp {
396  Replace(const std::optional<std::string>& var_str_optional_literal,
397  const std::string& pattern_str,
398  const std::string& replacement_str)
399  : StringOp(SqlStringOpKind::REPLACE, var_str_optional_literal)
400  , pattern_str_(pattern_str)
401  , replacement_str_(replacement_str)
402  , pattern_str_len_(pattern_str.size())
403  , replacement_str_len_(replacement_str.size()) {}
404 
405  NullableStrType operator()(const std::string& str) const override;
406 
407  const std::string pattern_str_;
408  const std::string replacement_str_;
409  const size_t pattern_str_len_;
410  const size_t replacement_str_len_;
411 };
412 
413 struct SplitPart : public StringOp {
414  SplitPart(const std::optional<std::string>& var_str_optional_literal,
415  const std::string& delimiter,
416  const int64_t split_part)
417  : StringOp(SqlStringOpKind::SPLIT_PART, var_str_optional_literal)
418  , delimiter_(delimiter)
419  , split_part_(split_part == 0 ? 1UL : std::abs(split_part))
420  , delimiter_length_(delimiter.size())
421  , reverse_(split_part < 0) {}
422 
423  NullableStrType operator()(const std::string& str) const override;
424 
425  // Make string_view version?
426 
427  const std::string delimiter_;
428  const size_t split_part_;
429  const size_t delimiter_length_;
430  const bool reverse_;
431 };
432 
433 struct RegexpSubstr : public StringOp {
434  public:
435  RegexpSubstr(const std::optional<std::string>& var_str_optional_literal,
436  const std::string& regex_pattern,
437  const int64_t start_pos,
438  const int64_t occurrence,
439  const std::string& regex_params,
440  const int64_t sub_match_group_idx)
441  : StringOp(SqlStringOpKind::REGEXP_SUBSTR, var_str_optional_literal)
442  , regex_pattern_str_(
443  regex_pattern) // for toString() as std::regex does not have str() method
444  , regex_pattern_(
445  StringOp::generateRegex("REGEXP_SUBSTR", regex_pattern, regex_params, true))
446  , start_pos_(start_pos > 0 ? start_pos - 1 : start_pos)
447  , occurrence_(occurrence > 0 ? occurrence - 1 : occurrence)
448  , sub_match_info_(set_sub_match_info(regex_params, sub_match_group_idx)) {}
449 
450  NullableStrType operator()(const std::string& str) const override;
451 
452  private:
453  static std::string get_sub_match(const boost::smatch& match,
454  const std::pair<bool, int64_t> sub_match_info);
455 
456  static std::pair<bool, int64_t> set_sub_match_info(const std::string& regex_pattern,
457  const int64_t sub_match_group_idx);
458 
459  const std::string regex_pattern_str_;
460  const boost::regex regex_pattern_;
461  const int64_t start_pos_;
462  const int64_t occurrence_;
463  const std::pair<bool, int64_t> sub_match_info_;
464 };
465 
466 struct RegexpReplace : public StringOp {
467  public:
468  RegexpReplace(const std::optional<std::string>& var_str_optional_literal,
469  const std::string& regex_pattern,
470  const std::string& replacement,
471  const int64_t start_pos,
472  const int64_t occurrence,
473  const std::string& regex_params)
474  : StringOp(SqlStringOpKind::REGEXP_REPLACE, var_str_optional_literal)
475  , regex_pattern_str_(
476  regex_pattern) // for toString() as std::regex does not have str() method
477  , regex_pattern_(
478  StringOp::generateRegex("REGEXP_REPLACE", regex_pattern, regex_params, false))
479  , replacement_(replacement)
480  , start_pos_(start_pos > 0 ? start_pos - 1 : start_pos)
481  , occurrence_(occurrence) {}
482 
483  NullableStrType operator()(const std::string& str) const override;
484 
485  private:
486  static std::pair<size_t, size_t> get_nth_regex_match(const std::string& str,
487  const size_t start_pos,
488  const boost::regex& regex_pattern,
489  const int64_t occurrence);
490 
491  const std::string regex_pattern_str_;
492  const boost::regex regex_pattern_;
493  const std::string replacement_;
494  const int64_t start_pos_;
495  const int64_t occurrence_;
496 };
497 
498 // We currently do not allow strict mode JSON parsing per the SQL standard, as
499 // 1) We can't throw run-time errors in the case that the string operator
500 // is evaluated in an actual kernel, which is the case for none-encoded text
501 // inputs, and would need to capture the parsing and key errors and set
502 // kernel error flags accordingly. Currently throwing an error in even a CPU
503 // kernel will crash the server as it's not caught (by design, as executor kernels
504 // use error codes so that GPU and CPU code can throw errors).
505 // 2) When JSON_VALUE (or other not-yet-implemented JSON operators) is run over
506 // a string dictionary, if the column shares a dictionary such that the dictionary
507 // contains entries not in the column, we can throw errors for fields not in the
508 // actual column, as we compute JSON_VALUE for all values in the dictionary
509 // pre-kernel launch to build the string dictionary translation map. Since the
510 // offending values may not actually be in the column (when it references a
511 // shared dict), there is not even a way for the user to filter out or
512 // case-guard the offending values
513 // Todo(todd): Implement proper error infra for StringOps, both for the
514 // none-encoded and dictionary encoded paths
515 
516 struct JsonValue : public StringOp {
517  public:
518  JsonValue(const std::optional<std::string>& var_str_optional_literal,
519  const std::string& json_path)
520  : StringOp(SqlStringOpKind::JSON_VALUE, var_str_optional_literal)
521  , json_parse_mode_(parse_json_parse_mode(json_path))
522  , json_keys_(parse_json_path(json_path)) {}
523 
524  NullableStrType operator()(const std::string& str) const override;
525 
526  private:
527  enum class JsonKeyKind { JSON_OBJECT, JSON_ARRAY };
528  enum class JsonParseMode { PARSE_MODE_LAX, PARSE_MODE_STRICT };
529 
530  struct JsonKey {
531  JsonKeyKind key_kind;
532  std::string object_key;
533  // Todo (todd): Support array ranges ala SQL Server
534  size_t array_key;
535 
536  JsonKey(const std::string& object_key)
537  : key_kind(JsonKeyKind::JSON_OBJECT), object_key(object_key) {}
538  JsonKey(const size_t array_key)
539  : key_kind(JsonKeyKind::JSON_ARRAY), array_key(array_key) {}
540  };
541 
542  static JsonParseMode parse_json_parse_mode(std::string_view json_path);
543  static std::vector<JsonKey> parse_json_path(const std::string& json_path);
544  inline NullableStrType handle_parse_error(const std::string& json_str) const {
545  if (json_parse_mode_ == JsonParseMode::PARSE_MODE_LAX) {
546  return NullableStrType();
547  } else {
548  throw std::runtime_error("Could not parse: " + json_str + ".");
549  }
550  }
551 
552  inline NullableStrType handle_key_error(const std::string& json_str) const {
553  if (json_parse_mode_ == JsonParseMode::PARSE_MODE_LAX) {
554  return NullableStrType();
555  } else {
556  throw std::runtime_error("Key not found or did not contain value in: " + json_str +
557  ".");
558  }
559  }
560  static constexpr bool allow_strict_json_parsing{false};
561  const JsonParseMode json_parse_mode_; // If PARSE_MODE_LAX return null and don't throw
562  // error on parsing error
563  const std::vector<JsonKey> json_keys_;
564 };
565 
566 struct Base64Encode : public StringOp {
567  Base64Encode(const std::optional<std::string>& var_str_optional_literal)
568  : StringOp(SqlStringOpKind::BASE64_ENCODE, var_str_optional_literal) {}
569 
570  NullableStrType operator()(const std::string& str) const override;
571 };
572 
573 struct Base64Decode : public StringOp {
574  Base64Decode(const std::optional<std::string>& var_str_optional_literal)
575  : StringOp(SqlStringOpKind::BASE64_DECODE, var_str_optional_literal) {}
576 
577  NullableStrType operator()(const std::string& str) const override;
578 };
579 
580 struct NullOp : public StringOp {
581  NullOp(const std::optional<std::string>& var_str_optional_literal,
582  const SqlStringOpKind op_kind)
583  : StringOp(SqlStringOpKind::INVALID, var_str_optional_literal), op_kind_(op_kind) {}
584 
585  NullableStrType operator()(const std::string& str) const override {
586  return NullableStrType(); // null string
587  }
588 
589  const SqlStringOpKind op_kind_;
590 };
591 
592 std::unique_ptr<const StringOp> gen_string_op(const StringOpInfo& string_op_info);
593 
594 std::pair<std::string, bool /* is null */> apply_string_op_to_literals(
595  const StringOpInfo& string_op_info);
596 
597 Datum apply_numeric_op_to_literals(const StringOpInfo& string_op_info);
598 
599 class StringOps {
600  public:
601  StringOps() : string_ops_(genStringOpsFromOpInfos({})), num_ops_(0UL) {}
602 
603  StringOps(const std::vector<StringOpInfo>& string_op_infos)
604  : string_ops_(genStringOpsFromOpInfos(string_op_infos))
605  , num_ops_(string_op_infos.size()) {}
606 
607  std::string operator()(const std::string& str) const;
608 
609  std::string multi_input_eval(const std::string_view str1,
610  const std::string_view str2) const;
611 
612  std::string_view operator()(const std::string_view sv, std::string& sv_storage) const;
613 
614  Datum numericEval(const std::string_view str) const;
615  Datum numericEval(const std::string_view str1, const std::string_view str2) const;
616 
617  size_t size() const { return num_ops_; }
618 
619  private:
620  std::vector<std::unique_ptr<const StringOp>> genStringOpsFromOpInfos(
621  const std::vector<StringOpInfo>& string_op_infos) const;
622 
623  const std::vector<std::unique_ptr<const StringOp>> string_ops_;
624  const size_t num_ops_;
625 };
626 
627 } // namespace StringOps_Namespace
Datum apply_numeric_op_to_literals(const StringOpInfo &string_op_info)
Definition: StringOps.cpp:1145
const std::string json_str(const rapidjson::Value &obj) noexcept
Definition: JsonAccessors.h:46
#define UNREACHABLE()
Definition: Logger.h:338
SqlStringOpKind
Definition: sqldefs.h:89
Constants for Builtin SQL Types supported by HEAVY.AI.
CONSTEXPR DEVICE bool is_null(const T &value)
std::pair< std::string, bool > apply_string_op_to_literals(const StringOpInfo &string_op_info)
Definition: StringOps.cpp:1134
bool g_enable_smem_group_by true
Datum NullDatum(const SQLTypeInfo &ti)
Definition: Datum.cpp:288
Definition: sqltypes.h:79
bool g_enable_watchdog false
Definition: Execute.cpp:80
#define CHECK(condition)
Definition: Logger.h:291
Common Enum definitions for SQL processing.
constexpr double n
Definition: Utm.h:38
Definition: Datum.h:69
std::unique_ptr< const StringOp > gen_string_op(const StringOpInfo &string_op_info)
Definition: StringOps.cpp:922