diff --git a/src/share/ob_lob_access_utils.cpp b/src/share/ob_lob_access_utils.cpp index 00b7e412fb..3f445964f8 100644 --- a/src/share/ob_lob_access_utils.cpp +++ b/src/share/ob_lob_access_utils.cpp @@ -560,6 +560,14 @@ int ObTextStringIter::get_next_block_inner(ObString &str) COMMON_LOG(WARN,"Lob: falied to get first block.", K(ret)); } } else { + // if put backward, we should compact buffer remain and move reserved part closed to the reading value + if (output_data.remain() > 0 && ctx_->is_backward_ && ctx_->reserved_byte_len_ > 0) { + // from :[0, output_data.length_][output_data.length_, output_data.buffer_size_][reserved_part] + // to :[0, output_data.length_][reserved_part] + MEMMOVE(output_data.ptr() + output_data.length(), + output_data.ptr() + output_data.length() + output_data.remain(), + ctx_->reserved_byte_len_); + } ctx_->content_byte_len_ = ctx_->reserved_byte_len_ + output_data.length(); // ToDo: @gehao get directly from lob mngr ? uint32 cur_out_len = static_cast(ObCharset::strlen_char(cs_type_, @@ -569,7 +577,7 @@ int ObTextStringIter::get_next_block_inner(ObString &str) ctx_->last_accessed_byte_len_ = ctx_->accessed_byte_len_; ctx_->last_accessed_len_ = ctx_->accessed_len_; ctx_->accessed_byte_len_ += output_data.length(); - ctx_->accessed_len_ += cur_out_len;\ + ctx_->accessed_len_ += cur_out_len; ctx_->iter_count_++; str.assign_ptr(ctx_->buff_, ctx_->content_byte_len_); } @@ -658,7 +666,7 @@ void ObTextStringIter::set_reserved_byte_len(uint32_t reserved_byte_len) void ObTextStringIter::reset_reserve_len() { - if (is_valid_for_config()) { + if (is_valid_for_config(TEXTSTRING_ITER_NEXT)) { ctx_->reserved_byte_len_ = 0; ctx_->reserved_len_ = 0; } diff --git a/src/share/ob_lob_access_utils.h b/src/share/ob_lob_access_utils.h index c4997879be..e8f350d2d0 100644 --- a/src/share/ob_lob_access_utils.h +++ b/src/share/ob_lob_access_utils.h @@ -198,10 +198,10 @@ private: int get_outrow_prefix_data(uint32_t prefix_char_len); int reserve_data(); int reserve_byte_data(); - OB_INLINE bool is_valid_for_config() + OB_INLINE bool is_valid_for_config(ObTextStringIterState valid_state = TEXTSTRING_ITER_INIT) { return (is_init_ && is_outrow_ && has_lob_header_ - && state_ == TEXTSTRING_ITER_INIT && OB_NOT_NULL(ctx_)); + && state_ == valid_state && OB_NOT_NULL(ctx_)); } private: ObObjType type_; diff --git a/src/sql/engine/expr/ob_expr_trim.cpp b/src/sql/engine/expr/ob_expr_trim.cpp index 89fb5b7cab..5d3154d042 100644 --- a/src/sql/engine/expr/ob_expr_trim.cpp +++ b/src/sql/engine/expr/ob_expr_trim.cpp @@ -435,12 +435,12 @@ static int text_trim2(ObTextStringIter &str_iter, int64_t result_len = output.length() + (total_byte_len - str_iter.get_accessed_byte_len()); if (OB_FAIL(output_result.init(result_len))) { LOG_WARN("init stringtext result failed", K(ret), K(result_len)); - } else { - output_result.append(output); + } else if (OB_FAIL(output_result.append(output))) { + LOG_WARN("fail to append to result", K(ret), K(output.length()), K(output_result)); } } - } else { - output_result.append(str_data); + } else if (OB_FAIL(output_result.append(str_data))) { + LOG_WARN("fail to append to result", K(ret), K(str_data.length()), K(output_result)); } } } else if (trim_type == ObExprTrim::TYPE_RTRIM) { @@ -525,12 +525,12 @@ static int text_trim(ObTextStringIter &str_iter, int64_t result_len = output.length() + (total_byte_len - str_iter.get_accessed_byte_len()); if (OB_FAIL(output_result.init(result_len))) { LOG_WARN("init stringtext result failed", K(ret), K(result_len)); - } else { - output_result.append(output); + } else if (OB_FAIL(output_result.append(output))) { + LOG_WARN("fail to append to result", K(ret), K(output.length()), K(output_result)); } } - } else { - output_result.append(str_data); + } else if (OB_FAIL(output_result.append(str_data))) { + LOG_WARN("fail to append to result", K(ret), K(str_data.length()), K(output_result)); } } } else if (trim_type == ObExprTrim::TYPE_RTRIM) { @@ -553,14 +553,22 @@ static int text_trim(ObTextStringIter &str_iter, LOG_WARN("stringtext result reserve buffer failed", K(ret)); } else if (OB_FAIL(output_result.lseek(result_len, 0))) { LOG_WARN("result lseek failed", K(ret)); + } else if (buf_size < output.length()) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("buf size is wrong with data length", K(ret), K(buf_size), K(output.length())); } else { buf_pos = buf_size - output.length(); MEMCPY(buf + buf_pos, output.ptr(), output.length()); } } } else { - buf_pos -= str_data.length(); - MEMCPY(buf + buf_pos, str_data.ptr(), str_data.length()); + if (buf_pos < str_data.length()) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("buf pos is wrong with data length", K(ret), K(buf_pos), K(str_data.length())); + } else { + buf_pos -= str_data.length(); + MEMCPY(buf + buf_pos, str_data.ptr(), str_data.length()); + } } } if (OB_SUCC(ret)) { @@ -576,23 +584,27 @@ static int text_trim(ObTextStringIter &str_iter, && found_start == false && is_finished == false && (state = str_iter.get_next_block(str_data)) == TEXTSTRING_ITER_NEXT) { - if (OB_FAIL(ObExprTrim::trim(output, trim_type, pattern, str_data))) { - LOG_WARN("do trim failed", K(ret)); - } else if (str_iter.get_accessed_byte_len() == total_byte_len) { // accessed to the end of data - is_finished = true; - if (OB_FAIL(output_result.init(output.length()))) { - LOG_WARN("init stringtext result failed", K(ret), K(output.length())); - } else { - output_result.append(output); - } + if (OB_FAIL(ObExprTrim::trim(output, ObExprTrim::TYPE_LTRIM, pattern, str_data))) { + LOG_WARN("do front ltrim failed", K(ret), K(pattern), K(str_data)); } else if (output.length() != 0) { found_start = true; str_iter.reset_reserve_len(); - start_pos = total_byte_len - str_iter.get_accessed_byte_len() + str_data.length(); + start_pos = str_iter.get_accessed_byte_len() - output.length(); // output not copied + } else if (str_iter.get_accessed_byte_len() == total_byte_len) { // search to end and all output is zero + is_finished = true; + if (OB_FAIL(output_result.init(output.length()))) { + LOG_WARN("init stringtext result failed", K(ret), K(output.length())); + } else if (OB_FAIL(output_result.append(output))) { + LOG_WARN("fail to append to result", K(ret), K(output.length()), K(output_result)); + } } } if (OB_FAIL(ret) || is_finished) { + } else if (state != TEXTSTRING_ITER_NEXT && state != TEXTSTRING_ITER_END) { + ret = (str_iter.get_inner_ret() != OB_SUCCESS) ? + str_iter.get_inner_ret() : OB_INVALID_DATA; + LOG_WARN("iter state invalid", K(ret), K(state), K(str_iter)); } else { OB_ASSERT(found_start); // find end @@ -607,9 +619,9 @@ static int text_trim(ObTextStringIter &str_iter, bool found_end = false; while (OB_SUCC(ret) && found_end == false - && (back_state = str_iter.get_next_block(str_data)) == TEXTSTRING_ITER_NEXT) { + && (back_state = str_backward_iter.get_next_block(backward_str_data)) == TEXTSTRING_ITER_NEXT) { if (OB_FAIL(ObExprTrim::trim(backward_output, ObExprTrim::TYPE_RTRIM, pattern, backward_str_data))) { - LOG_WARN("do trim failed", K(ret)); + LOG_WARN("do backward rtrim failed", K(ret), K(pattern), K(backward_str_data)); } else if (backward_output.length() != 0) { found_end = true; end_pos = total_byte_len - str_backward_iter.get_accessed_byte_len() + backward_output.length(); @@ -618,6 +630,10 @@ static int text_trim(ObTextStringIter &str_iter, // copy from start to end int result_len = end_pos - start_pos; if (OB_FAIL(ret)) { + } else if (state != TEXTSTRING_ITER_NEXT && state != TEXTSTRING_ITER_END) { + ret = (str_backward_iter.get_inner_ret() != OB_SUCCESS) ? + str_backward_iter.get_inner_ret() : OB_INVALID_DATA; + LOG_WARN("str_backward_iter state invalid", K(ret), K(state), K(str_backward_iter)); } else if (result_len < 0) { ret = OB_SIZE_OVERFLOW; LOG_WARN("init stringtext result failed", K(ret), K(start_pos), K(end_pos)); @@ -625,25 +641,23 @@ static int text_trim(ObTextStringIter &str_iter, // the same as input if it is a temp lob? } else if (OB_FAIL(output_result.init(result_len))) { LOG_WARN("init stringtext result failed", K(ret), K(output.length())); - } else if (OB_FAIL(output_result.append(output))) { - // error log } else { - result_len -= output.length(); - while (OB_SUCC(ret) && (state = str_iter.get_next_block(str_data)) == TEXTSTRING_ITER_NEXT) { + str_data = output; + do { if (str_data.length() > result_len) { if (OB_FAIL(output_result.append(str_data.ptr(), result_len))) { - // error log + LOG_WARN("fail to append to result", K(ret), K(result_len), K(output_result)); } else { result_len = 0; } } else if (OB_FAIL(output_result.append(str_data))) { - // error log + LOG_WARN("fail to append to result", K(ret), K(str_data.length()), K(output_result)); } else { result_len -= str_data.length(); } - } + } while (OB_SUCC(ret) && result_len > 0 && (state = str_iter.get_next_block(str_data)) == TEXTSTRING_ITER_NEXT); if (OB_SUCC(ret)) { - OB_ASSERT(result_len = 0); + OB_ASSERT(result_len == 0); } } } diff --git a/tools/deploy/mysql_test/test_suite/static_engine/r/mysql/expr_trim.result b/tools/deploy/mysql_test/test_suite/static_engine/r/mysql/expr_trim.result index 6edc824392..dfde895eff 100644 --- a/tools/deploy/mysql_test/test_suite/static_engine/r/mysql/expr_trim.result +++ b/tools/deploy/mysql_test/test_suite/static_engine/r/mysql/expr_trim.result @@ -194,3 +194,63 @@ select TRIM(LEADING 'a' FROM TRIM(SUBSTR(REPEAT(NULL, 4 + 1), 1, LEAST(146, 20)) | NULL | +-----------------------------------------------------------------------------+ +create table t1 (c1 longtext); +insert into t1 values(concat(repeat(' ', 256*1024), 'ad')); +insert into t1 values(concat('ad', repeat(' ', 256*1024))); +insert into t1 values(concat(repeat(' ', 256*1024), 'ad', repeat(' ', 256*1024))); +select length(c1) from t1; ++------------+ +| length(c1) | ++------------+ +| 262146 | +| 262146 | +| 524290 | ++------------+ +select length(trim(c1)), trim(c1) from t1; ++------------------+----------+ +| length(trim(c1)) | trim(c1) | ++------------------+----------+ +| 2 | ad | +| 2 | ad | +| 2 | ad | ++------------------+----------+ +drop table t1; + +create table t1 (c1 longtext); +insert into t1 values(concat(repeat('abcd', 600*1024), 'xx')); +insert into t1 values(concat('xx', repeat('abcd', 600*1024))); +insert into t1 values(concat(repeat('abcd', 600*1024), 'xx', repeat('abcd', 600*1024))); +select length(c1) from t1; ++------------+ +| length(c1) | ++------------+ +| 2457602 | +| 2457602 | +| 4915202 | ++------------+ +select length(trim(leading 'abcd' from c1)) from t1; ++--------------------------------------+ +| length(trim(leading 'abcd' from c1)) | ++--------------------------------------+ +| 2 | +| 2457602 | +| 2457602 | ++--------------------------------------+ +select length(trim(trailing 'abcd' from c1)) from t1; ++---------------------------------------+ +| length(trim(trailing 'abcd' from c1)) | ++---------------------------------------+ +| 2457602 | +| 2 | +| 2457602 | ++---------------------------------------+ +select length(trim(both 'abcd' from c1)) from t1; ++-----------------------------------+ +| length(trim(both 'abcd' from c1)) | ++-----------------------------------+ +| 2 | +| 2 | +| 2 | ++-----------------------------------+ +drop table t1; + diff --git a/tools/deploy/mysql_test/test_suite/static_engine/t/expr_trim.test b/tools/deploy/mysql_test/test_suite/static_engine/t/expr_trim.test index b1a91c8713..04e470663f 100644 --- a/tools/deploy/mysql_test/test_suite/static_engine/t/expr_trim.test +++ b/tools/deploy/mysql_test/test_suite/static_engine/t/expr_trim.test @@ -70,5 +70,23 @@ select collation(TRIM( BOTH _binary'a' FROM _gbk'abc' )) ; select TRIM(LEADING 'a' FROM TRIM(SUBSTR(REPEAT(NULL, 4 + 1), 1, LEAST(146, 20)))); +create table t1 (c1 longtext); +insert into t1 values(concat(repeat(' ', 256*1024), 'ad')); +insert into t1 values(concat('ad', repeat(' ', 256*1024))); +insert into t1 values(concat(repeat(' ', 256*1024), 'ad', repeat(' ', 256*1024))); +select length(c1) from t1; +select length(trim(c1)), trim(c1) from t1; +drop table t1; + +create table t1 (c1 longtext); +insert into t1 values(concat(repeat('abcd', 600*1024), 'xx')); +insert into t1 values(concat('xx', repeat('abcd', 600*1024))); +insert into t1 values(concat(repeat('abcd', 600*1024), 'xx', repeat('abcd', 600*1024))); +select length(c1) from t1; +select length(trim(leading 'abcd' from c1)) from t1; +select length(trim(trailing 'abcd' from c1)) from t1; +select length(trim(both 'abcd' from c1)) from t1; +drop table t1; + connection syscon; --sleep 2