MCPcopy Create free account
hub / github.com/apache/impala / Replace

Method Replace

be/src/exprs/string-functions-ir.cc:503–628  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

501}
502
503StringVal StringFunctions::Replace(FunctionContext* context, const StringVal& str,
504 const StringVal& pattern, const StringVal& replace) {
505 DCHECK_LE(str.len, StringVal::MAX_LENGTH);
506 DCHECK_LE(pattern.len, StringVal::MAX_LENGTH);
507 DCHECK_LE(replace.len, StringVal::MAX_LENGTH);
508 if (str.is_null || pattern.is_null || replace.is_null) return StringVal::null();
509 if (pattern.len == 0 || pattern.len > str.len) return str;
510
511 // StringSearch keeps a pointer to the StringValue object, so it must remain
512 // in scope if used.
513 StringSearch search;
514 StringValue needle;
515 const StringSearch *search_ptr;
516 const ReplaceContext* rptr = reinterpret_cast<ReplaceContext*>
517 (context->GetFunctionState(FunctionContext::FRAGMENT_LOCAL));
518 if (UNLIKELY(rptr == nullptr)) {
519 needle = StringValue::FromStringVal(pattern);
520 search = StringSearch(&needle);
521 search_ptr = &search;
522 } else {
523 search_ptr = &rptr->search;
524 }
525
526 const StringValue haystack = StringValue::FromStringVal(str);
527 int64_t match_pos = search_ptr->Search(&haystack);
528
529 // No match? Skip everything.
530 if (match_pos < 0) return str;
531
532 StringValue::SimpleString haystack_s = haystack.ToSimpleString();
533
534 DCHECK_GT(pattern.len, 0);
535 DCHECK_GE(haystack_s.len, pattern.len);
536 int buffer_space;
537 const int delta = replace.len - pattern.len;
538 // MAX_LENGTH is unsigned, so convert back to int to do correctly signed compare
539 DCHECK_LE(delta, static_cast<int>(StringVal::MAX_LENGTH) - 1);
540 if ((delta > 0 && delta < 128) && haystack_s.len <= 128) {
541 // Quick estimate for potential matches - this heuristic is needed to win
542 // over regexp_replace on expanding patterns. 128 is arbitrarily chosen so
543 // we can't massively over-estimate the buffer size.
544 int matches_possible = 0;
545 char c = pattern.ptr[0];
546 for (int i = 0; i <= haystack_s.len - pattern.len; ++i) {
547 if (haystack_s.ptr[i] == c) ++matches_possible;
548 }
549 buffer_space = haystack_s.len + matches_possible * delta;
550 } else {
551 // Note - cannot overflow because pattern.len is at least one
552 static_assert(StringVal::MAX_LENGTH - 1 + StringVal::MAX_LENGTH <=
553 std::numeric_limits<decltype(buffer_space)>::max(),
554 "Buffer space computation can overflow");
555 buffer_space = haystack_s.len + delta;
556 }
557
558 StringVal result(context, buffer_space);
559 // result may be NULL if we went over MAX_LENGTH or the allocation failed.
560 if (UNLIKELY(result.is_null)) return result;

Callers

nothing calls this directly

Calls 10

StringSearchClass · 0.85
maxFunction · 0.85
SubstituteFunction · 0.85
GetFunctionStateMethod · 0.80
has_errorMethod · 0.80
SearchMethod · 0.45
ToSimpleStringMethod · 0.45
SubstringMethod · 0.45
SetErrorMethod · 0.45
ResizeMethod · 0.45

Tested by

no test coverage detected