Files
oceanbase/src/storage/ob_query_iterator_util.cpp
oceanbase-admin cea7de1475 init push
2021-05-31 22:56:52 +08:00

119 lines
4.7 KiB
C++

/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
#include "share/ob_worker.h"
#include "storage/ob_query_iterator_util.h"
namespace oceanbase {
using namespace common;
namespace storage {
int pad_column(const ObAccuracy accuracy, common::ObIAllocator& padding_alloc, common::ObObj& cell)
{
int ret = OB_SUCCESS;
if (cell.is_fixed_len_char_type()) {
char* buf = NULL;
ObLength length = accuracy.get_length(); // byte or char length
int32_t cell_strlen = 0; // byte or char length
int32_t pad_whitespace_length = 0; // pad whitespace length
ObString space_pattern = ObCharsetUtils::get_const_str(cell.get_collation_type(), OB_PADDING_CHAR);
if (OB_FAIL(cell.get_char_length(accuracy, cell_strlen, share::is_oracle_mode()))) {
STORAGE_LOG(WARN, "Fail to get char length, ", K(ret));
} else {
if (cell_strlen < length) {
pad_whitespace_length = length - cell_strlen;
if (ObCharset::is_cs_nonascii(cell.get_collation_type())) {
pad_whitespace_length *= space_pattern.length();
}
}
if (pad_whitespace_length > 0) {
int32_t buf_len = cell.get_val_len() + pad_whitespace_length;
if (NULL == (buf = (char*)padding_alloc.alloc(buf_len))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
STORAGE_LOG(ERROR, "no memory", K(ret));
} else {
MEMMOVE(buf, cell.get_string_ptr(), cell.get_val_len());
if (ObCharset::is_cs_nonascii(cell.get_collation_type())) {
for (int32_t len_i = cell.get_val_len(); len_i + space_pattern.length() <= buf_len;
len_i += space_pattern.length()) {
MEMCPY(buf + len_i, space_pattern.ptr(), space_pattern.length());
}
STORAGE_LOG(DEBUG, "multi-byte padding", K(pad_whitespace_length), K(cell));
} else {
MEMSET(buf + cell.get_val_len(), OB_PADDING_CHAR, pad_whitespace_length);
}
// watch out !!! in order to deep copy an ObObj instance whose type is char or varchar,
// set_collation_type() should be revoked. But here no need to set collation type
cell.set_string(cell.get_type(), ObString(buf_len, buf_len, buf));
}
}
}
}
return ret;
}
int pad_column(const common::ObAccuracy accuracy, sql::ObEvalCtx& ctx, sql::ObExpr* expr)
{
int ret = OB_SUCCESS;
sql::ObDatum* datum = NULL;
if (OB_ISNULL(expr)) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid argument", K(ret));
} else if ((datum = &expr->locate_expr_datum(ctx))->is_null()) {
// do nothing.
} else if (expr->obj_meta_.is_fixed_len_char_type()) {
ObCollationType cs_type = expr->datum_meta_.cs_type_;
ObLength length = accuracy.get_length(); // byte or char length
int32_t cur_len = 0; // byte or char length
int32_t pad_whitespace_length = 0; // pad whitespace length
ObString space_pattern = ObCharsetUtils::get_const_str(cs_type, OB_PADDING_CHAR);
if (is_oracle_byte_length(share::is_oracle_mode(), accuracy.get_length_semantics())) {
cur_len = datum->len_;
} else {
cur_len = static_cast<int32_t>(ObCharset::strlen_char(cs_type, datum->ptr_, datum->len_));
}
if (cur_len < length) {
pad_whitespace_length = length - cur_len;
if (ObCharset::is_cs_nonascii(cs_type)) {
pad_whitespace_length *= space_pattern.length();
}
}
if (pad_whitespace_length > 0) {
const char* old = datum->ptr_;
const int32_t buf_len = datum->len_ + pad_whitespace_length;
char* buf = expr->get_str_res_mem(ctx, buf_len);
if (OB_ISNULL(buf)) {
ret = OB_ALLOCATE_MEMORY_FAILED;
STORAGE_LOG(ERROR, "no memory", K(ret));
} else {
MEMMOVE(buf, old, datum->len_);
if (ObCharset::is_cs_nonascii(cs_type)) {
for (int32_t len_i = datum->len_; len_i + space_pattern.length() <= buf_len;
len_i += space_pattern.length()) {
MEMCPY(buf + len_i, space_pattern.ptr(), space_pattern.length());
}
} else {
MEMSET(buf + datum->len_, OB_PADDING_CHAR, pad_whitespace_length);
}
datum->ptr_ = buf;
datum->len_ = buf_len;
}
}
}
return ret;
}
} // namespace storage
} // namespace oceanbase