20 #include <rapidjson/document.h>
21 #include <boost/algorithm/string/predicate.hpp>
23 namespace StringOps_Namespace {
25 boost::regex StringOp::generateRegex(
const std::string& op_name,
26 const std::string& regex_pattern,
27 const std::string& regex_params,
28 const bool supports_sub_matches) {
29 bool is_case_sensitive =
false;
30 bool is_case_insensitive =
false;
32 for (
const auto& c : regex_params) {
35 is_case_sensitive =
true;
38 is_case_insensitive =
true;
41 if (!supports_sub_matches) {
42 throw std::runtime_error(op_name +
43 " does not support 'e' (sub-matches) option.");
50 if (supports_sub_matches) {
51 throw std::runtime_error(
"Unrecognized regex parameter for " + op_name +
52 ", expected either 'c' 'i', or 'e'.");
54 throw std::runtime_error(
"Unrecognized regex parameter for " + op_name +
55 ", expected either 'c' or 'i'.");
59 if (!is_case_sensitive && !is_case_insensitive) {
60 throw std::runtime_error(op_name +
61 " params must either specify case-sensitivity ('c') or "
62 "case-insensitivity ('i').");
64 if (is_case_sensitive && is_case_insensitive) {
65 throw std::runtime_error(op_name +
66 " params cannot specify both case-sensitivity ('c') and "
67 "case-insensitivity ('i').");
69 if (is_case_insensitive) {
70 return boost::regex(regex_pattern,
71 boost::regex_constants::extended |
72 boost::regex_constants::optimize |
73 boost::regex_constants::icase);
77 boost::regex_constants::extended | boost::regex_constants::optimize);
81 NullableStrType TryStringCast::operator()(
const std::string& str)
const {
82 UNREACHABLE() <<
"Invalid string output for TryStringCast";
83 return NullableStrType();
86 Datum TryStringCast::numericEval(
const std::string_view str)
const {
94 }
catch (std::runtime_error& e) {
99 NullableStrType Position::operator()(
const std::string& str)
const {
100 UNREACHABLE() <<
"Invalid string output for Position";
104 Datum Position::numericEval(
const std::string_view str)
const {
108 const int64_t str_len = str.size();
109 const int64_t wrapped_start = start_ >= 0 ? start_ : str_len + start_;
111 const auto search_index = str.find(search_str_, wrapped_start);
112 if (search_index == std::string::npos) {
115 return_datum.
bigintval =
static_cast<int64_t
>(search_index) + 1;
121 NullableStrType Lower::operator()(
const std::string& str)
const {
122 std::string output_str(str);
124 output_str.begin(), output_str.end(), output_str.begin(), [](
unsigned char c) {
125 return std::tolower(c);
130 NullableStrType Upper::operator()(
const std::string& str)
const {
131 std::string output_str(str);
133 output_str.begin(), output_str.end(), output_str.begin(), [](
unsigned char c) {
134 return std::toupper(c);
139 NullableStrType InitCap::operator()(
const std::string& str)
const {
140 std::string output_str(str);
141 bool last_char_whitespace =
true;
142 for (
auto& c : output_str) {
143 if (isspace(c) || delimiter_bitmap_[reinterpret_cast<const uint8_t&>(c)]) {
144 last_char_whitespace =
true;
147 if (last_char_whitespace) {
149 last_char_whitespace =
false;
157 NullableStrType Reverse::operator()(
const std::string& str)
const {
158 const std::string reversed_str = std::string(str.rbegin(), str.rend());
162 NullableStrType Repeat::operator()(
const std::string& str)
const {
163 std::string repeated_str;
164 repeated_str.reserve(str.size() * n_);
165 for (
size_t r = 0; r < n_; ++r) {
171 NullableStrType Concat::operator()(
const std::string& str)
const {
172 return reverse_order_ ? str_literal_ + str : str + str_literal_;
175 NullableStrType Concat::operator()(
const std::string& str1,
176 const std::string& str2)
const {
180 NullableStrType Pad::operator()(
const std::string& str)
const {
181 return pad_mode_ == Pad::PadMode::LEFT ? lpad(str) : rpad(str);
184 std::string Pad::lpad(
const std::string& str)
const {
185 const auto str_len = str.size();
186 const size_t chars_to_fill = str_len < padded_length_ ? padded_length_ - str_len : 0UL;
187 if (chars_to_fill == 0UL) {
188 return str.substr(0, padded_length_);
192 if (padding_string_length_ == 1UL) {
193 return std::string(chars_to_fill, padding_char_) + str;
196 std::string fitted_padding_str;
197 fitted_padding_str.reserve(chars_to_fill);
198 for (
size_t i = 0; i < chars_to_fill; ++i) {
199 fitted_padding_str.push_back(padding_string_[i % padding_string_length_]);
201 return fitted_padding_str + str;
204 std::string Pad::rpad(
const std::string& str)
const {
205 const auto str_len = str.size();
206 const size_t chars_to_fill = str_len < padded_length_ ? padded_length_ - str_len : 0UL;
207 if (chars_to_fill == 0UL) {
208 return str.substr(str_len - padded_length_, std::string::npos);
212 if (padding_string_length_ == 1UL) {
213 return str + std::string(chars_to_fill, padding_char_);
216 std::string fitted_padding_str;
217 fitted_padding_str.reserve(chars_to_fill);
218 for (
size_t i = 0; i < chars_to_fill; ++i) {
219 fitted_padding_str.push_back(padding_string_[i % padding_string_length_]);
221 return str + fitted_padding_str;
227 return PadMode::LEFT;
229 return PadMode::RIGHT;
233 return PadMode::LEFT;
237 NullableStrType Trim::operator()(
const std::string& str)
const {
238 const auto str_len = str.size();
239 size_t trim_begin = 0;
240 if (trim_mode_ == TrimMode::LEFT || trim_mode_ == TrimMode::BOTH) {
241 while (trim_begin < str_len &&
242 trim_char_bitmap_[reinterpret_cast<const uint8_t&>(str[trim_begin])]) {
246 size_t trim_end = str_len - 1;
247 if (trim_mode_ == TrimMode::RIGHT || trim_mode_ == TrimMode::BOTH) {
248 while (trim_end > trim_begin &&
249 trim_char_bitmap_[reinterpret_cast<const uint8_t&>(str[trim_end])]) {
253 if (trim_begin == 0 && trim_end == str_len - 1) {
256 return str.substr(trim_begin, trim_end + 1 - trim_begin);
259 Trim::TrimMode Trim::op_kind_to_trim_mode(
const SqlStringOpKind op_kind) {
262 return Trim::TrimMode::BOTH;
264 return Trim::TrimMode::LEFT;
266 return Trim::TrimMode::RIGHT;
270 return Trim::TrimMode::BOTH;
274 NullableStrType Substring::operator()(
const std::string& str)
const {
277 const int64_t str_len = str.size();
278 const int64_t wrapped_start = start_ >= 0 ? start_ : str_len + start_;
279 const size_t capped_start =
280 wrapped_start > str_len ? str_len : (wrapped_start < 0 ? 0 : wrapped_start);
281 return str.substr(capped_start, length_);
284 NullableStrType Overlay::operator()(
const std::string& base_str)
const {
287 const int64_t str_len = base_str.size();
288 const int64_t wrapped_start = start_ >= 0 ? start_ : str_len + start_;
289 const size_t capped_start =
290 wrapped_start > str_len ? str_len : (wrapped_start < 0 ? 0 : wrapped_start);
291 std::string replaced_str = base_str.substr(0, capped_start);
292 replaced_str += insert_str_;
293 const size_t remainder_start =
294 std::min(wrapped_start + replacement_length_,
size_t(str_len));
295 const size_t remainder_length =
static_cast<size_t>(str_len) - remainder_start;
296 replaced_str += base_str.substr(remainder_start, remainder_length);
300 NullableStrType Replace::operator()(
const std::string& str)
const {
301 std::string replaced_str(str);
303 size_t search_start_index = 0;
305 search_start_index = replaced_str.find(pattern_str_, search_start_index);
306 if (search_start_index == std::string::npos) {
309 replaced_str.replace(search_start_index, pattern_str_len_, replacement_str_);
310 search_start_index += replacement_str_len_;
315 NullableStrType SplitPart::operator()(
const std::string& str)
const {
319 if (delimiter_ ==
"") {
323 const size_t str_len = str.size();
324 size_t delimiter_pos = reverse_ ? str_len : 0UL;
325 size_t last_delimiter_pos;
326 size_t delimiter_idx = 0UL;
329 last_delimiter_pos = delimiter_pos;
330 delimiter_pos = reverse_ ? str.rfind(delimiter_, delimiter_pos - 1UL)
331 : str.find(delimiter_, delimiter_pos + delimiter_length_);
332 }
while (delimiter_pos != std::string::npos && ++delimiter_idx < split_part_);
334 if (delimiter_idx == 0UL && split_part_ == 1UL) {
340 if (delimiter_pos == std::string::npos &&
341 (delimiter_idx < split_part_ - 1UL || delimiter_idx < 1UL)) {
343 return NullableStrType();
347 const size_t substr_start =
348 delimiter_pos == std::string::npos ? 0UL : delimiter_pos + delimiter_length_;
349 return str.substr(substr_start, last_delimiter_pos - substr_start);
351 const size_t substr_start =
352 split_part_ == 1UL ? 0UL : last_delimiter_pos + delimiter_length_;
353 return str.substr(substr_start, delimiter_pos - substr_start);
357 NullableStrType RegexpReplace::operator()(
const std::string& str)
const {
358 const int64_t str_len = str.size();
359 const int64_t pos = start_pos_ < 0 ? str_len + start_pos_ : start_pos_;
360 const size_t wrapped_start = std::clamp(pos, int64_t(0), str_len);
361 if (occurrence_ == 0L) {
363 std::string::const_iterator replace_start(str.cbegin() + wrapped_start);
364 boost::regex_replace(std::back_inserter(result),
369 return str.substr(0UL, wrapped_start) +
result;
371 const auto occurrence_match_pos = RegexpReplace::get_nth_regex_match(
375 occurrence_ > 0 ? occurrence_ - 1 : occurrence_);
376 if (occurrence_match_pos.first == std::string::npos) {
381 std::string::const_iterator replace_start(str.cbegin() + occurrence_match_pos.first);
382 std::string::const_iterator replace_end(str.cbegin() + occurrence_match_pos.second);
383 std::string replaced_match;
384 boost::regex_replace(std::back_inserter(replaced_match),
389 return str.substr(0UL, occurrence_match_pos.first) + replaced_match +
390 str.substr(occurrence_match_pos.second, std::string::npos);
394 std::pair<size_t, size_t> RegexpReplace::get_nth_regex_match(
395 const std::string& str,
396 const size_t start_pos,
397 const boost::regex& regex_pattern,
398 const int64_t occurrence) {
399 std::vector<std::pair<size_t, size_t>> regex_match_positions;
400 std::string::const_iterator search_start(str.cbegin() + start_pos);
402 int64_t match_idx = 0;
403 size_t string_pos = start_pos;
404 while (boost::regex_search(search_start, str.cend(), match, regex_pattern)) {
405 string_pos += match.position(
size_t(0)) + match.length(0);
406 regex_match_positions.emplace_back(
407 std::make_pair(string_pos - match.length(0), string_pos));
408 if (match_idx++ == occurrence) {
409 return regex_match_positions.back();
412 match.suffix().first;
418 const int64_t wrapped_match = occurrence >= 0 ? occurrence : match_idx + occurrence;
419 if (wrapped_match < 0 || wrapped_match >= match_idx) {
421 return std::make_pair(std::string::npos, std::string::npos);
423 return regex_match_positions[wrapped_match];
426 NullableStrType RegexpSubstr::operator()(
const std::string& str)
const {
427 const int64_t str_len = str.size();
428 const int64_t pos = start_pos_ < 0 ? str_len + start_pos_ : start_pos_;
429 const size_t wrapped_start = std::clamp(pos, int64_t(0), str_len);
430 int64_t match_idx = 0;
432 std::vector<std::string> regex_matches;
433 std::string::const_iterator search_start(str.cbegin() + wrapped_start);
435 while (boost::regex_search(search_start, str.cend(), match, regex_pattern_)) {
436 if (match_idx++ == occurrence_) {
437 if (sub_match_info_.first) {
438 return RegexpSubstr::get_sub_match(match, sub_match_info_);
440 return NullableStrType(match[0]);
442 regex_matches.emplace_back(match[0]);
444 match.suffix().first;
446 const int64_t wrapped_match = occurrence_ >= 0 ? occurrence_ : match_idx + occurrence_;
447 if (wrapped_match < 0 || wrapped_match >= match_idx) {
448 return NullableStrType();
450 if (sub_match_info_.first) {
451 return RegexpSubstr::get_sub_match(match, sub_match_info_);
453 return regex_matches[wrapped_match];
456 std::string RegexpSubstr::get_sub_match(
const boost::smatch& match,
457 const std::pair<bool, int64_t> sub_match_info) {
458 const int64_t num_sub_matches = match.size() - 1;
459 const int64_t wrapped_sub_match = sub_match_info.second >= 0
460 ? sub_match_info.second
461 : num_sub_matches + sub_match_info.second;
462 if (wrapped_sub_match < 0 || wrapped_sub_match >= num_sub_matches) {
465 return match[wrapped_sub_match + 1];
468 std::pair<bool, int64_t> RegexpSubstr::set_sub_match_info(
469 const std::string& regex_pattern,
470 const int64_t sub_match_group_idx) {
471 if (regex_pattern.find(
"e", 0UL) == std::string::npos) {
472 return std::make_pair(
false, 0UL);
474 return std::make_pair(
475 true, sub_match_group_idx > 0L ? sub_match_group_idx - 1 : sub_match_group_idx);
479 JsonValue::JsonParseMode JsonValue::parse_json_parse_mode(std::string_view json_path) {
480 size_t const string_pos = json_path.find(
'$');
481 if (string_pos == 0) {
483 return JsonValue::JsonParseMode::PARSE_MODE_LAX;
484 }
else if (string_pos == std::string::npos) {
485 throw std::runtime_error(
"JSON search path must include a '$' literal.");
487 std::string_view
const prefix = json_path.substr(0, string_pos);
488 if (boost::iequals(prefix, std::string_view(
"lax "))) {
489 return JsonValue::JsonParseMode::PARSE_MODE_LAX;
490 }
else if (boost::iequals(prefix, std::string_view(
"strict "))) {
491 if constexpr (JsonValue::allow_strict_json_parsing) {
492 return JsonValue::JsonParseMode::PARSE_MODE_STRICT;
494 throw std::runtime_error(
"Strict parsing not currently supported for JSON_VALUE.");
497 throw std::runtime_error(
"Issue parsing JSON_VALUE Parse Mode.");
501 std::vector<JsonValue::JsonKey> JsonValue::parse_json_path(
const std::string& json_path) {
503 size_t string_pos = json_path.find(
"$");
504 if (string_pos == std::string::npos) {
505 throw std::runtime_error(
"JSON search path must begin with '$' literal.");
510 static const auto& key_regex = *
new boost::regex(
511 R
"~(^(\.(([[:alpha:]][[:alnum:]_-]*)|"([[:alpha:]][ [:alnum:]_-]*)"))|\[([[:digit:]]+)\])~",
512 boost::regex_constants::extended | boost::regex_constants::optimize);
513 static_assert(std::is_trivially_destructible_v<decltype(key_regex)>);
515 std::string::const_iterator search_start(json_path.cbegin() + string_pos);
517 std::vector<JsonKey> json_keys;
518 while (boost::regex_search(search_start, json_path.cend(), match, key_regex)) {
520 if (match.position(
size_t(0)) != 0L) {
522 throw std::runtime_error(
"JSON search path parsing error: '" + json_path +
"'");
524 size_t matching_expr = 0;
525 if (match[3].matched) {
528 }
else if (match[4].matched) {
531 }
else if (match[5].matched) {
536 string_pos += match.length(0);
538 const std::string key_match(match[matching_expr].first, match[matching_expr].second);
540 if (isalpha(key_match[0])) {
542 json_keys.emplace_back(JsonKey(key_match));
545 json_keys.emplace_back(JsonKey(std::stoi(key_match)));
548 match.suffix().first;
550 if (json_keys.empty()) {
551 throw std::runtime_error(
"No keys found in JSON search path.");
553 if (string_pos < json_path.size()) {
554 throw std::runtime_error(
"JSON path parsing error.");
559 NullableStrType JsonValue::operator()(
const std::string& str)
const {
560 rapidjson::Document document;
561 if (document.Parse(str.c_str()).HasParseError()) {
562 if constexpr (JsonValue::allow_strict_json_parsing) {
563 return handle_parse_error(str);
565 return NullableStrType();
568 rapidjson::Value& json_val = document;
569 for (
const auto& json_key : json_keys_) {
570 switch (json_key.key_kind) {
571 case JsonKeyKind::JSON_OBJECT: {
572 if (!json_val.IsObject() || !json_val.HasMember(json_key.object_key)) {
573 if constexpr (JsonValue::allow_strict_json_parsing) {
574 return handle_key_error(str);
576 return NullableStrType();
579 json_val = json_val[json_key.object_key];
582 case JsonKeyKind::JSON_ARRAY: {
583 if (!json_val.IsArray() || json_val.Size() <= json_key.array_key) {
584 if constexpr (JsonValue::allow_strict_json_parsing) {
585 return handle_key_error(str);
587 return NullableStrType();
590 json_val = json_val[json_key.array_key];
596 if (json_val.IsString()) {
597 return NullableStrType(std::string(json_val.GetString()));
598 }
else if (json_val.IsNumber()) {
599 if (json_val.IsDouble()) {
601 }
else if (json_val.IsInt64()) {
603 }
else if (json_val.IsUint64()) {
609 if constexpr (JsonValue::allow_strict_json_parsing) {
610 return handle_key_error(str);
612 return NullableStrType();
615 }
else if (json_val.IsBool()) {
616 return NullableStrType(std::string(json_val.IsTrue() ?
"true" :
"false"));
617 }
else if (json_val.IsNull()) {
618 return NullableStrType();
622 if constexpr (JsonValue::allow_strict_json_parsing) {
623 return handle_key_error(str);
625 return NullableStrType();
630 NullableStrType Base64Encode::operator()(
const std::string& str)
const {
634 NullableStrType Base64Decode::operator()(
const std::string& str)
const {
638 std::string StringOps::operator()(
const std::string& str)
const {
639 NullableStrType modified_str(str);
640 if (modified_str.is_null) {
643 for (
const auto& string_op : string_ops_) {
644 modified_str = string_op->operator()(modified_str.str);
645 if (modified_str.is_null) {
649 return modified_str.str;
652 std::string StringOps::multi_input_eval(
const std::string_view str1,
653 const std::string_view str2)
const {
654 NullableStrType modified_str1(str1);
655 NullableStrType modified_str2(str2);
656 if (modified_str1.is_null || modified_str2.is_null) {
659 for (
const auto& string_op : string_ops_) {
660 modified_str1 = string_op->operator()(modified_str1.str, modified_str2.str);
661 if (modified_str1.is_null) {
665 return modified_str1.str;
668 std::string_view StringOps::operator()(
const std::string_view sv,
669 std::string& sv_storage)
const {
671 NullableStrType nullable_str(sv);
672 for (
const auto& string_op : string_ops_) {
673 nullable_str = string_op->operator()(nullable_str.str);
674 if (nullable_str.is_null) {
678 sv_storage = nullable_str.str;
682 Datum StringOps::numericEval(
const std::string_view str)
const {
683 const auto num_string_producing_ops = string_ops_.size() - 1;
684 if (num_string_producing_ops == 0UL) {
687 return string_ops_.back()->numericEval(str);
689 NullableStrType modified_str(str);
690 for (
size_t string_op_idx = 0; string_op_idx < num_string_producing_ops;
692 const auto& string_op = string_ops_[string_op_idx];
693 modified_str = string_op->operator()(modified_str.str);
694 if (modified_str.is_null) {
698 return string_ops_.back()->numericEval(modified_str.str);
701 std::vector<std::unique_ptr<const StringOp>> StringOps::genStringOpsFromOpInfos(
702 const std::vector<StringOpInfo>& string_op_infos)
const {
705 std::vector<std::unique_ptr<const StringOp>> string_ops;
706 string_ops.reserve(string_op_infos.size());
707 for (
const auto& string_op_info : string_op_infos) {
716 std::optional<std::string> var_string_optional_literal;
717 const auto op_kind = string_op_info.
getOpKind();
721 return std::make_unique<const NullOp>(var_string_optional_literal, op_kind);
732 CHECK_EQ(num_non_variable_literals, 0UL);
733 return std::make_unique<const Lower>(var_string_optional_literal);
736 CHECK_EQ(num_non_variable_literals, 0UL);
737 return std::make_unique<const Upper>(var_string_optional_literal);
740 CHECK_EQ(num_non_variable_literals, 0UL);
741 return std::make_unique<const InitCap>(var_string_optional_literal);
744 CHECK_EQ(num_non_variable_literals, 0UL);
745 return std::make_unique<const Reverse>(var_string_optional_literal);
748 CHECK_EQ(num_non_variable_literals, 1UL);
749 const auto num_repeats_literal = string_op_info.
getIntLiteral(1);
750 return std::make_unique<const Repeat>(var_string_optional_literal,
751 num_repeats_literal);
755 CHECK_GE(num_non_variable_literals, 0UL);
756 CHECK_LE(num_non_variable_literals, 1UL);
757 if (num_non_variable_literals == 1UL) {
760 return std::make_unique<const Concat>(var_string_optional_literal,
764 return std::make_unique<const Concat>(var_string_optional_literal);
769 CHECK_EQ(num_non_variable_literals, 2UL);
770 const auto padded_length_literal = string_op_info.
getIntLiteral(1);
772 return std::make_unique<Pad>(var_string_optional_literal,
774 padded_length_literal,
775 padding_string_literal);
780 CHECK_EQ(num_non_variable_literals, 1UL);
782 return std::make_unique<Trim>(
783 var_string_optional_literal, op_kind, trim_chars_literal);
786 CHECK_GE(num_non_variable_literals, 1UL);
787 CHECK_LE(num_non_variable_literals, 2UL);
788 const auto start_pos_literal = string_op_info.
getIntLiteral(1);
790 if (has_length_literal) {
792 return std::make_unique<const Substring>(
793 var_string_optional_literal, start_pos_literal, length_literal);
795 return std::make_unique<const Substring>(var_string_optional_literal,
800 CHECK_GE(num_non_variable_literals, 2UL);
801 CHECK_LE(num_non_variable_literals, 3UL);
803 const auto start_pos_literal = string_op_info.
getIntLiteral(2);
805 if (has_length_literal) {
807 return std::make_unique<const Overlay>(var_string_optional_literal,
808 replace_string_literal,
812 return std::make_unique<const Overlay>(
813 var_string_optional_literal, replace_string_literal, start_pos_literal);
817 CHECK_GE(num_non_variable_literals, 2UL);
818 CHECK_LE(num_non_variable_literals, 2UL);
821 return std::make_unique<const Replace>(var_string_optional_literal,
822 pattern_string_literal,
823 replacement_string_literal);
826 CHECK_GE(num_non_variable_literals, 2UL);
827 CHECK_LE(num_non_variable_literals, 2UL);
829 const auto split_part_literal = string_op_info.
getIntLiteral(2);
830 return std::make_unique<const SplitPart>(
831 var_string_optional_literal, delimiter_literal, split_part_literal);
834 CHECK_GE(num_non_variable_literals, 5UL);
835 CHECK_LE(num_non_variable_literals, 5UL);
838 const auto start_pos_literal = string_op_info.
getIntLiteral(3);
839 const auto occurrence_literal = string_op_info.
getIntLiteral(4);
841 return std::make_unique<const RegexpReplace>(var_string_optional_literal,
846 regex_params_literal);
849 CHECK_GE(num_non_variable_literals, 5UL);
850 CHECK_LE(num_non_variable_literals, 5UL);
852 const auto start_pos_literal = string_op_info.
getIntLiteral(2);
853 const auto occurrence_literal = string_op_info.
getIntLiteral(3);
855 const auto sub_match_idx_literal = string_op_info.
getIntLiteral(5);
856 return std::make_unique<const RegexpSubstr>(var_string_optional_literal,
860 regex_params_literal,
861 sub_match_idx_literal);
864 CHECK_EQ(num_non_variable_literals, 1UL);
866 return std::make_unique<const JsonValue>(var_string_optional_literal,
870 CHECK_EQ(num_non_variable_literals, 0UL);
871 return std::make_unique<const Base64Encode>(var_string_optional_literal);
874 CHECK_EQ(num_non_variable_literals, 0UL);
875 return std::make_unique<const Base64Decode>(var_string_optional_literal);
878 CHECK_EQ(num_non_variable_literals, 0UL);
879 return std::make_unique<const TryStringCast>(return_ti,
880 var_string_optional_literal);
883 CHECK_GE(num_non_variable_literals, 1UL);
884 CHECK_LE(num_non_variable_literals, 2UL);
887 if (has_start_pos_literal) {
888 const auto start_pos_literal = string_op_info.
getIntLiteral(2);
889 return std::make_unique<const Position>(
890 var_string_optional_literal, search_literal, start_pos_literal);
892 return std::make_unique<const Position>(var_string_optional_literal,
898 return std::make_unique<NullOp>(var_string_optional_literal, op_kind);
902 return std::make_unique<NullOp>(var_string_optional_literal, op_kind);
909 const std::string null_str{
""};
910 return std::make_pair(null_str,
true);
913 return string_op->operator()().toPair();
919 return string_op->numericEval();
const SQLTypeInfo & getReturnType() const
Datum apply_numeric_op_to_literals(const StringOpInfo &string_op_info)
size_t numLiterals() const
bool intLiteralArgAtIdxExists(const size_t index) const
int64_t getIntLiteral(const size_t index) const
size_t numNonVariableLiterals() const
bool hasNullLiteralArg() const
bool hasVarStringLiteral() const
std::pair< std::string, bool > apply_string_op_to_literals(const StringOpInfo &string_op_info)
Datum StringToDatum(const std::string_view s, SQLTypeInfo &ti)
OUTPUT transform(INPUT const &input, FUNC const &func)
Datum NullDatum(const SQLTypeInfo &ti)
std::string getStringLiteral(const size_t index) const
std::string decode_base64(const std::string &val, bool trim_nulls)
static std::string encode_base64(const std::string &val)
const SqlStringOpKind & getOpKind() const
std::unique_ptr< const StringOp > gen_string_op(const StringOpInfo &string_op_info)