Files
oceanbase/src/observer/mysql/ob_mysql_result_set.cpp

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;
}