982 lines
35 KiB
C++
982 lines
35 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 "ob_inner_sql_result.h"
|
|
|
|
#include "lib/mysqlclient/ob_mysql_result.h"
|
|
#include "lib/hash/ob_hashmap.h"
|
|
#include "lib/rc/context.h"
|
|
#include "lib/signal/ob_signal_struct.h"
|
|
#include "share/rc/ob_tenant_base.h"
|
|
#include "observer/ob_req_time_service.h"
|
|
#include "omt/ob_tenant.h"
|
|
|
|
namespace oceanbase
|
|
{
|
|
using namespace common;
|
|
using namespace common::sqlclient;
|
|
using namespace share;
|
|
using namespace share::schema;
|
|
using namespace sql;
|
|
|
|
namespace observer
|
|
{
|
|
inline int ObInnerSQLResult::check_extend_value(const common::ObObj &obj)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (obj.is_null()) {
|
|
ret = OB_ERR_NULL_VALUE;
|
|
} else if (obj.is_min_value()) {
|
|
ret = OB_ERR_MIN_VALUE;
|
|
} else if (obj.is_max_value()) {
|
|
ret = OB_ERR_MIN_VALUE;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
ObInnerSQLResult::ObInnerSQLResult(ObSQLSessionInfo &session)
|
|
: column_map_created_(false), column_indexed_(false), column_map_(),
|
|
mem_context_(nullptr),
|
|
mem_context_destroy_guard_(mem_context_),
|
|
sql_ctx_(), schema_guard_(share::schema::ObSchemaMgrItem::MOD_INNER_SQL_RESULT),
|
|
opened_(false), session_(session),
|
|
result_set_(nullptr), remote_result_set_(nullptr), row_(NULL),
|
|
execute_start_ts_(0), execute_end_ts_(0),
|
|
compat_mode_(ORACLE_MODE == session.get_compatibility_mode() ? lib::Worker::CompatMode::ORACLE : lib::Worker::CompatMode::MYSQL),
|
|
is_inited_(false),
|
|
store_first_row_(false),
|
|
iter_end_(false),
|
|
is_read_(true),
|
|
has_tenant_resource_(true),
|
|
tenant_(nullptr)
|
|
|
|
{
|
|
sql_ctx_.exec_type_ = InnerSql;
|
|
}
|
|
|
|
int ObInnerSQLResult::init(bool has_tenant_resource)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
lib::ContextParam param;
|
|
param.set_mem_attr(session_.get_effective_tenant_id(),
|
|
ObModIds::OB_RESULT_SET,
|
|
ObCtxIds::DEFAULT_CTX_ID)
|
|
.set_properties(lib::USE_TL_PAGE_OPTIONAL)
|
|
.set_page_size(OB_MALLOC_MIDDLE_BLOCK_SIZE)
|
|
.set_ablock_size(lib::INTACT_MIDDLE_AOBJECT_SIZE);
|
|
if (OB_FAIL(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context_, param))) {
|
|
LOG_WARN("create memory entity failed", K(ret));
|
|
} else if (has_tenant_resource) {
|
|
if (OB_FAIL(GCTX.omt_->get_tenant_with_tenant_lock(session_.get_effective_tenant_id(), handle_, tenant_))) {
|
|
if (OB_IN_STOP_STATE == ret) {
|
|
ret = OB_TENANT_NOT_IN_SERVER;
|
|
}
|
|
LOG_WARN("get tenant lock fail", K(ret), K(session_.get_effective_tenant_id()));
|
|
}
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
set_has_tenant_resource(has_tenant_resource);
|
|
if (!has_tenant_resource) {
|
|
remote_result_set_ = new (buf_) ObRemoteResultSet(mem_context_->get_arena_allocator());
|
|
remote_result_set_->reset_and_init_remote_resp_handler();
|
|
} else {
|
|
result_set_ = new (buf_) ObResultSet(session_, mem_context_->get_arena_allocator());
|
|
result_set_->set_is_inner_result_set(true);
|
|
}
|
|
is_inited_ = true;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObInnerSQLResult::init()
|
|
{
|
|
return init(true);
|
|
}
|
|
|
|
ObInnerSQLResult::~ObInnerSQLResult()
|
|
{
|
|
close();
|
|
if (result_set_ != nullptr) {
|
|
int ret = OB_SUCCESS;
|
|
MAKE_TENANT_SWITCH_SCOPE_GUARD(tenant_guard);
|
|
if (has_tenant_resource() && OB_FAIL(tenant_guard.switch_to(tenant_))) {
|
|
LOG_WARN("switch tenant fail", K(ret));
|
|
} else {
|
|
result_set_->~ObResultSet();
|
|
}
|
|
}
|
|
if (remote_result_set_ != nullptr) {
|
|
remote_result_set_->~ObRemoteResultSet();
|
|
}
|
|
if (tenant_ != nullptr) {
|
|
tenant_->unlock(handle_);
|
|
tenant_ = nullptr;
|
|
}
|
|
}
|
|
|
|
int ObInnerSQLResult::open()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
execute_start_ts_ = ObTimeUtility::current_time();
|
|
MAKE_TENANT_SWITCH_SCOPE_GUARD(tenant_guard);
|
|
if (has_tenant_resource()) {
|
|
result_set().get_exec_context().set_plan_start_time(execute_start_ts_);
|
|
}
|
|
if (OB_UNLIKELY(!is_inited_)) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("not init", K(ret));
|
|
} else if (has_tenant_resource() && OB_FAIL(tenant_guard.switch_to(tenant_))) {
|
|
LOG_WARN("switch tenant failed", K(ret), K(session_.get_effective_tenant_id()));
|
|
} else {
|
|
lib::CompatModeGuard g(compat_mode_);
|
|
SQL_INFO_GUARD(session_.get_current_query_string(), session_.get_cur_sql_id());
|
|
bool is_select = has_tenant_resource() ?
|
|
ObStmt::is_select_stmt(result_set_->get_stmt_type())
|
|
: ObStmt::is_select_stmt(remote_result_set_->get_stmt_type());
|
|
WITH_CONTEXT(mem_context_) {
|
|
if (opened_) {
|
|
ret = OB_INIT_TWICE;
|
|
LOG_WARN("result set already open", K(ret));
|
|
} else if (has_tenant_resource() && OB_FAIL(result_set_->open())) {
|
|
result_set_->refresh_location_cache_by_errno(true, ret);
|
|
LOG_WARN("open result set failed", K(ret));
|
|
// move after precess_retry().
|
|
// result_set_->close();
|
|
} else if (is_read_&& is_select) {
|
|
//prefetch 1 row for throwing error code and retry
|
|
opened_ = true;
|
|
if ((has_tenant_resource() && OB_FAIL(result_set_->get_next_row(row_)))
|
|
|| (!has_tenant_resource() && OB_FAIL(remote_result_set_->get_next_row(row_)))) {
|
|
if (OB_ITER_END == ret) {
|
|
iter_end_ = true;
|
|
ret = OB_SUCCESS;
|
|
} else {
|
|
LOG_WARN("get_next_row failed", K(ret), K(has_tenant_resource()));
|
|
}
|
|
} else {
|
|
store_first_row_ = true;
|
|
}
|
|
} else {
|
|
opened_ = true;
|
|
}
|
|
}
|
|
}
|
|
execute_end_ts_ = ObTimeUtility::current_time();
|
|
return ret;
|
|
}
|
|
|
|
int ObInnerSQLResult::close()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
// close can be executed too if result set not open.
|
|
if (opened_) {
|
|
// opened=true imply is_inited=true
|
|
if (OB_FAIL(inner_close())) {
|
|
LOG_WARN("result set close failed", K(ret));
|
|
}
|
|
}
|
|
column_map_.clear();
|
|
column_indexed_ = false;
|
|
return ret;
|
|
}
|
|
|
|
int ObInnerSQLResult::force_close()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_FAIL(inner_close())) {
|
|
LOG_WARN("result set close failed", K(ret));
|
|
}
|
|
column_map_.clear();
|
|
column_indexed_ = false;
|
|
return ret;
|
|
}
|
|
int ObInnerSQLResult::inner_close()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
lib::CompatModeGuard g(compat_mode_);
|
|
SQL_INFO_GUARD(session_.get_current_query_string(), session_.get_cur_sql_id());
|
|
LOG_DEBUG("compat_mode_", K(ret), K(compat_mode_), K(lbt()));
|
|
|
|
MAKE_TENANT_SWITCH_SCOPE_GUARD(tenant_guard);
|
|
if (has_tenant_resource() && OB_FAIL(tenant_guard.switch_to(tenant_))) {
|
|
LOG_WARN("switch tenant failed", K(ret), K(session_.get_effective_tenant_id()));
|
|
} else {
|
|
WITH_CONTEXT(mem_context_) {
|
|
if (has_tenant_resource() && OB_FAIL(result_set_->close())) {
|
|
result_set_->refresh_location_cache_by_errno(true, ret);
|
|
LOG_WARN("result set close failed", K(ret));
|
|
} else if(!has_tenant_resource() && OB_FAIL(remote_result_set_->close())) {
|
|
LOG_WARN("remote_result_set close failed", K(ret));
|
|
}
|
|
}
|
|
}
|
|
opened_ = false;
|
|
store_first_row_ = false;
|
|
iter_end_ = false;
|
|
return ret;
|
|
}
|
|
|
|
int ObInnerSQLResult::next()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
MAKE_TENANT_SWITCH_SCOPE_GUARD(tenant_guard);
|
|
LOG_DEBUG("compat_mode_", K(ret), K(compat_mode_), K(lbt()));
|
|
if (!opened_) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("not opened", K(ret));
|
|
} else if (iter_end_) {
|
|
ret = OB_ITER_END;
|
|
} else if (has_tenant_resource() && OB_FAIL(tenant_guard.switch_to(tenant_))) {
|
|
LOG_WARN("switch tenant failed", K(ret), K(session_.get_effective_tenant_id()));
|
|
} else if (store_first_row_) {
|
|
store_first_row_ = false;
|
|
} else {
|
|
row_ = NULL;
|
|
lib::CompatModeGuard g(compat_mode_);
|
|
SQL_INFO_GUARD(session_.get_current_query_string(), session_.get_cur_sql_id());
|
|
WITH_CONTEXT(mem_context_) {
|
|
if (has_tenant_resource() && OB_FAIL(result_set_->get_next_row(row_))) {
|
|
if (OB_ITER_END != ret) {
|
|
result_set_->refresh_location_cache_by_errno(true, ret);
|
|
LOG_WARN("get next row failed", K(ret));
|
|
}
|
|
} else if (!has_tenant_resource() && OB_FAIL(remote_result_set_->get_next_row(row_))) {
|
|
if (OB_ITER_END != ret) {
|
|
LOG_WARN("get next row failed",
|
|
K(ret), K(remote_result_set_->get_field_columns()->count()));
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObInnerSQLResult::build_column_map() const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (!opened_) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("not opened", K(ret));
|
|
} else if (!column_map_created_) {
|
|
if (OB_FAIL(column_map_.create(COLUMN_MAP_BUCKET_NUM,
|
|
ObModIds::OB_HASH_BUCKET_SQL_COLUMN_MAP, ObModIds::OB_HASH_NODE_SQL_COLUMN_MAP))) {
|
|
LOG_WARN("create hash table failed", K(ret), LITERAL_K(COLUMN_MAP_BUCKET_NUM));
|
|
} else {
|
|
column_map_created_ = true;
|
|
}
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
column_map_.clear();
|
|
const ColumnsFieldIArray *fields = has_tenant_resource()
|
|
? result_set_->get_field_columns()
|
|
: remote_result_set_->get_field_columns();
|
|
if (OB_ISNULL(fields)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("invalid argument", K(ret), K(fields));
|
|
}
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < fields->count(); ++i) {
|
|
if (nullptr == fields->at(i).cname_) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("null field name", K(ret), "field", fields->at(i));
|
|
} else {
|
|
if (OB_FAIL(column_map_.set_refactored(fields->at(i).cname_, i))) {
|
|
// ignore duplicate column name
|
|
if (OB_HASH_EXIST == ret) {
|
|
ret = OB_SUCCESS;
|
|
} else {
|
|
LOG_WARN("add column name to column map failed", K(ret));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (OB_SUCC(ret)) {
|
|
column_indexed_ = true;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObInnerSQLResult::find_idx(const char *col_name, int64_t &idx) const
|
|
{
|
|
idx = OB_INVALID_INDEX;
|
|
int ret = OB_SUCCESS;
|
|
if (!opened_) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("not opened", K(ret));
|
|
} else if (nullptr == col_name) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("invalid argument", K(ret), KP(col_name));
|
|
} else {
|
|
if (OB_UNLIKELY(!column_indexed_)) {
|
|
if (OB_FAIL(build_column_map())) {
|
|
LOG_WARN("build column map failed", K(ret));
|
|
}
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
ret = column_map_.get_refactored(ObString::make_string(col_name), idx);
|
|
if (OB_SUCCESS != ret && OB_HASH_NOT_EXIST != ret) {
|
|
LOG_WARN("get index from hash failed", K(ret), K(col_name));
|
|
} else if (OB_HASH_NOT_EXIST == ret) {
|
|
ret = OB_ENTRY_NOT_EXIST;
|
|
} else if (OB_INVALID_INDEX == idx) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("invalid index", K(ret), K(idx));
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
#define DEF_GET_VALUE_BY_INDEX_IMPL(name, obj_name, type) \
|
|
int ObInnerSQLResult::name(const int64_t col_idx, type &val) const \
|
|
{ \
|
|
int ret = OB_SUCCESS; \
|
|
if (!opened_) { \
|
|
ret = OB_NOT_INIT; \
|
|
LOG_WARN("not opened", K(ret)); \
|
|
} else if (NULL == row_) { \
|
|
ret = OB_ERR_UNEXPECTED; \
|
|
LOG_WARN("row is null", K(ret)); \
|
|
} else if (col_idx \
|
|
>= (NULL == row_->projector_ ? row_->count_ : row_->projector_size_)) { \
|
|
ret = OB_SIZE_OVERFLOW; \
|
|
LOG_WARN("column index overflow", K(ret), K(col_idx), "row", *row_); \
|
|
} else { \
|
|
const int64_t idx = (NULL != row_->projector_ ? row_->projector_[col_idx] : col_idx); \
|
|
if (idx < 0 || idx >= row_->count_) { \
|
|
ret = OB_ERR_UNEXPECTED; \
|
|
LOG_WARN("invalid index", K(ret), K(idx), "cell count", row_->count_); \
|
|
} else { \
|
|
const ObObj &obj = row_->cells_[idx]; \
|
|
if (OB_FAIL(check_extend_value(obj))) { \
|
|
LOG_DEBUG("check extend value failed", K(ret)); \
|
|
} else if (OB_FAIL(obj.obj_name(val))) { \
|
|
LOG_WARN("get "#type" value from obj failed", K(ret), K(obj), K(obj.get_meta().get_type()), K(col_idx), K_(row)); \
|
|
} \
|
|
} \
|
|
} \
|
|
return ret; \
|
|
}
|
|
|
|
#define DEF_GET_VALUE_BY_INDEX(name, type) DEF_GET_VALUE_BY_INDEX_IMPL(name, name, type)
|
|
|
|
//DEF_GET_VALUE_BY_INDEX(get_int, int64_t);
|
|
DEF_GET_VALUE_BY_INDEX_IMPL(get_uint, get_uint64, uint64_t);
|
|
DEF_GET_VALUE_BY_INDEX(get_datetime, int64_t);
|
|
DEF_GET_VALUE_BY_INDEX(get_date, int32_t);
|
|
DEF_GET_VALUE_BY_INDEX(get_time, int64_t);
|
|
DEF_GET_VALUE_BY_INDEX(get_year, uint8_t);
|
|
|
|
int ObInnerSQLResult::get_timestamp(const int64_t col_idx, const common::ObTimeZoneInfo *tz_info,
|
|
int64_t &val) const
|
|
{
|
|
UNUSED(tz_info);
|
|
int ret = OB_SUCCESS;
|
|
if (OB_UNLIKELY(!opened_)) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("not opened", K(ret));
|
|
} else if (OB_UNLIKELY(NULL == row_)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("row is null", K(ret));
|
|
} else if (OB_UNLIKELY(col_idx >= (NULL == row_->projector_ ? row_->count_ : row_->projector_size_))) {
|
|
ret = OB_SIZE_OVERFLOW;
|
|
LOG_WARN("column index overflow", K(ret), K(col_idx), "row", *row_);
|
|
} else {
|
|
const int64_t idx = (NULL != row_->projector_ ? row_->projector_[col_idx] : col_idx);
|
|
if (OB_UNLIKELY(idx < 0) || OB_UNLIKELY(idx >= row_->count_)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("invalid index", K(ret), K(idx), "cell count", row_->count_);
|
|
} else {
|
|
const ObObj &obj = row_->cells_[idx];
|
|
if (OB_FAIL(check_extend_value(obj))) {
|
|
LOG_DEBUG("check extend value failed", K(ret));
|
|
} else {
|
|
val = obj.get_timestamp();
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObInnerSQLResult::get_otimestamp_value(const int64_t col_idx, const common::ObTimeZoneInfo &tz_info,
|
|
const common::ObObjType type, common::ObOTimestampData &otimestamp_val) const
|
|
{
|
|
UNUSED(tz_info);
|
|
int ret = OB_SUCCESS;
|
|
if (OB_UNLIKELY(!opened_)) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("not opened", K(ret));
|
|
} else if (OB_UNLIKELY(NULL == row_)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("row is null", K(ret));
|
|
} else if (OB_UNLIKELY(col_idx >= (NULL == row_->projector_ ? row_->count_ : row_->projector_size_))) {
|
|
ret = OB_SIZE_OVERFLOW;
|
|
LOG_WARN("column index overflow", K(ret), K(col_idx), "row", *row_);
|
|
} else {
|
|
const int64_t idx = (NULL != row_->projector_ ? row_->projector_[col_idx] : col_idx);
|
|
if (OB_UNLIKELY(idx < 0) || OB_UNLIKELY(idx >= row_->count_)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("invalid index", K(ret), K(idx), "cell count", row_->count_);
|
|
} else {
|
|
const ObObj &obj = row_->cells_[idx];
|
|
if (OB_UNLIKELY(type != obj.get_type())) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("type is mismatch", K(type), K(obj), K(ret));
|
|
} else if (OB_FAIL(check_extend_value(obj))) {
|
|
LOG_DEBUG("check extend value failed", K(ret));
|
|
} else {
|
|
otimestamp_val = obj.get_otimestamp_value();
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObInnerSQLResult::get_timestamp_tz(const int64_t col_idx, const common::ObTimeZoneInfo &tz_info,
|
|
common::ObOTimestampData &otimestamp_val) const
|
|
{
|
|
return get_otimestamp_value(col_idx, tz_info, ObTimestampTZType, otimestamp_val);
|
|
}
|
|
|
|
int ObInnerSQLResult::get_timestamp_ltz(const int64_t col_idx, const common::ObTimeZoneInfo &tz_info,
|
|
common::ObOTimestampData &otimestamp_val) const
|
|
{
|
|
return get_otimestamp_value(col_idx, tz_info, ObTimestampLTZType, otimestamp_val);
|
|
}
|
|
|
|
int ObInnerSQLResult::get_timestamp_nano(const int64_t col_idx, const common::ObTimeZoneInfo &tz_info,
|
|
common::ObOTimestampData &otimestamp_val) const
|
|
{
|
|
return get_otimestamp_value(col_idx, tz_info, ObTimestampNanoType, otimestamp_val);
|
|
}
|
|
|
|
DEF_GET_VALUE_BY_INDEX(get_interval_ym, ObIntervalYMValue);
|
|
DEF_GET_VALUE_BY_INDEX(get_interval_ds, ObIntervalDSValue);
|
|
|
|
int ObInnerSQLResult::get_bool(const int64_t col_idx, bool &bool_val) const
|
|
{
|
|
int64_t v = 0;
|
|
int ret = OB_SUCCESS;
|
|
if (!opened_) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("not opened", K(ret));
|
|
} else if (OB_INVALID_INDEX == col_idx) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("invalid argument", K(ret), K(col_idx));
|
|
} else if (OB_FAIL(get_int(col_idx, v))) {
|
|
LOG_WARN("get int value failed", K(ret), K(col_idx));
|
|
} else {
|
|
bool_val = v;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
DEF_GET_VALUE_BY_INDEX(get_varchar, ObString);
|
|
DEF_GET_VALUE_BY_INDEX(get_raw, ObString);
|
|
DEF_GET_VALUE_BY_INDEX(get_nvarchar2, ObString);
|
|
DEF_GET_VALUE_BY_INDEX(get_nchar, ObString);
|
|
DEF_GET_VALUE_BY_INDEX(get_float, float);
|
|
DEF_GET_VALUE_BY_INDEX(get_double, double);
|
|
|
|
int ObInnerSQLResult::get_int(const int64_t col_idx, int64_t &int_val) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
const ObObj *obj = NULL;
|
|
if (OB_FAIL(get_obj(col_idx, obj))) {
|
|
LOG_WARN("get obj error", K(ret));
|
|
} else if (OB_ISNULL(obj)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("get a invalud obj", K(col_idx), K(obj), K(ret));
|
|
} else if (OB_UNLIKELY(ObIntTC != obj->get_type_class())) {
|
|
ret = OB_OBJ_TYPE_ERROR;
|
|
LOG_WARN("invalid input type", K(ret), K(*obj));
|
|
} else {
|
|
int_val = obj->get_int();
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObInnerSQLResult::get_number_impl(const int64_t col_idx, number::ObNumber &ret_nmb) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (!opened_) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("not opened", K(ret));
|
|
} else if (NULL == row_) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("row is null", K(ret));
|
|
} else if (col_idx >= (NULL == row_->projector_ ? row_->count_ : row_->projector_size_)) {
|
|
ret = OB_SIZE_OVERFLOW;
|
|
LOG_WARN("column index overflow", K(ret), K(col_idx), "row", *row_);
|
|
} else {
|
|
const int64_t idx = (NULL != row_->projector_ ? row_->projector_[col_idx] : col_idx);
|
|
if (idx < 0 || idx >= row_->count_) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("invalid index", K(ret), K(idx), "cell count", row_->count_);
|
|
} else {
|
|
const ObObj &obj = row_->cells_[idx];
|
|
if (OB_FAIL(check_extend_value(obj))) {
|
|
LOG_DEBUG("check extend value failed", K(ret));
|
|
} else if (obj.is_decimal_int()) {
|
|
if (OB_FAIL(wide::to_number(obj.get_decimal_int(), obj.get_int_bytes(), obj.get_scale(),
|
|
mem_context_->get_arena_allocator(), ret_nmb))) {
|
|
LOG_WARN("to_number failed", K(ret));
|
|
}
|
|
} else if (OB_FAIL(obj.get_number(ret_nmb))) {
|
|
LOG_WARN("get number failed", K(ret));
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
DEF_GET_VALUE_BY_INDEX_IMPL(get_urowid_impl, get_urowid, ObURowIDData);
|
|
|
|
#undef DEF_GET_VALUE_BY_INDEX
|
|
#undef DEF_GET_VALUE_BY_INDEX_IMPL
|
|
|
|
int ObInnerSQLResult::get_type(const int64_t col_idx, ObObjMeta &type) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (!opened_) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("not opened", K(ret));
|
|
} else if (NULL == row_) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("row is null", K(ret));
|
|
} else if (col_idx
|
|
>= (NULL == row_->projector_ ? row_->count_ : row_->projector_size_)) {
|
|
ret = OB_SIZE_OVERFLOW;
|
|
LOG_WARN("column index overflow", K(ret), K(col_idx), "row", *row_);
|
|
} else {
|
|
const int64_t idx = (NULL != row_->projector_ ? row_->projector_[col_idx] : col_idx);
|
|
if (idx < 0 || idx >= row_->count_) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("invalid index", K(ret), K(idx), "cell count", row_->count_);
|
|
} else {
|
|
const ObObj &obj = row_->cells_[idx];
|
|
type = obj.get_meta();
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObInnerSQLResult::get_col_meta(const int64_t col_idx, bool old_max_length,
|
|
oceanbase::common::ObString &name, ObDataType &data_type) const
|
|
{
|
|
UNUSEDx(col_idx, old_max_length, name, data_type);
|
|
int ret = OB_ERR_UNEXPECTED;
|
|
return ret;
|
|
}
|
|
|
|
int64_t ObInnerSQLResult::get_column_count() const
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
int ObInnerSQLResult::get_obj(const int64_t col_idx, ObObj &obj,
|
|
const ObTimeZoneInfo *tz_info,
|
|
ObIAllocator *allocator) const
|
|
{
|
|
UNUSED(tz_info);
|
|
UNUSED(allocator);
|
|
int ret = OB_SUCCESS;
|
|
if (!opened_) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("not opened", K(ret));
|
|
} else if (NULL == row_) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("row is null", K(ret));
|
|
} else if (col_idx
|
|
>= (NULL == row_->projector_ ? row_->count_ : row_->projector_size_)) {
|
|
ret = OB_SIZE_OVERFLOW;
|
|
LOG_WARN("column index overflow", K(ret), K(col_idx), "row", *row_);
|
|
} else {
|
|
const int64_t idx = (NULL != row_->projector_ ? row_->projector_[col_idx] : col_idx);
|
|
if (idx < 0 || idx >= row_->count_) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("invalid index", K(ret), K(idx), "cell count", row_->count_);
|
|
} else {
|
|
obj = row_->cells_[idx];
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
#define DEF_GET_VALUE_BY_NAME(name, type) \
|
|
int ObInnerSQLResult::name(const char *col_name, type &val) const \
|
|
{ \
|
|
int ret = OB_SUCCESS; \
|
|
int64_t idx = OB_INVALID_INDEX; \
|
|
if (!opened_) { \
|
|
ret = OB_NOT_INIT; \
|
|
LOG_WARN("not opened", K(ret)); \
|
|
} else if (NULL == col_name) { \
|
|
ret = OB_INVALID_ARGUMENT; \
|
|
LOG_WARN("column name can not be NULL", K(ret)); \
|
|
} else if (OB_FAIL(find_idx(col_name, idx))) { \
|
|
if (OB_ENTRY_NOT_EXIST == ret) { \
|
|
ret = OB_ERR_COLUMN_NOT_FOUND; \
|
|
} else { \
|
|
LOG_WARN("find column index failed", K(ret), K(col_name)); \
|
|
} \
|
|
} else if (OB_INVALID_INDEX == idx) { \
|
|
ret = OB_ERR_UNEXPECTED; \
|
|
LOG_WARN("invalid index returned", K(ret), K(idx)); \
|
|
} else if (OB_FAIL(name(idx, val))) { \
|
|
if (OB_ERR_NULL_VALUE != ret) { \
|
|
LOG_WARN(#name" failed", K(ret), K(idx)); \
|
|
} \
|
|
} \
|
|
return ret; \
|
|
}
|
|
|
|
DEF_GET_VALUE_BY_NAME(get_int, int64_t);
|
|
DEF_GET_VALUE_BY_NAME(get_uint, uint64_t);
|
|
DEF_GET_VALUE_BY_NAME(get_datetime, int64_t);
|
|
DEF_GET_VALUE_BY_NAME(get_date, int32_t);
|
|
DEF_GET_VALUE_BY_NAME(get_time, int64_t);
|
|
DEF_GET_VALUE_BY_NAME(get_year, uint8_t);
|
|
DEF_GET_VALUE_BY_NAME(get_bool, bool);
|
|
DEF_GET_VALUE_BY_NAME(get_varchar, ObString);
|
|
DEF_GET_VALUE_BY_NAME(get_raw, ObString);
|
|
DEF_GET_VALUE_BY_NAME(get_float, float);
|
|
DEF_GET_VALUE_BY_NAME(get_double, double);
|
|
DEF_GET_VALUE_BY_NAME(get_number_impl, number::ObNumber);
|
|
DEF_GET_VALUE_BY_NAME(get_type, ObObjMeta);
|
|
DEF_GET_VALUE_BY_NAME(get_obj, ObObj);
|
|
DEF_GET_VALUE_BY_NAME(get_interval_ym, ObIntervalYMValue);
|
|
DEF_GET_VALUE_BY_NAME(get_interval_ds, ObIntervalDSValue);
|
|
DEF_GET_VALUE_BY_NAME(get_nvarchar2, ObString);
|
|
DEF_GET_VALUE_BY_NAME(get_nchar, ObString);
|
|
DEF_GET_VALUE_BY_NAME(get_urowid_impl, ObURowIDData);
|
|
#undef DEF_GET_VALUE_BY_NAME
|
|
|
|
int ObInnerSQLResult::get_timestamp(const char *col_name, const common::ObTimeZoneInfo *tz_info,
|
|
int64_t &val) const
|
|
{
|
|
UNUSED(tz_info);
|
|
int ret = OB_SUCCESS;
|
|
int64_t idx = OB_INVALID_INDEX;
|
|
if (OB_UNLIKELY(!opened_)) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("not opened", K(ret));
|
|
} else if (OB_UNLIKELY(NULL == col_name)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("column name can not be NULL", K(ret));
|
|
} else if (OB_FAIL(find_idx(col_name, idx))) {
|
|
if (OB_ENTRY_NOT_EXIST == ret) {
|
|
ret = OB_ERR_COLUMN_NOT_FOUND;
|
|
} else {
|
|
LOG_WARN("find column index failed", K(ret), K(col_name));
|
|
}
|
|
} else if (OB_UNLIKELY(OB_INVALID_INDEX == idx)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("invalid index returned", K(ret), K(idx));
|
|
} else if (OB_FAIL(get_timestamp(idx, tz_info, val))) {
|
|
if (OB_ERR_NULL_VALUE != ret) {
|
|
LOG_WARN("get_timestamp failed", K(ret), K(idx));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObInnerSQLResult::get_otimestamp_value(const char *col_name, const common::ObTimeZoneInfo &tz_info,
|
|
const common::ObObjType type, common::ObOTimestampData &otimestamp_val) const
|
|
{
|
|
UNUSED(tz_info);
|
|
int ret = OB_SUCCESS;
|
|
int64_t idx = OB_INVALID_INDEX;
|
|
if (OB_UNLIKELY(!opened_)) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("not opened", K(ret));
|
|
} else if (OB_UNLIKELY(NULL == col_name)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("column name can not be NULL", K(ret));
|
|
} else if (OB_FAIL(find_idx(col_name, idx))) {
|
|
if (OB_ENTRY_NOT_EXIST == ret) {
|
|
ret = OB_ERR_COLUMN_NOT_FOUND;
|
|
} else {
|
|
LOG_WARN("find column index failed", K(ret), K(col_name));
|
|
}
|
|
} else if (OB_UNLIKELY(OB_INVALID_INDEX == idx)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("invalid index returned", K(ret), K(idx));
|
|
} else if (OB_FAIL(get_otimestamp_value(idx, tz_info, type, otimestamp_val))) {
|
|
if (OB_ERR_NULL_VALUE != ret) {
|
|
LOG_WARN("get_otimestamp failed", K(ret), K(idx));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObInnerSQLResult::get_timestamp_tz(const char *col_name, const common::ObTimeZoneInfo &tz_info,
|
|
common::ObOTimestampData &otimestamp_val) const
|
|
{
|
|
return get_otimestamp_value(col_name, tz_info, ObTimestampTZType, otimestamp_val);
|
|
}
|
|
|
|
int ObInnerSQLResult::get_timestamp_ltz(const char *col_name, const common::ObTimeZoneInfo &tz_info,
|
|
common::ObOTimestampData &otimestamp_val) const
|
|
{
|
|
return get_otimestamp_value(col_name, tz_info, ObTimestampLTZType, otimestamp_val);
|
|
}
|
|
|
|
int ObInnerSQLResult::get_timestamp_nano(const char *col_name, const common::ObTimeZoneInfo &tz_info,
|
|
common::ObOTimestampData &otimestamp_val) const
|
|
{
|
|
return get_otimestamp_value(col_name, tz_info, ObTimestampNanoType, otimestamp_val);
|
|
}
|
|
|
|
int ObInnerSQLResult::get_number(const int64_t col_idx,
|
|
common::number::ObNumber &nmb_val) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (!opened_) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("not opened", K(ret));
|
|
} else if (OB_INVALID_INDEX == col_idx) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("invalid argument", K(ret), K(col_idx));
|
|
} else if (OB_FAIL(get_number_impl(col_idx, nmb_val))) {
|
|
LOG_WARN("get number impl failed", K(ret), K(col_idx));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObInnerSQLResult::get_number(const char *col_name, common::number::ObNumber &nmb_val) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (!opened_) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("not opened", K(ret));
|
|
} else if (NULL == col_name) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("invalid argument", K(ret), KP(col_name));
|
|
} else if (OB_FAIL(get_number_impl(col_name, nmb_val))) {
|
|
LOG_WARN("get number impl failed", K(ret), K(col_name));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObInnerSQLResult::inner_get_number(const int64_t col_idx, number::ObNumber &nmb_val,
|
|
IAllocator &allocator) const
|
|
{
|
|
UNUSED(allocator);
|
|
int ret = OB_SUCCESS;
|
|
if (!opened_) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("not opened", K(ret));
|
|
} else if (OB_INVALID_INDEX == col_idx) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("invalid argument", K(ret), K(col_idx));
|
|
} else if (OB_FAIL(get_number_impl(col_idx, nmb_val))) {
|
|
LOG_WARN("get number impl failed", K(ret), K(col_idx));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObInnerSQLResult::inner_get_number(const char *col_name, number::ObNumber &nmb_val,
|
|
IAllocator &allocator) const
|
|
{
|
|
UNUSED(allocator);
|
|
int ret = OB_SUCCESS;
|
|
if (!opened_) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("not opened", K(ret));
|
|
} else if (NULL == col_name) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("invalid argument", K(ret), KP(col_name));
|
|
} else if (OB_FAIL(get_number_impl(col_name, nmb_val))) {
|
|
LOG_WARN("get number impl failed", K(ret), K(col_name));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObInnerSQLResult::inner_get_urowid(const int64_t col_idx,
|
|
ObURowIDData &urowid_data,
|
|
ObIAllocator &/* not used */) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (!opened_) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("not opened", K(ret));
|
|
} else if (OB_FAIL(get_urowid_impl(col_idx, urowid_data))) {
|
|
LOG_WARN("failed to get urowid", K(ret));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObInnerSQLResult::inner_get_urowid(const char* col_name,
|
|
ObURowIDData &urowid_data,
|
|
ObIAllocator &/* no used */) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (!opened_) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("not opened", K(ret));
|
|
} else if (OB_FAIL(get_urowid_impl(col_name, urowid_data))) {
|
|
LOG_WARN("failed to get urowid data", K(ret));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObInnerSQLResult::get_lob_locator(const int64_t col_idx, ObLobLocator *&lob_locator) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_FAIL(get_lob_locator_impl(col_idx, lob_locator))) {
|
|
LOG_WARN("get lob locator impl failed", K(ret), K(col_idx));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObInnerSQLResult::get_lob_locator(const char *col_name, ObLobLocator *&lob_locator) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_FAIL(get_lob_locator_impl(col_name, lob_locator))) {
|
|
LOG_WARN("get lob locator impl failed", K(ret), K(col_name));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObInnerSQLResult::inner_get_lob_locator(const int64_t col_idx, ObLobLocator *&lob_locator,
|
|
ObIAllocator &allocator) const
|
|
{
|
|
UNUSED(allocator);
|
|
int ret = OB_SUCCESS;
|
|
if (OB_FAIL(get_lob_locator_impl(col_idx, lob_locator))) {
|
|
LOG_WARN("get lob locator impl failed", K(ret), K(col_idx));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObInnerSQLResult::inner_get_lob_locator(const char *col_name, ObLobLocator *&lob_locator,
|
|
ObIAllocator &allocator) const
|
|
{
|
|
UNUSED(allocator);
|
|
int ret = OB_SUCCESS;
|
|
if (OB_FAIL(get_lob_locator_impl(col_name, lob_locator))) {
|
|
LOG_WARN("get lob locator impl failed", K(ret), K(col_name));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObInnerSQLResult::get_lob_locator_impl(const int64_t col_idx, ObLobLocator *&lob_locator) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (!opened_) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("not opened", K(ret));
|
|
} else if (OB_ISNULL(row_)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("row is null", K(ret));
|
|
} else if (OB_INVALID_INDEX == col_idx) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("invalid argument", K(ret), K(col_idx));
|
|
} else if (col_idx >= (NULL == row_->projector_ ? row_->count_ : row_->projector_size_)) {
|
|
ret = OB_SIZE_OVERFLOW;
|
|
LOG_WARN("column index overflow", K(ret), K(col_idx), "row", *row_);
|
|
} else {
|
|
const int64_t idx = (NULL != row_->projector_ ? row_->projector_[col_idx] : col_idx);
|
|
if (idx < 0 || idx >= row_->count_) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("invalid index", K(ret), K(idx), "cell count", row_->count_);
|
|
} else {
|
|
const ObObj &obj = row_->cells_[idx];
|
|
if (OB_FAIL(check_extend_value(obj))) {
|
|
LOG_DEBUG("check extend value failed", K(ret));
|
|
} else if (OB_FAIL(obj.get_lob_locator(lob_locator))) {
|
|
LOG_WARN("get lob locator value from obj failed", K(ret), K(obj), K(col_idx), K_(row));
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObInnerSQLResult::get_lob_locator_impl(const char *col_name, ObLobLocator *&lob_locator) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (!opened_) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("not opened", K(ret));
|
|
} else {
|
|
int64_t idx = OB_INVALID_INDEX;
|
|
if (OB_ISNULL(col_name)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("column name can not be NULL", K(ret));
|
|
} else if (OB_FAIL(find_idx(col_name, idx))) {
|
|
if (OB_ENTRY_NOT_EXIST == ret) {
|
|
ret = OB_ERR_COLUMN_NOT_FOUND;
|
|
} else {
|
|
LOG_WARN("find column index failed", K(ret), K(col_name));
|
|
}
|
|
} else if (OB_INVALID_INDEX == idx) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("invalid index returned", K(ret), K(idx));
|
|
} else if (OB_FAIL(get_lob_locator_impl(idx, lob_locator))) {
|
|
if (OB_ERR_NULL_VALUE != ret) {
|
|
LOG_WARN("inner get lob locator failed", K(ret), K(idx));
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObInnerSQLResult::get_obj(const int64_t col_idx, const common::ObObj *&result) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (!opened_) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("not opened", K(ret));
|
|
} else if (NULL == row_) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("row is null", K(ret));
|
|
} else if (col_idx
|
|
>= (NULL == row_->projector_ ? row_->count_ : row_->projector_size_)) {
|
|
ret = OB_SIZE_OVERFLOW;
|
|
LOG_WARN("column index overflow", K(ret), K(col_idx), "row", *row_);
|
|
} else {
|
|
const int64_t idx = (NULL != row_->projector_ ? row_->projector_[col_idx] : col_idx);
|
|
if (idx < 0 || idx >= row_->count_) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("invalid index", K(ret), K(idx), "cell count", row_->count_);
|
|
} else {
|
|
const ObObj &obj = row_->cells_[idx];
|
|
if (OB_FAIL(check_extend_value(obj))) {
|
|
LOG_DEBUG("check extend value failed", K(ret));
|
|
} else {
|
|
result = &obj;
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObInnerSQLResult::print_info() const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (!opened_) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("not opened", K(ret));
|
|
} else {
|
|
LOG_INFO("result", K_(result_set));
|
|
}
|
|
return ret;
|
|
}
|
|
} // end of namespace observer
|
|
} // end of namespace oceanbase
|