161 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			161 lines
		
	
	
		
			5.3 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.
 | 
						|
 */
 | 
						|
 | 
						|
#define USING_LOG_PREFIX SERVER
 | 
						|
#include "observer/mysql/ob_mysql_result_set.h"
 | 
						|
 | 
						|
#include "observer/mysql/obsm_utils.h"
 | 
						|
#include "lib/container/ob_array.h"
 | 
						|
#include "rpc/obmysql/ob_mysql_field.h"
 | 
						|
#include "observer/ob_server.h"
 | 
						|
#include "share/ob_lob_access_utils.h"
 | 
						|
 | 
						|
using namespace oceanbase::common;
 | 
						|
using namespace oceanbase::observer;
 | 
						|
using namespace oceanbase::obmysql;
 | 
						|
 | 
						|
int ObMySQLResultSet::to_mysql_field(const ObField &field, ObMySQLField &mfield)
 | 
						|
{
 | 
						|
  int ret = OB_SUCCESS;
 | 
						|
  mfield.dname_ = field.dname_;
 | 
						|
  mfield.tname_ = field.tname_;
 | 
						|
  mfield.org_tname_ = field.org_tname_;
 | 
						|
  mfield.cname_ = field.cname_;
 | 
						|
  mfield.org_cname_ = field.org_cname_;
 | 
						|
 | 
						|
  if (OB_SUCC(ret)) {
 | 
						|
    mfield.accuracy_ = field.accuracy_;
 | 
						|
    // mfield.type_ = oceanbase::obmysql::MYSQL_TYPE_LONG;
 | 
						|
    // mfield.default_value_ = field.default_value_;
 | 
						|
 | 
						|
    // To distinguish between binary and nonbinary data for string data types,
 | 
						|
    // check whether the charsetnr value is 63. Also, flag must be set to binary accordingly
 | 
						|
    mfield.charsetnr_ = field.charsetnr_;
 | 
						|
    mfield.flags_ = field.flags_;
 | 
						|
    mfield.length_ = field.length_;
 | 
						|
 | 
						|
    // 对于Varchar类,检查charset:
 | 
						|
    mfield.flags_ &= (~BINARY_FLAG);
 | 
						|
    bool is_oracle_lob = false;
 | 
						|
    if (ObLongTextType == field.type_.get_type() && lib::is_oracle_mode()) { // was ObLobType
 | 
						|
      is_oracle_lob = true;
 | 
						|
    }
 | 
						|
    if (ob_is_string_type(field.type_.get_type())
 | 
						|
        && ObCharset::is_valid_collation(static_cast<ObCollationType>(field.charsetnr_))
 | 
						|
        && ObCharset::is_bin_sort(static_cast<ObCollationType>(field.charsetnr_))
 | 
						|
        && !is_oracle_lob) {
 | 
						|
      mfield.flags_ |= BINARY_FLAG;
 | 
						|
    }
 | 
						|
 | 
						|
    ObScale decimals = mfield.accuracy_.get_scale();
 | 
						|
    ObPrecision pre = mfield.accuracy_.get_precision();
 | 
						|
    // TIMESTAMP、UNSIGNED通过map直接映射
 | 
						|
    if (0 == field.type_name_.case_compare("SYS_REFCURSOR")) {
 | 
						|
      mfield.type_ = MYSQL_TYPE_CURSOR;
 | 
						|
    } else {
 | 
						|
      ret = ObSMUtils::get_mysql_type(field.type_.get_type(), mfield.type_, mfield.flags_, decimals);
 | 
						|
    }
 | 
						|
    if (OB_SUCC(ret) && is_oracle_lob) {
 | 
						|
      mfield.flags_ &= (~BLOB_FLAG); // was ObLobType
 | 
						|
    }
 | 
						|
 | 
						|
    mfield.type_owner_ = field.type_owner_;
 | 
						|
    mfield.type_name_ = field.type_name_;
 | 
						|
   //  In this scenario, the precsion and scale of number are undefined,
 | 
						|
   //  and the internal implementation of ob is represented by an illegal value (-1, -85).
 | 
						|
   //  However, oracle is represented by 0. In order to be compatible with
 | 
						|
   //  the behavior of oracle, it is corrected to 0 here.
 | 
						|
    if ((ObNumberType == field.type_.get_type()
 | 
						|
          || ObUNumberType == field.type_.get_type())
 | 
						|
        && lib::is_oracle_mode()) { // was decimal
 | 
						|
      decimals = (decimals==NUMBER_SCALE_UNKNOWN_YET ? 0:decimals);
 | 
						|
      pre = (pre==PRECISION_UNKNOWN_YET ? 0:pre);
 | 
						|
    }
 | 
						|
    mfield.accuracy_.set_precision(pre);
 | 
						|
    mfield.accuracy_.set_scale(decimals);
 | 
						|
    mfield.inout_mode_ = field.inout_mode_;
 | 
						|
    if (OB_SUCC(ret)
 | 
						|
        && ObExtendType == field.type_.get_type() && mfield.type_name_.empty()) {
 | 
						|
      // anonymous collection
 | 
						|
      uint16_t flags;
 | 
						|
      ObScale num_decimals;
 | 
						|
      ret = ObSMUtils::get_mysql_type(
 | 
						|
        field.default_value_.get_type(), mfield.default_value_, flags, num_decimals);
 | 
						|
    }
 | 
						|
    if (OB_SUCC(ret)
 | 
						|
        && EMySQLFieldType::MYSQL_TYPE_BIT == mfield.type_
 | 
						|
        && 1 != mfield.accuracy_.get_precision()) {
 | 
						|
      // bit(1) flags -> UNSIGNED
 | 
						|
      // bit(2) flags -> BINARY_FLAG | BLOB_FLAG | UNSIGNED
 | 
						|
      mfield.flags_ |= BINARY_FLAG;
 | 
						|
      mfield.flags_ |= BLOB_FLAG;
 | 
						|
    }
 | 
						|
    if (field.is_hidden_rowid_) {
 | 
						|
      mfield.inout_mode_ |= 0x04;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  LOG_TRACE("to mysql field", K(ret), K(mfield), K(field));
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
int ObMySQLResultSet::next_field(ObMySQLField &obmf)
 | 
						|
{
 | 
						|
  int ret = OB_SUCCESS;
 | 
						|
  int64_t field_cnt = 0;
 | 
						|
  const ColumnsFieldIArray *fields = get_field_columns();
 | 
						|
  if (OB_ISNULL(fields)) {
 | 
						|
    ret = OB_INVALID_ARGUMENT;
 | 
						|
  } else {
 | 
						|
    field_cnt = get_field_cnt();
 | 
						|
    if (field_index_ >= field_cnt) {
 | 
						|
      ret = OB_ITER_END;
 | 
						|
    } else {
 | 
						|
      const ObField &field = fields->at(field_index_++);
 | 
						|
      if (OB_FAIL(to_mysql_field(field, obmf))) {
 | 
						|
        // do nothing
 | 
						|
      } else {
 | 
						|
        replace_lob_type(get_session(), field, obmf);
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  set_errcode(ret);
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
int ObMySQLResultSet::next_param(ObMySQLField &obmf)
 | 
						|
{
 | 
						|
  int ret = OB_SUCCESS;
 | 
						|
  const ParamsFieldIArray *params = get_param_fields();
 | 
						|
  if (OB_ISNULL(params)) {
 | 
						|
    ret = OB_INVALID_ARGUMENT;
 | 
						|
  } else {
 | 
						|
    const int64_t param_cnt = params->count();
 | 
						|
    if (param_index_ >= param_cnt) {
 | 
						|
      ret = OB_ITER_END;
 | 
						|
    }
 | 
						|
    if (OB_SUCC(ret)) {
 | 
						|
      ObField field;
 | 
						|
      ret = params->at(param_index_++, field);
 | 
						|
      if (OB_SUCC(ret)) {
 | 
						|
        if (OB_FAIL(to_mysql_field(field, obmf))) {
 | 
						|
          // do nothing
 | 
						|
        } else {
 | 
						|
          replace_lob_type(get_session(), field, obmf);
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  set_errcode(ret);
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 |