541 lines
21 KiB
C++
541 lines
21 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 COMMON
|
|
#include "share/ob_virtual_table_iterator.h"
|
|
#include "share/schema/ob_schema_getter_guard.h"
|
|
#include "share/config/ob_server_config.h"
|
|
#include "share/object/ob_obj_cast.h"
|
|
#include "common/rowkey/ob_rowkey_info.h"
|
|
#include "share/inner_table/ob_inner_table_schema.h"
|
|
#include "sql/engine/ob_operator.h"
|
|
#include "sql/engine/expr/ob_expr_column_conv.h"
|
|
#include "sql/session/ob_sql_session_info.h"
|
|
|
|
using namespace oceanbase::common;
|
|
using namespace oceanbase::share;
|
|
using namespace oceanbase::sql;
|
|
using namespace oceanbase::share::schema;
|
|
namespace oceanbase {
|
|
namespace common {
|
|
|
|
void ObVirtualTableIterator::reset()
|
|
{
|
|
output_column_ids_.reset();
|
|
reserved_column_cnt_ = 0;
|
|
schema_guard_ = NULL;
|
|
table_schema_ = NULL;
|
|
index_schema_ = NULL;
|
|
// Since ObObj's destructor does not do meaningful operations, in order to save performance, ObObj's destructor call
|
|
// is omitted, and the cells_memory is directly released.
|
|
if (OB_LIKELY(NULL != allocator_ && NULL != cur_row_.cells_)) {
|
|
allocator_->free(cur_row_.cells_);
|
|
}
|
|
cur_row_.cells_ = NULL;
|
|
cur_row_.count_ = 0;
|
|
key_ranges_.reset();
|
|
reset_convert_ctx();
|
|
allocator_ = NULL;
|
|
session_ = NULL;
|
|
}
|
|
|
|
void ObVirtualTableIterator::reset_convert_ctx()
|
|
{
|
|
if (OB_LIKELY(NULL != allocator_ && NULL != convert_row_.cells_)) {
|
|
allocator_->free(convert_row_.cells_);
|
|
}
|
|
saved_key_ranges_.reset();
|
|
cols_schema_.reset();
|
|
convert_row_.cells_ = NULL;
|
|
convert_row_.count_ = 0;
|
|
need_convert_ = false;
|
|
convert_alloc_.reset();
|
|
}
|
|
|
|
int ObVirtualTableIterator::free_convert_ctx()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (!need_convert_) {
|
|
} else if (OB_UNLIKELY(convert_row_.count_ <= 0 || NULL == convert_row_.cells_)) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("convert row is not init", K(ret), K(convert_row_));
|
|
} else {
|
|
if (OB_ISNULL(allocator_)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("allocator is NULL", K(ret));
|
|
} else {
|
|
key_ranges_.reset();
|
|
if (OB_FAIL(key_ranges_.assign(saved_key_ranges_))) {
|
|
LOG_WARN("failed to assign key ranges", K(ret));
|
|
}
|
|
saved_key_ranges_.reset();
|
|
// Since ObObj's destructor does not do meaningful operations, in order to save performance, ObObj's destructor
|
|
// call is omitted, and the cells_memory is directly released.
|
|
allocator_->free(convert_row_.cells_);
|
|
convert_row_.cells_ = NULL;
|
|
convert_row_.count_ = 0;
|
|
convert_alloc_.reset();
|
|
cols_schema_.reset();
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObVirtualTableIterator::convert_key(
|
|
const ObRowkey& src, ObRowkey& dst, common::ObIArray<const ObColumnSchemaV2*>& key_cols)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (src.get_obj_cnt() > 0) {
|
|
const ObObj* src_key_objs = src.get_obj_ptr();
|
|
void* tmp_ptr = NULL;
|
|
ObObj* new_key_obj = NULL;
|
|
tmp_ptr = allocator_->alloc(src.get_obj_cnt() * sizeof(ObObj));
|
|
if (OB_ISNULL(tmp_ptr)) {
|
|
ret = OB_ALLOCATE_MEMORY_FAILED;
|
|
LOG_WARN("fail to alloc new obj", K(ret));
|
|
} else if (OB_ISNULL(new_key_obj = new (tmp_ptr) ObObj[src.get_obj_cnt()])) {
|
|
ret = OB_ALLOCATE_MEMORY_FAILED;
|
|
LOG_WARN("fail to alloc new obj", K(ret));
|
|
} else if (src.get_obj_cnt() > key_cols.count()) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("keys are not match with columns", K(ret));
|
|
}
|
|
CompatModeGuard g(ObWorker::CompatMode::MYSQL);
|
|
const ObDataTypeCastParams dtc_params = ObBasicSessionInfo::create_dtc_params(session_);
|
|
ObCastCtx cast_ctx(allocator_, &dtc_params, CM_NONE, ObCharset::get_system_collation());
|
|
for (uint64_t nth_obj = 0; OB_SUCC(ret) && nth_obj < src.get_obj_cnt(); ++nth_obj) {
|
|
const ObObj& src_obj = src_key_objs[nth_obj];
|
|
if (src_obj.is_min_value()) {
|
|
new_key_obj[nth_obj].set_min_value();
|
|
} else if (src_obj.is_max_value()) {
|
|
new_key_obj[nth_obj].set_max_value();
|
|
} else if (src_obj.is_null()) {
|
|
new_key_obj[nth_obj].set_null();
|
|
} else {
|
|
if (OB_FAIL(ObObjCaster::to_type(
|
|
key_cols.at(nth_obj)->get_data_type(), cast_ctx, src_key_objs[nth_obj], new_key_obj[nth_obj]))) {
|
|
LOG_WARN("fail to cast obj",
|
|
K(ret),
|
|
K(allocator_),
|
|
K(key_cols.at(nth_obj)->get_data_type()),
|
|
K(src_key_objs[nth_obj]));
|
|
}
|
|
}
|
|
} // end for
|
|
if (OB_SUCC(ret)) {
|
|
dst.assign(new_key_obj, src.get_obj_cnt());
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
// get origin type of keys in mysql mode
|
|
// first find the column name that is same as origin virtual table in mysql mode
|
|
// then find column type by column name
|
|
int ObVirtualTableIterator::get_key_cols(common::ObIArray<const ObColumnSchemaV2*>& key_cols)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
common::ObArray<uint64_t> column_ids;
|
|
key_cols.reset();
|
|
if (need_convert_ && !key_ranges_.empty()) {
|
|
if (index_schema_->get_rowkey_info().get_column_ids(column_ids)) {
|
|
LOG_WARN("get key column ids failed", K(ret));
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
common::ObArray<const ObString*> column_names;
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < column_ids.count(); ++i) {
|
|
const ObColumnSchemaV2* col_schema = table_schema_->get_column_schema(column_ids.at(i));
|
|
if (OB_ISNULL(col_schema)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("column schema is null", K(ret));
|
|
} else if (OB_FAIL(column_names.push_back(&col_schema->get_column_name_str()))) {
|
|
LOG_WARN("fail to push back column name", K(ret));
|
|
}
|
|
}
|
|
if (OB_SUCC(ret) && column_ids.count() != column_names.count()) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("column infos are not match ", K(ret));
|
|
}
|
|
// get origin key type by column name
|
|
if (OB_SUCC(ret)) {
|
|
const ObTableSchema* org_table_schema = NULL;
|
|
uint64_t org_table_id = get_origin_tid_by_oracle_mapping_tid(table_schema_->get_table_id());
|
|
if (OB_INVALID_ID == org_table_id) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("failed to get origin table id", K(ret));
|
|
} else if (OB_FAIL(
|
|
schema_guard_->get_table_schema(combine_id(OB_SYS_TENANT_ID, org_table_id), org_table_schema))) {
|
|
LOG_WARN("get table schema failed", K(org_table_id), K(ret));
|
|
} else if (NULL == org_table_schema) {
|
|
ret = OB_TABLE_NOT_EXIST;
|
|
LOG_WARN("get table schema failed", K(ret));
|
|
} else {
|
|
// switch mysql mode, find column schema by column name
|
|
CompatModeGuard g(ObWorker::CompatMode::MYSQL);
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < column_names.count(); ++i) {
|
|
const ObString* column_name = column_names.at(i);
|
|
const ObColumnSchemaV2* col_schema = org_table_schema->get_column_schema(*column_name);
|
|
if (OB_ISNULL(col_schema)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("column schema is null", K(ret), K(*column_name));
|
|
} else if (OB_FAIL(key_cols.push_back(col_schema))) {
|
|
LOG_WARN("fail to push back column name", K(ret));
|
|
}
|
|
}
|
|
if (OB_SUCC(ret) && key_cols.count() != column_names.count()) {
|
|
LOG_WARN("column infos are not match ", K(ret));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
// If key objects are in oracle mode, then need to convert to obj in mysql mode
|
|
// and it's find the origin type in mysql mode
|
|
// every virtual table in oracle mode must be match with one virtual table in mysql mode
|
|
int ObVirtualTableIterator::convert_key_ranges()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(table_schema_)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("table schema is NULL", K(ret));
|
|
} else if (!key_ranges_.empty()) {
|
|
common::ObSEArray<common::ObNewRange, 16> tmp_range;
|
|
common::ObArray<const ObColumnSchemaV2*> key_cols;
|
|
if (OB_FAIL(get_key_cols(key_cols))) {
|
|
LOG_WARN("failed to get key types", K(ret));
|
|
}
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < key_ranges_.count(); ++i) {
|
|
ObNewRange new_range;
|
|
new_range.table_id_ = key_ranges_.at(i).table_id_;
|
|
new_range.border_flag_ = key_ranges_.at(i).border_flag_;
|
|
if (OB_FAIL(convert_key(key_ranges_.at(i).start_key_, new_range.start_key_, key_cols))) {
|
|
LOG_WARN("fail to convert start key", K(ret), K(allocator_));
|
|
} else if (OB_FAIL(convert_key(key_ranges_.at(i).end_key_, new_range.end_key_, key_cols))) {
|
|
LOG_WARN("fail to convert end key", K(ret), K(allocator_));
|
|
} else if (OB_FAIL(tmp_range.push_back(new_range))) {
|
|
LOG_WARN("fail to push back new range", K(ret), K(allocator_));
|
|
}
|
|
} // end for
|
|
if (OB_SUCC(ret)) {
|
|
if (OB_FAIL(saved_key_ranges_.assign(key_ranges_))) {
|
|
LOG_WARN("fail to assign new range", K(ret), K(allocator_));
|
|
} else {
|
|
key_ranges_.reset();
|
|
if (OB_FAIL(key_ranges_.assign(tmp_range))) {
|
|
LOG_WARN("fail to assign new range", K(ret), K(allocator_));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObVirtualTableIterator::init_convert_ctx()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
convert_alloc_.set_tenant_id(table_schema_->get_tenant_id());
|
|
const ObDataTypeCastParams dtc_params = ObBasicSessionInfo::create_dtc_params(session_);
|
|
ObCastCtx cast_ctx(&convert_alloc_, &dtc_params, CM_NONE, table_schema_->get_collation_type());
|
|
cast_ctx_ = cast_ctx;
|
|
|
|
if (need_convert_) {
|
|
ObObj* cells = NULL;
|
|
void* tmp_ptr = NULL;
|
|
if (OB_UNLIKELY(NULL == allocator_ || 0 == reserved_column_cnt_ || NULL == table_schema_ || NULL == session_)) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("data member is not init", K(ret), K(allocator_), K(reserved_column_cnt_));
|
|
} else if (OB_ISNULL(tmp_ptr = allocator_->alloc(reserved_column_cnt_ * sizeof(ObObj)))) {
|
|
ret = OB_ALLOCATE_MEMORY_FAILED;
|
|
COMMON_LOG(ERROR, "fail to alloc cells", K(ret), K(reserved_column_cnt_));
|
|
} else if (OB_ISNULL(cells = new (tmp_ptr) ObObj[reserved_column_cnt_])) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("fail to new cell array", K(ret), K(reserved_column_cnt_));
|
|
} else {
|
|
convert_row_.cells_ = cells;
|
|
convert_row_.count_ = reserved_column_cnt_;
|
|
if (OB_FAIL(convert_key_ranges())) {
|
|
LOG_WARN("fail to convert key ranges", K(ret), K(key_ranges_), K(reserved_column_cnt_));
|
|
}
|
|
}
|
|
}
|
|
LOG_DEBUG("key ranges", K(ret), K(key_ranges_));
|
|
return ret;
|
|
}
|
|
|
|
int ObVirtualTableIterator::open()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
void* tmp_ptr = NULL;
|
|
ObObj* cells = NULL;
|
|
if (OB_UNLIKELY(NULL == allocator_ || 0 == reserved_column_cnt_)) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("data member is not init", K(ret), K(allocator_), K(reserved_column_cnt_));
|
|
} else if (OB_ISNULL(scan_param_) || (NULL != scan_param_->output_exprs_ && NULL == scan_param_->op_)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("invalid argument", K(ret));
|
|
} else if (OB_ISNULL(tmp_ptr = allocator_->alloc(reserved_column_cnt_ * sizeof(ObObj)))) {
|
|
ret = OB_ALLOCATE_MEMORY_FAILED;
|
|
COMMON_LOG(ERROR, "fail to alloc cells", K(ret), K(reserved_column_cnt_));
|
|
} else if (OB_ISNULL(cells = new (tmp_ptr) ObObj[reserved_column_cnt_])) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("fail to new cell array", K(ret), K(reserved_column_cnt_));
|
|
} else {
|
|
cur_row_.cells_ = cells;
|
|
cur_row_.count_ = reserved_column_cnt_;
|
|
if (OB_FAIL(init_convert_ctx())) {
|
|
LOG_WARN("fail to init convert context", K(ret));
|
|
} else if (OB_FAIL(inner_open())) {
|
|
LOG_WARN("fail to inner open", K(ret));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObVirtualTableIterator::get_all_columns_schema()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < output_column_ids_.count(); ++i) {
|
|
const uint64_t column_id = output_column_ids_.at(i);
|
|
const ObColumnSchemaV2* col_schema = table_schema_->get_column_schema(column_id);
|
|
if (OB_ISNULL(col_schema)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_ERROR("col_schema is NULL", K(ret), K(column_id));
|
|
} else if (OB_FAIL(cols_schema_.push_back(col_schema))) {
|
|
LOG_WARN("failed to push back column schema", K(ret));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObVirtualTableIterator::convert_output_row(ObNewRow*& cur_row)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(cur_row)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("current row is NULL", K(ret));
|
|
} else if (!need_convert_) {
|
|
// don't convert
|
|
} else {
|
|
convert_alloc_.reuse();
|
|
if (cols_schema_.empty() && OB_FAIL(get_all_columns_schema())) {
|
|
LOG_WARN("failed to get columns schema", K(ret));
|
|
}
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < output_column_ids_.count(); ++i) {
|
|
const uint64_t column_id = output_column_ids_.at(i);
|
|
const ObColumnSchemaV2* col_schema = cols_schema_.at(i);
|
|
if (cur_row->get_cell(i).is_null() ||
|
|
(cur_row->get_cell(i).is_string_type() && 0 == cur_row->get_cell(i).get_data_length())) {
|
|
convert_row_.cells_[i].set_null();
|
|
} else if (OB_FAIL(ObObjCaster::to_type(col_schema->get_data_type(),
|
|
col_schema->get_collation_type(),
|
|
cast_ctx_,
|
|
cur_row->get_cell(i),
|
|
convert_row_.cells_[i]))) {
|
|
LOG_WARN("failed to cast obj in oracle mode", K(ret), K(column_id));
|
|
}
|
|
}
|
|
cur_row = &convert_row_;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObVirtualTableIterator::get_next_row(ObNewRow*& row)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObNewRow* cur_row = NULL;
|
|
if (OB_FAIL(inner_get_next_row(cur_row))) {
|
|
if (OB_UNLIKELY(OB_ITER_END != ret)) {
|
|
LOG_WARN("fail to inner get next row", K(ret));
|
|
}
|
|
} else if (OB_ISNULL(cur_row)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("succ to inner get next row, but row is NULL", K(ret));
|
|
} else if (OB_UNLIKELY(cur_row->count_ < output_column_ids_.count())) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_ERROR("row count is less than output column count", K(ret), K(cur_row->count_), K(output_column_ids_.count()));
|
|
} else if (OB_ISNULL(cur_row->cells_)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_ERROR("cur_row->cells_ is NULL", K(ret));
|
|
} else if (OB_ISNULL(table_schema_)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_ERROR("table schema is NULL", K(ret));
|
|
} else if (OB_FAIL(convert_output_row(cur_row))) {
|
|
LOG_WARN("failed to convert row", K(ret));
|
|
}
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < output_column_ids_.count(); ++i) {
|
|
const uint64_t column_id = output_column_ids_.at(i);
|
|
const ObColumnSchemaV2* col_schema = table_schema_->get_column_schema(column_id);
|
|
if (OB_ISNULL(col_schema)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_ERROR("col_schema is NULL", K(ret), K(column_id));
|
|
} else if (OB_UNLIKELY(col_schema->get_data_type() != cur_row->cells_[i].get_type() &&
|
|
ObNullType != cur_row->cells_[i].get_type())) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
if (GCONF.in_upgrade_mode()) {
|
|
LOG_WARN("column type in this row is not expected type",
|
|
K(ret),
|
|
K(i),
|
|
"table_name",
|
|
table_schema_->get_table_name_str(),
|
|
"column_name",
|
|
col_schema->get_column_name_str(),
|
|
K(column_id),
|
|
K(cur_row->cells_[i]),
|
|
K(col_schema->get_data_type()),
|
|
K(output_column_ids_));
|
|
} else {
|
|
LOG_ERROR("column type in this row is not expected type",
|
|
K(ret),
|
|
K(i),
|
|
"table_name",
|
|
table_schema_->get_table_name_str(),
|
|
"column_name",
|
|
col_schema->get_column_name_str(),
|
|
K(column_id),
|
|
K(cur_row->cells_[i]),
|
|
K(col_schema->get_data_type()),
|
|
K(output_column_ids_));
|
|
}
|
|
}
|
|
if (OB_SUCC(ret) && ob_is_string_tc(col_schema->get_data_type()) &&
|
|
col_schema->get_data_length() < cur_row->cells_[i].get_string_len()) {
|
|
// Check the column schema to ensure that it meets the schema definition;
|
|
// But currently, only strings that exceed the length limit are processed to prevent occupying too many
|
|
// performance resources and causing too much interface delay
|
|
ObObj output_obj;
|
|
ObArray<ObString>* type_infos = NULL;
|
|
const bool is_strict = false;
|
|
ObExprResType res_type;
|
|
res_type.set_accuracy(col_schema->get_accuracy());
|
|
res_type.set_collation_type(col_schema->get_collation_type());
|
|
res_type.set_type(col_schema->get_data_type());
|
|
ObCastCtx cast_ctx = cast_ctx_;
|
|
cast_ctx.cast_mode_ = cast_ctx_.cast_mode_ | CM_WARN_ON_FAIL;
|
|
if (OB_FAIL(ObExprColumnConv::convert_skip_null_check(
|
|
output_obj, cur_row->cells_[i], res_type, is_strict, cast_ctx, type_infos))) {
|
|
LOG_WARN("fail to convert skip null check", KR(ret), "object", cur_row->cells_[i]);
|
|
} else {
|
|
cur_row->cells_[i] = output_obj;
|
|
if (OB_SUCCESS != cast_ctx.warning_) {
|
|
LOG_WARN("invalid row result, check schema",
|
|
"warning_num",
|
|
cast_ctx.warning_,
|
|
"object",
|
|
cur_row->cells_[i],
|
|
K(res_type));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
row = cur_row;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObVirtualTableIterator::get_next_row()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObNewRow* row = NULL;
|
|
if (OB_ISNULL(scan_param_) || OB_ISNULL(scan_param_->output_exprs_) || OB_ISNULL(scan_param_->op_)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("invalid argument", K(ret));
|
|
} else if (OB_FAIL(get_next_row(row))) {
|
|
if (OB_ITER_END != ret) {
|
|
LOG_WARN("get next row failed", K(ret));
|
|
}
|
|
} else if (OB_ISNULL(row)) {
|
|
LOG_WARN("NULL row returned", K(ret));
|
|
} else if (scan_param_->output_exprs_->count() > row->count_) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN(
|
|
"row count less than output exprs", K(ret), K(*row), "output_exprs_cnt", scan_param_->output_exprs_->count());
|
|
} else {
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < scan_param_->output_exprs_->count(); i++) {
|
|
ObExpr* expr = scan_param_->output_exprs_->at(i);
|
|
ObDatum& datum = expr->locate_datum_for_write(scan_param_->op_->get_eval_ctx());
|
|
if (OB_FAIL(datum.from_obj(row->cells_[i], expr->obj_datum_map_))) {
|
|
LOG_WARN("convert ObObj to ObDatum failed", K(ret));
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObVirtualTableIterator::close()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_UNLIKELY(cur_row_.count_ <= 0 || NULL == cur_row_.cells_)) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("cur_row is not init", K(ret), K(cur_row_));
|
|
} else if (OB_FAIL(inner_close())) {
|
|
LOG_WARN("fail to execute inner close", K(ret));
|
|
} else if (OB_FAIL(free_convert_ctx())) {
|
|
LOG_WARN("fail to free convert context", K(ret));
|
|
} else {
|
|
if (OB_ISNULL(allocator_)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("allocator is NULL", K(ret));
|
|
} else {
|
|
// Since ObObj's destructor does not do meaningful operations, in order to save performance, ObObj's destructor
|
|
// call is omitted, and the cells_memory is directly released.
|
|
allocator_->free(cur_row_.cells_);
|
|
cur_row_.cells_ = NULL;
|
|
cur_row_.count_ = 0;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
// level_str support: db_acc, table_acc
|
|
// reference: ob_expr_sys_privilege_check.cpp:calc_resultN
|
|
int ObVirtualTableIterator::check_priv(const ObString &level_str,
|
|
const ObString &db_name,
|
|
const ObString &table_name,
|
|
int64_t tenant_id,
|
|
bool &passed)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
share::schema::ObSessionPrivInfo session_priv;
|
|
CK (OB_NOT_NULL(session_) && OB_NOT_NULL(schema_guard_));
|
|
OX (session_->get_session_priv_info(session_priv));
|
|
// bool allow_show = true;
|
|
if (OB_SUCC(ret)) {
|
|
//tenant_id in table is static casted to int64_t,
|
|
//and use statis_cast<uint64_t> for retrieving(same with schema_service)
|
|
// schema拆分后,普通租户schema表的tenant_id为0,此时鉴权取session_priv.tenant_id_
|
|
if (session_priv.tenant_id_ != static_cast<uint64_t>(tenant_id)
|
|
&& OB_INVALID_TENANT_ID != tenant_id) {
|
|
//not current tenant's row
|
|
} else if (0 == level_str.case_compare("db_acc")) {
|
|
if (OB_FAIL(schema_guard_->check_db_show(session_priv, db_name, passed))) {
|
|
LOG_WARN("Check db show failed", K(ret));
|
|
}
|
|
} else if (0 == level_str.case_compare("table_acc")) {
|
|
//if (OB_FAIL(priv_mgr.check_table_show(session_priv,
|
|
if (OB_FAIL(schema_guard_->check_table_show(session_priv, db_name, table_name, passed))) {
|
|
LOG_WARN("Check table show failed", K(ret));
|
|
}
|
|
} else {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Check priv level error", K(ret));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
}// common
|
|
}// oceanbase
|