119 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			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
 |