1490 lines
48 KiB
C++
1490 lines
48 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_table_api_row_iterator.h"
|
|
#include "ob_table_rpc_processor.h"
|
|
#include "observer/ob_service.h"
|
|
#include "sql/ob_sql_utils.h"
|
|
#include "sql/engine/expr/ob_expr_add.h"
|
|
#include "sql/resolver/expr/ob_raw_expr_util.h"
|
|
#include "storage/ob_partition_service.h"
|
|
|
|
using namespace oceanbase::common;
|
|
using namespace oceanbase::table;
|
|
using namespace oceanbase::share;
|
|
using namespace oceanbase::share::schema;
|
|
using namespace oceanbase::sql;
|
|
|
|
|
|
namespace oceanbase {
|
|
namespace observer {
|
|
|
|
/**
|
|
* -------------------------------------------------------ObTableApiRowIterator--------------------------------------------------------
|
|
*/
|
|
ObTableApiRowIterator::ObTableApiRowIterator()
|
|
: part_service_(NULL),
|
|
schema_service_(NULL),
|
|
ctx_(NULL),
|
|
schema_guard_(),
|
|
table_schema_(NULL),
|
|
table_id_(0),
|
|
tenant_id_(0),
|
|
schema_version_(0),
|
|
rowkey_column_cnt_(0),
|
|
properties_(),
|
|
column_ids_(),
|
|
columns_type_(),
|
|
column_descs_(),
|
|
row_objs_(),
|
|
missing_default_objs_(),
|
|
generate_column_exprs_(),
|
|
generate_column_idxs_(),
|
|
expr_ctx_(),
|
|
row_(),
|
|
stmt_allocator_(ObModIds::TABLE_BATCH_OPERATION),
|
|
row_allocator_(ObModIds::TABLE_BATCH_OPERATION),
|
|
entity_(NULL),
|
|
has_generate_column_(false),
|
|
is_inited_(false)
|
|
{
|
|
}
|
|
|
|
ObTableApiRowIterator::~ObTableApiRowIterator()
|
|
{
|
|
if (has_generate_column_) {
|
|
sql::ObSQLUtils::destruct_default_expr_context(expr_ctx_);
|
|
has_generate_column_ = false;
|
|
}
|
|
}
|
|
|
|
int ObTableApiRowIterator::init(
|
|
storage::ObPartitionService &partition_service,
|
|
share::schema::ObMultiVersionSchemaService &schema_service,
|
|
ObTableServiceCtx &ctx)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
|
|
if (is_inited_) {
|
|
ret = OB_INIT_TWICE;
|
|
LOG_WARN("The table api row iterator has been inited, ", K(ret));
|
|
} else if (OB_FAIL(schema_service.get_schema_guard(schema_guard_))) {
|
|
LOG_WARN("failed to get schema guard", K(ret));
|
|
} else if (OB_FAIL(schema_guard_.get_table_schema(ctx.param_.table_id_, table_schema_))) {
|
|
LOG_WARN("get table schema failed", K(ctx.param_.table_id_), K(ret));
|
|
} else if (OB_ISNULL(table_schema_)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_ERROR("NULL ptr", K(ret), K(table_schema_));
|
|
} else if (OB_FAIL(check_table_supported(table_schema_))) {
|
|
LOG_WARN("check table support failed", K(ret));
|
|
} else {
|
|
table_id_ = ctx.param_.table_id_;
|
|
tenant_id_ = extract_tenant_id(table_id_);
|
|
schema_version_ = table_schema_->get_schema_version();
|
|
rowkey_column_cnt_ = table_schema_->get_rowkey_column_num();
|
|
part_service_ = &partition_service;
|
|
ctx_ = &ctx;
|
|
stmt_allocator_.set_tenant_id(tenant_id_);
|
|
row_allocator_.set_tenant_id(tenant_id_);
|
|
is_inited_ = true;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
void ObTableApiRowIterator::reset()
|
|
{
|
|
if (has_generate_column_) {
|
|
sql::ObSQLUtils::destruct_default_expr_context(expr_ctx_);
|
|
}
|
|
part_service_ = NULL;
|
|
schema_service_ = NULL;
|
|
ctx_ = NULL;
|
|
table_schema_ = NULL;
|
|
table_id_ = 0;
|
|
tenant_id_ = 0;
|
|
schema_version_ = 0;
|
|
rowkey_column_cnt_ = 0;
|
|
properties_.reset();
|
|
column_ids_.reset();
|
|
columns_type_.reset();
|
|
column_descs_.reset();
|
|
row_objs_.reset();
|
|
missing_default_objs_.reset();
|
|
generate_column_exprs_.reset();
|
|
generate_column_idxs_.reset();
|
|
stmt_allocator_.reset();
|
|
row_allocator_.reset();
|
|
entity_ = NULL;
|
|
has_generate_column_ = false;
|
|
is_inited_ = false;
|
|
}
|
|
|
|
int ObTableApiRowIterator::check_row(ObNewRow &row)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
const int64_t N = columns_type_.count();
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < N; ++i) {
|
|
if (OB_FAIL(check_column_type(columns_type_.at(i), row.get_cell(i)))) {
|
|
LOG_WARN("Fail to check column type, ", K(ret), K(i), K(columns_type_.at(i)), K(row.get_cell(i)));
|
|
}
|
|
} // end for
|
|
return ret;
|
|
}
|
|
|
|
int ObTableApiRowIterator::entity_to_row(const ObITableEntity &entity, ObIArray<ObObj> &row)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObObj obj;
|
|
const int64_t N = entity.get_rowkey_size();
|
|
row.reuse();
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < N; ++i) {
|
|
if (OB_FAIL(entity.get_rowkey_value(i, obj))) {
|
|
LOG_WARN("failed to get rowkey value", K(ret), K(i));
|
|
} else if (OB_FAIL(row.push_back(obj))) {
|
|
LOG_WARN("failed to push", K(ret), K(i), K(obj));
|
|
}
|
|
} // end for
|
|
if (OB_SUCC(ret)) {
|
|
if (OB_FAIL(entity.get_properties_values(row))) {
|
|
LOG_WARN("failed to get properties values", K(ret));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTableApiRowIterator::fill_get_param(
|
|
ObTableServiceCtx &ctx,
|
|
const ObTableOperationType::Type op_type,
|
|
ObRowkey &rowkey,
|
|
storage::ObTableScanParam &scan_param,
|
|
share::schema::ObTableParam &table_param)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
scan_param.key_ranges_.reset();
|
|
if (OB_FAIL(fill_range(rowkey, scan_param.key_ranges_))) {
|
|
LOG_WARN("Fail to fill range, ", K(ret));
|
|
} else if (OB_FAIL(fill_flag(ctx, scan_param))) {
|
|
LOG_WARN("Fail to fill param flag, ", K(ret));
|
|
} else if (OB_FAIL(table_param.convert(*table_schema_, *table_schema_, column_ids_, false /*index back*/))) {
|
|
LOG_WARN("failed to convert table param", K(ret));
|
|
} else {
|
|
if (ObTableOperationType::DEL == op_type
|
|
|| ObTableOperationType::UPDATE == op_type
|
|
|| ObTableOperationType::INSERT_OR_UPDATE == op_type
|
|
|| ObTableOperationType::REPLACE == op_type
|
|
|| ObTableOperationType::INCREMENT == op_type
|
|
|| ObTableOperationType::APPEND == op_type) {
|
|
scan_param.for_update_ = true;
|
|
}
|
|
scan_param.table_param_ = &table_param;
|
|
LOG_DEBUG("Success to fill get param.");
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTableApiRowIterator::fill_multi_get_param(
|
|
ObTableServiceCtx &ctx,
|
|
const ObTableBatchOperation &batch_operation,
|
|
storage::ObTableScanParam &scan_param,
|
|
share::schema::ObTableParam &table_param)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
scan_param.key_ranges_.reset();
|
|
const int64_t N = batch_operation.count();
|
|
if (N <= 0) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Invalid argument, ", K(ret), K(N));
|
|
}
|
|
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < N; ++i) {
|
|
ObRowkey rowkey = const_cast<ObITableEntity &>(batch_operation.at(i).entity()).get_rowkey();
|
|
if (OB_FAIL(fill_range(rowkey, scan_param.key_ranges_))) {
|
|
LOG_WARN("Fail to fill range, ", K(ret), K(i));
|
|
}
|
|
} // end for
|
|
|
|
if (OB_SUCC(ret)) {
|
|
if (OB_FAIL(fill_flag(ctx, scan_param))) {
|
|
LOG_WARN("Fail to fill param flag, ", K(ret));
|
|
} else if (OB_FAIL(table_param.convert(*table_schema_, *table_schema_, column_ids_, false /*index back*/))) {
|
|
LOG_WARN("failed to convert table param", K(ret));
|
|
} else {
|
|
const ObTableOperation &table_operation = batch_operation.at(0);
|
|
if (ObTableOperationType::DEL == table_operation.type()
|
|
|| ObTableOperationType::UPDATE == table_operation.type()
|
|
|| ObTableOperationType::INSERT_OR_UPDATE == table_operation.type()
|
|
|| ObTableOperationType::REPLACE == table_operation.type()
|
|
|| ObTableOperationType::INCREMENT == table_operation.type()
|
|
|| ObTableOperationType::APPEND == table_operation.type()) {
|
|
scan_param.for_update_ = true;
|
|
}
|
|
scan_param.table_param_ = &table_param;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTableApiRowIterator::fill_generate_columns(common::ObNewRow &row)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObISqlExpression *expr = NULL;
|
|
const int64_t N = generate_column_exprs_.count();
|
|
int64_t col_idx = 0;
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < N; ++i) {
|
|
if (OB_FAIL(generate_column_exprs_.at(i, expr))) {
|
|
LOG_WARN("Fail to get generate column expr, ", K(ret), K(i));
|
|
} else if (OB_FAIL(generate_column_idxs_.at(i, col_idx))) {
|
|
LOG_WARN("Fail to get generate column idx, ", K(ret), K(i));
|
|
} else if (NULL != expr) {
|
|
if (OB_FAIL(sql::ObSQLUtils::calc_sql_expression(
|
|
expr,
|
|
*table_schema_,
|
|
column_descs_,
|
|
row,
|
|
row_allocator_,
|
|
expr_ctx_,
|
|
row.cells_[col_idx]))) {
|
|
LOG_WARN("failed to calc expr from str", K(column_descs_), K(ret));
|
|
} else {
|
|
LOG_DEBUG("Success to calc expr, ", K(col_idx), K(row.cells_[col_idx]));
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
|
|
int ObTableApiRowIterator::cons_all_columns(const ObITableEntity &entity, const bool ignore_missing_column)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
const ObRowkeyInfo &rowkey_info = table_schema_->get_rowkey_info();
|
|
if (OB_FAIL(entity.get_properties_names(properties_))) {
|
|
LOG_WARN("failed to get properties, ", K(ret));
|
|
} else if (OB_FAIL(rowkey_info.get_column_ids(column_ids_))) {
|
|
LOG_WARN("failed to get rowkey column ids", K(ret), K(rowkey_info));
|
|
} else {
|
|
const schema::ObColumnSchemaV2 *column_schema = NULL;
|
|
uint64_t column_id = OB_INVALID_ID;
|
|
|
|
//add rowkey column
|
|
const int64_t rowkey_cnt = rowkey_info.get_size();
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < rowkey_cnt; ++i) {
|
|
if (OB_FAIL(rowkey_info.get_column_id(i, column_id))) {
|
|
LOG_WARN("failed to get column id", K(ret), K(i));
|
|
} else if (NULL == (column_schema = table_schema_->get_column_schema(column_id))) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("rowkey column not exists", K(ret), K(column_id));
|
|
} else if (OB_FAIL(add_column_type(*column_schema))) {
|
|
LOG_WARN("Fail to add column type, ", K(ret));
|
|
}
|
|
} // end for
|
|
|
|
//add property column
|
|
const int64_t property_cnt = properties_.count();
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < property_cnt; ++i) {
|
|
const ObString &cname = properties_.at(i);
|
|
if (NULL == (column_schema = table_schema_->get_column_schema(cname))) {
|
|
ret = OB_ERR_COLUMN_NOT_FOUND;
|
|
LOG_WARN("column not exists", K(ret), K(cname));
|
|
} else if (!ignore_missing_column && column_schema->is_generated_column()) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Should not have generate columns, ", K(ret), K(cname));
|
|
} else if (OB_FAIL(column_ids_.push_back(column_schema->get_column_id()))) {
|
|
LOG_WARN("failed to add column id", K(ret));
|
|
} else if (OB_FAIL(add_column_type(*column_schema))) {
|
|
LOG_WARN("Fail to add column type, ", K(ret));
|
|
}
|
|
} // end for
|
|
|
|
//add missing column
|
|
if (OB_SUCC(ret) && !ignore_missing_column) {
|
|
if (OB_FAIL(cons_missing_columns(entity))) {
|
|
LOG_WARN("Fail to cons missing column, ", K(ret));
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTableApiRowIterator::cons_missing_columns(const ObITableEntity &entity)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
has_generate_column_ = false;
|
|
if (table_schema_->get_column_count() - table_schema_->get_rowkey_column_num() <= entity.get_properties_count()) {
|
|
// no missing columns, do nothing
|
|
} else {
|
|
// some columns are missing
|
|
ObTableSchema::const_column_iterator iter = NULL;
|
|
ObTableSchema::const_column_iterator begin = table_schema_->column_begin();
|
|
ObTableSchema::const_column_iterator end = table_schema_->column_end();
|
|
ObObj obj;
|
|
ObExprResType column_type;
|
|
const schema::ObColumnSchemaV2 *column = NULL;
|
|
for (iter = begin; OB_SUCC(ret) && iter != end; ++iter) {
|
|
column = *iter;
|
|
// skip all rowkeys
|
|
if (OB_ISNULL(column)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("invalid column schema", K(column));
|
|
} else if (!column->is_rowkey_column()) {
|
|
if (OB_FAIL(entity.get_property(column->get_column_name_str(), obj))) {
|
|
ret = OB_SUCCESS;
|
|
// missing column
|
|
obj = column->get_cur_default_value();
|
|
if (OB_FAIL(missing_default_objs_.push_back(obj))) {
|
|
LOG_WARN("Failed to push default obj, ", K(ret));
|
|
} else if (OB_FAIL(column_ids_.push_back(column->get_column_id()))) {
|
|
LOG_WARN("failed to add column id", K(ret));
|
|
} else if (OB_FAIL(add_column_type(*column))) {
|
|
LOG_WARN("Fail to add column type, ", K(ret));
|
|
} else {
|
|
if (column->is_generated_column()) {
|
|
if (OB_FAIL(generate_column_idxs_.push_back(column_ids_.count() - 1))) {
|
|
LOG_WARN("Failed to push generate column idx, ", K(ret));
|
|
}
|
|
has_generate_column_ = true;
|
|
}
|
|
LOG_DEBUG("add missing column", K(obj), K(column_type));
|
|
}
|
|
}
|
|
} else {}
|
|
} //end for
|
|
|
|
//fill generate expression
|
|
if (has_generate_column_) {
|
|
generate_column_exprs_.reuse();
|
|
uint64_t tenant_id = extract_tenant_id(table_schema_->get_table_id());
|
|
if (OB_FAIL(sql::ObSQLUtils::make_default_expr_context(tenant_id, stmt_allocator_, expr_ctx_))) {
|
|
LOG_WARN("failed to make default expr context ", K(ret));
|
|
}
|
|
|
|
for (iter = begin; OB_SUCC(ret) && iter != end; ++iter) {
|
|
column = *iter;
|
|
if (column->is_generated_column()) {
|
|
ObISqlExpression *expr = NULL;
|
|
obj = column->get_orig_default_value();
|
|
if (OB_FAIL(sql::ObSQLUtils::make_generated_expression_from_str(
|
|
obj.get_string(),
|
|
*table_schema_,
|
|
*column,
|
|
column_descs_,
|
|
stmt_allocator_,
|
|
expr))) {
|
|
STORAGE_LOG(WARN,
|
|
"failed to make sql expression",
|
|
K(obj.get_string()),
|
|
K(*table_schema_),
|
|
K(*column),
|
|
K(column_descs_),
|
|
K(ret));
|
|
} else if (OB_FAIL(generate_column_exprs_.push_back(expr))) {
|
|
STORAGE_LOG(WARN, "push back error", K(ret));
|
|
} else {
|
|
/*do nothing*/
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
|
|
int ObTableApiRowIterator::add_column_type(const share::schema::ObColumnSchemaV2 &column_schema)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObExprResType column_type;
|
|
ObColDesc column_desc;
|
|
if (OB_FAIL(cons_column_type(column_schema, column_type))) {
|
|
LOG_WARN("failed to cons column type", K(ret));
|
|
} else if (OB_FAIL(columns_type_.push_back(column_type))) {
|
|
LOG_WARN("failed to push back column type, ", K(ret));
|
|
} else {
|
|
column_desc.col_id_ = column_schema.get_column_id();
|
|
column_desc.col_type_ = column_schema.get_meta_type();
|
|
if (OB_FAIL(column_descs_.push_back(column_desc))) {
|
|
LOG_WARN("failed to push back column desc, ", K(ret));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTableApiRowIterator::cons_column_type(const schema::ObColumnSchemaV2 &column_schema, ObExprResType &column_type)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
column_type.set_type(column_schema.get_data_type());
|
|
column_type.set_result_flag(ObRawExprUtils::calc_column_result_flag(column_schema));
|
|
if (ob_is_string_type(column_schema.get_data_type())) {
|
|
column_type.set_collation_type(column_schema.get_collation_type());
|
|
column_type.set_collation_level(CS_LEVEL_IMPLICIT);
|
|
} else {
|
|
column_type.set_collation_type(CS_TYPE_BINARY);
|
|
column_type.set_collation_level(CS_LEVEL_NUMERIC);
|
|
}
|
|
const ObAccuracy &accuracy = column_schema.get_accuracy();
|
|
column_type.set_accuracy(accuracy);
|
|
const bool is_zerofill = column_type.has_result_flag(ZEROFILL_FLAG);
|
|
if (is_zerofill) {
|
|
ret = OB_NOT_SUPPORTED;
|
|
LOG_WARN("modifing column with ZEROFILL flag is not supported", K(ret), K(column_schema));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
|
|
int ObTableApiRowIterator::check_table_supported(const ObTableSchema *table_schema)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (!table_schema->is_user_table()) {
|
|
ret = OB_NOT_SUPPORTED;
|
|
LOG_WARN("table type not supported", K(ret),
|
|
"table_name", table_schema->get_table_name_str(),
|
|
"type", table_schema->get_table_type());
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTableApiRowIterator::check_column_type(const ObExprResType &column_type, ObObj &obj)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
const bool is_not_nullable = column_type.has_result_flag(NOT_NULL_FLAG);
|
|
const ObCollationType cs_type = column_type.get_collation_type();
|
|
// 1. check nullable
|
|
if (is_not_nullable && obj.is_null()) {
|
|
ret = OB_BAD_NULL_ERROR;
|
|
} else if (obj.is_null()) {
|
|
// continue
|
|
} else if (column_type.get_type() != obj.get_type()
|
|
&& !(ob_is_string_type(column_type.get_type()) && ob_is_string_type(obj.get_type()))) {
|
|
// 2. data type mismatch
|
|
ret = OB_OBJ_TYPE_ERROR;
|
|
LOG_WARN("object type mismatch with column type", K(ret), K(column_type), K(obj));
|
|
} else {
|
|
// 3. check collation
|
|
if (!ob_is_string_type(obj.get_type())) {
|
|
// not string type, continue
|
|
} else {
|
|
if (cs_type == obj.get_collation_type()) {
|
|
// same collation type
|
|
} else if (cs_type == CS_TYPE_BINARY) {
|
|
// any collation type can be compatible with cs_type_binary
|
|
obj.set_collation_type(cs_type);
|
|
} else if (ObCharset::charset_type_by_coll(cs_type) == ObCharset::charset_type_by_coll(obj.get_collation_type())) {
|
|
// same charset, convert it
|
|
obj.set_collation_type(cs_type);
|
|
} else {
|
|
ret = OB_ERR_COLLATION_MISMATCH;
|
|
LOG_WARN("collation type mismatch with column", K(ret), K(column_type), K(obj));
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
// convert obj type to the column type (char, varchar or text)
|
|
obj.set_type(column_type.get_type());
|
|
}
|
|
}
|
|
// 4. check accuracy
|
|
if (OB_SUCC(ret)) {
|
|
if (OB_FAIL(ob_obj_accuracy_check_only(column_type.get_accuracy(), cs_type, obj))) {
|
|
LOG_WARN("accuracy check failed", K(ret), K(obj), K(column_type));
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
|
|
int ObTableApiRowIterator::fill_range(const ObRowkey &key, ObIArray<common::ObNewRange> &ranges)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObNewRange range;
|
|
|
|
if (key.get_obj_cnt() > rowkey_column_cnt_) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("wrong rowkey size", K(ret), K(key), K(columns_type_));
|
|
} else {
|
|
const int64_t N = key.get_obj_cnt();
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < N; ++i) {
|
|
if (OB_FAIL(check_column_type(columns_type_.at(i), const_cast<ObObj&> (key.get_obj_ptr()[i])))) {
|
|
LOG_WARN("Invalid column type, ", K(ret), K(i), K(columns_type_.at(i)), K(key.get_obj_ptr()[i]));
|
|
}
|
|
}
|
|
|
|
if (OB_SUCC(ret)) {
|
|
if (OB_FAIL(range.build_range(table_id_, key))) {
|
|
LOG_WARN("fail to build key range", K(ret), K_(table_id), K(key));
|
|
} else if (OB_FAIL(ranges.push_back(range))) {
|
|
LOG_WARN("fail to push back key range", K(ret), K(range));
|
|
} else {
|
|
}
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObTableApiRowIterator::fill_flag(ObTableServiceCtx &ctx, storage::ObTableScanParam &scan_param)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
const uint64_t table_id = ctx.param_.table_id_;
|
|
ObPartitionKey part_key(table_id, ctx.param_.partition_id_, 0);
|
|
scan_param.timeout_ = ctx.param_.timeout_ts_;
|
|
ObQueryFlag query_flag(ObQueryFlag::KeepOrder, // scan_order KeepOrder!
|
|
false, // daily_merge
|
|
false, // optimize
|
|
false, // whole_macro_scan
|
|
false, // full_row
|
|
false, // index_back
|
|
false, // query_stat
|
|
ObQueryFlag::MysqlMode, // sql_mode
|
|
true // read_latest
|
|
);
|
|
scan_param.scan_flag_.flag_ = query_flag.flag_;
|
|
scan_param.reserved_cell_count_ = column_ids_.count() + 10;
|
|
scan_param.for_update_ = false;
|
|
scan_param.column_ids_.reset();
|
|
scan_param.pkey_ = part_key;
|
|
scan_param.schema_version_ = schema_version_;
|
|
if (OB_FAIL(scan_param.column_ids_.assign(column_ids_))) {
|
|
LOG_WARN("fail to assign column id", K(ret));
|
|
} else {
|
|
scan_param.expr_ctx_.calc_buf_ = NULL;
|
|
scan_param.expr_ctx_.my_session_ = NULL;
|
|
scan_param.expr_ctx_.phy_plan_ctx_ = NULL;
|
|
scan_param.limit_param_.limit_ = -1;
|
|
scan_param.limit_param_.offset_ = 0;
|
|
scan_param.trans_desc_ = &(ctx.param_.processor_->get_trans_desc());
|
|
scan_param.index_id_ = table_id_;
|
|
scan_param.sql_mode_ = SMO_DEFAULT;
|
|
scan_param.allocator_->set_tenant_id(scan_param.pkey_.get_tenant_id());
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* ------------------------------------------------------------------ObTableApiInsertRowIterator---------------------------------------------------------
|
|
*/
|
|
ObTableApiInsertRowIterator::ObTableApiInsertRowIterator()
|
|
{
|
|
}
|
|
|
|
ObTableApiInsertRowIterator::~ObTableApiInsertRowIterator()
|
|
{
|
|
}
|
|
|
|
int ObTableApiInsertRowIterator::open(const ObTableOperation &table_operation)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (!is_inited_) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("The table api insert row iterator has not been inited, ", K(ret));
|
|
} else if (OB_FAIL(cons_all_columns(table_operation.entity()))) {
|
|
LOG_WARN("Fail to construct all columns, ", K(ret));
|
|
} else {
|
|
entity_ = &(table_operation.entity());
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTableApiInsertRowIterator::get_next_row(ObNewRow *&row)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
row_allocator_.reuse();
|
|
if (OB_ISNULL(entity_)) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("The entity is null, ", K(ret));
|
|
} else if (OB_FAIL(cons_row(*entity_, row))) {
|
|
LOG_WARN("Fail to construct insert row, ", K(ret));
|
|
} else {
|
|
//success
|
|
LOG_DEBUG("Api insert row iter, ", K(*row));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTableApiInsertRowIterator::cons_row(const table::ObITableEntity &entity, common::ObNewRow *&row)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_FAIL(entity_to_row(entity, row_objs_))) {
|
|
LOG_WARN("Fail to generate row from entity, ", K(ret));
|
|
} else {
|
|
const int64_t N = missing_default_objs_.count();
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < N; i++) {
|
|
if (OB_FAIL(row_objs_.push_back(missing_default_objs_.at(i)))) {
|
|
LOG_WARN("Fail to push default value to row, ", K(ret));
|
|
}
|
|
}
|
|
|
|
if (OB_SUCC(ret)) {
|
|
row_.assign(&row_objs_.at(0), row_objs_.count());
|
|
if (has_generate_column_ && OB_FAIL(fill_generate_columns(row_))) {
|
|
LOG_WARN("Fail to fill generate columns, ", K(ret));
|
|
}
|
|
}
|
|
|
|
if (OB_SUCC(ret)) {
|
|
if (OB_FAIL(check_row(row_))) {
|
|
LOG_WARN("Fail to check row, ", K(ret), K_(row));
|
|
} else {
|
|
row = &row_;
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
|
|
/**
|
|
* ------------------------------------------------------------------ObTableApiMultiInsertRowIterator---------------------------------------------------------
|
|
*/
|
|
ObTableApiMultiInsertRowIterator::ObTableApiMultiInsertRowIterator()
|
|
: batch_operation_(NULL),
|
|
row_idx_(0),
|
|
batch_cnt_(0),
|
|
is_iter_pause_(false)
|
|
{
|
|
}
|
|
|
|
ObTableApiMultiInsertRowIterator::~ObTableApiMultiInsertRowIterator()
|
|
{
|
|
}
|
|
|
|
void ObTableApiMultiInsertRowIterator::reset()
|
|
{
|
|
batch_operation_ = NULL;
|
|
row_idx_ = 0;
|
|
batch_cnt_ = 0;
|
|
is_iter_pause_ = false;
|
|
ObTableApiInsertRowIterator::reset();
|
|
}
|
|
|
|
int ObTableApiMultiInsertRowIterator::open(const ObTableBatchOperation &batch_operation)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (!is_inited_) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("The table api multi insert iterator has not been inited, ", K(ret));
|
|
} else if (OB_UNLIKELY(batch_operation.count() <= 0)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Invalid argument, ", K(ret), K(batch_operation.count()));
|
|
} else if (OB_FAIL(cons_all_columns(batch_operation.at(0).entity()))) {
|
|
LOG_WARN("Fail to construct all columns, ", K(ret));
|
|
} else {
|
|
batch_operation_ = &batch_operation;
|
|
row_idx_ = 0;
|
|
batch_cnt_ = batch_operation.count();
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTableApiMultiInsertRowIterator::get_next_row(common::ObNewRow *&row)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
row_allocator_.reuse();
|
|
if (OB_ISNULL(batch_operation_)) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("The table api multi insert row iterator has not been inited, ", K(ret));
|
|
} else if (row_idx_ >= batch_cnt_ || is_iter_pause_) {
|
|
ret = OB_ITER_END;
|
|
} else if (OB_FAIL(cons_row(batch_operation_->at(row_idx_).entity(), row))) {
|
|
LOG_WARN("Fail to construct row, ", K(ret), K(row_idx_));
|
|
} else {
|
|
row_idx_++;
|
|
is_iter_pause_ = true;
|
|
LOG_DEBUG("Api insert row iter, ", K(*row), K_(row_idx));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
|
|
/**
|
|
* ------------------------------------------------------------------ObTableApiUpdateRowIterator---------------------------------------------------------
|
|
*/
|
|
ObTableApiUpdateRowIterator::ObTableApiUpdateRowIterator()
|
|
: scan_param_(),
|
|
table_param_(stmt_allocator_),
|
|
update_column_ids_(),
|
|
scan_iter_(NULL),
|
|
old_row_(NULL),
|
|
new_row_(NULL),
|
|
row_idx_(0),
|
|
need_update_rowkey_(false),
|
|
table_operation_(NULL)
|
|
{
|
|
}
|
|
|
|
ObTableApiUpdateRowIterator::~ObTableApiUpdateRowIterator()
|
|
{
|
|
if (NULL != scan_iter_) {
|
|
if (NULL != part_service_) {
|
|
part_service_->revert_scan_iter(scan_iter_);
|
|
scan_iter_ = NULL;
|
|
} else {
|
|
LOG_ERROR("The part service is NULL, but the scan iter is NOT NULL!");
|
|
}
|
|
}
|
|
}
|
|
|
|
void ObTableApiUpdateRowIterator::reset()
|
|
{
|
|
if (NULL != scan_iter_) {
|
|
if (NULL != part_service_) {
|
|
part_service_->revert_scan_iter(scan_iter_);
|
|
scan_iter_ = NULL;
|
|
} else {
|
|
LOG_ERROR("The part service is NULL, but the scan iter is NOT NULL!");
|
|
}
|
|
}
|
|
scan_param_.destroy();
|
|
table_param_.reset();
|
|
update_column_ids_.reset();
|
|
old_row_ = NULL;
|
|
new_row_ = NULL;
|
|
row_idx_ = 0;
|
|
ObTableApiRowIterator::reset();
|
|
}
|
|
|
|
int ObTableApiUpdateRowIterator::open(const ObTableOperation &table_operation,
|
|
const ObRowkey &rowkey, bool need_update_rowkey/* = false */)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (!is_inited_) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("The table api update row iterator has not been inited, ", K(ret));
|
|
} else if (OB_FAIL(cons_all_columns(table_operation.entity()))) {
|
|
LOG_WARN("Fail to construct all columns, ", K(ret));
|
|
} else if (OB_FAIL(cons_update_columns(need_update_rowkey))) {
|
|
LOG_WARN("Fail to construct update columns, ", K(ret));
|
|
} else if (OB_FAIL(fill_get_param(*ctx_,
|
|
table_operation.type(), const_cast<ObRowkey &>(rowkey), scan_param_, table_param_))) {
|
|
LOG_WARN("Fail to fill get param, ", K(ret));
|
|
} else if (OB_FAIL(part_service_->table_scan(scan_param_, scan_iter_))) {
|
|
if (OB_TRY_LOCK_ROW_CONFLICT != ret) {
|
|
LOG_WARN("fail to scan table", K(ret));
|
|
}
|
|
} else {
|
|
table_operation_ = &table_operation;
|
|
old_row_ = NULL;
|
|
new_row_ = NULL;
|
|
row_idx_ = 0;
|
|
need_update_rowkey_ = need_update_rowkey;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTableApiUpdateRowIterator::get_next_row(ObNewRow *&row)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (!is_inited_) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("The table api update row iterator has not been inited, ", K(ret));
|
|
} else if (OB_ISNULL(scan_iter_)) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("The table api update row iterator has not been opened, ", K(ret));
|
|
} else {
|
|
if (0 == row_idx_ % 2) {
|
|
if (OB_FAIL(scan_iter_->get_next_row(row))) {
|
|
if (OB_ITER_END != ret) {
|
|
LOG_WARN("Fail to get next row, ", K(ret));
|
|
} else {
|
|
LOG_DEBUG("Update row iter end, ", K_(row_idx), K(scan_param_));
|
|
}
|
|
} else {
|
|
old_row_ = row;
|
|
LOG_DEBUG("Update old row, ", K_(row_idx), K(*old_row_));
|
|
}
|
|
} else if (OB_FAIL(cons_new_row(*table_operation_, row))) {
|
|
LOG_WARN("Fail to construct new row, ", K(ret));
|
|
} else {
|
|
new_row_ = row;
|
|
LOG_DEBUG("Update iter cons new row, ", K_(row_idx), K(*new_row_));
|
|
}
|
|
|
|
if (OB_SUCC(ret)) {
|
|
row_idx_++;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTableApiUpdateRowIterator::cons_update_columns(bool need_update_rowkey)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
update_column_ids_.reuse();
|
|
if (OB_UNLIKELY(column_ids_.count() <= 0)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("The column id array is empty, ", K(ret), K(column_ids_.count()));
|
|
} else {
|
|
const int64_t N = column_ids_.count() - missing_default_objs_.count();
|
|
int64_t begin_column_idx = need_update_rowkey ? 0 : rowkey_column_cnt_;
|
|
for (int64_t i = begin_column_idx; OB_SUCC(ret) && i < N; i++) {
|
|
if (OB_FAIL(update_column_ids_.push_back(column_ids_.at(i)))) {
|
|
LOG_WARN("Fail to push column id to update column ids array, ", K(ret));
|
|
}
|
|
}
|
|
|
|
if (OB_SUCC(ret) && has_generate_column_) {
|
|
const int64_t gen_col_cnt = generate_column_idxs_.count();
|
|
uint64_t column_id = 0;
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < gen_col_cnt; ++i) {
|
|
if (OB_FAIL(column_ids_.at(generate_column_idxs_.at(i), column_id))) {
|
|
LOG_WARN("Fail to get ith col id, ", K(ret), K(i));
|
|
} else if (OB_FAIL(update_column_ids_.push_back(column_id))) {
|
|
LOG_WARN("Fail to push generate column id to update column ids array, ", K(ret), K(i), K(column_id));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTableApiUpdateRowIterator::cons_new_row(const ObTableOperation &table_operation, common::ObNewRow *&row)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
row_objs_.reuse();
|
|
if (OB_FAIL(entity_to_row(table_operation.entity(), row_objs_))) {
|
|
LOG_WARN("Fail to generate row from entity, ", K(ret));
|
|
} else {
|
|
const int64_t rowkey_col_cnt = table_operation.entity().get_rowkey_size();
|
|
const int64_t base_col_cnt = row_objs_.count();
|
|
ObTableOperationType::Type type = table_operation.type();
|
|
|
|
switch(type) {
|
|
case ObTableOperationType::GET:
|
|
case ObTableOperationType::INSERT:
|
|
case ObTableOperationType::DEL:
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_ERROR("invalid operation type", K(ret), K(type));
|
|
break;
|
|
case ObTableOperationType::UPDATE:
|
|
case ObTableOperationType::INSERT_OR_UPDATE:
|
|
case ObTableOperationType::REPLACE:
|
|
//nothing to do
|
|
break;
|
|
case ObTableOperationType::INCREMENT: {
|
|
for (int64_t i = rowkey_col_cnt; OB_SUCC(ret) && i < base_col_cnt; ++i) {
|
|
if (OB_FAIL(obj_increment(row_objs_.at(i), old_row_->cells_[i], columns_type_.at(i), row_objs_.at(i)))) {
|
|
LOG_WARN("failed to increment", K(ret), K(i), K(row_objs_.at(i)), K(old_row_->cells_[i]));
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case ObTableOperationType::APPEND: {
|
|
for (int64_t i = rowkey_col_cnt; OB_SUCC(ret) && i < base_col_cnt; ++i) {
|
|
if (OB_FAIL(obj_append(row_objs_.at(i), old_row_->cells_[i], columns_type_.at(i), row_objs_.at(i)))) {
|
|
LOG_WARN("failed to append", K(ret), K(i), K(row_objs_.at(i)), K(old_row_->cells_[i]));
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_ERROR("invalid operation type", K(ret), K(type));
|
|
break;
|
|
}
|
|
|
|
if (OB_SUCC(ret) && !need_update_rowkey_) {
|
|
const int64_t N = rowkey_col_cnt;
|
|
for (int64_t i = 0; i < N; ++i) {
|
|
row_objs_[i] = old_row_->cells_[i];
|
|
}
|
|
}
|
|
|
|
if (OB_SUCC(ret)) {
|
|
//fill default columns
|
|
const int64_t N = missing_default_objs_.count();
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < N; ++i) {
|
|
if (OB_FAIL(row_objs_.push_back(old_row_->cells_[base_col_cnt + i]))) {
|
|
LOG_WARN("Fail to push back old row obj to new row, ", K(ret));
|
|
}
|
|
}
|
|
}
|
|
|
|
if (OB_SUCC(ret)) {
|
|
//fill generate columns
|
|
row_.assign(&row_objs_.at(0), row_objs_.count());
|
|
if (has_generate_column_ && OB_FAIL(fill_generate_columns(row_))) {
|
|
LOG_WARN("Fail to fill generate columns, ", K(ret));
|
|
}
|
|
}
|
|
|
|
if (OB_SUCC(ret)) {
|
|
if (OB_FAIL(check_row(row_))) {
|
|
LOG_WARN("Fail to check new row, ", K(ret));
|
|
}
|
|
}
|
|
}
|
|
|
|
if (OB_SUCC(ret)) {
|
|
row = &row_;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
|
|
int ObTableApiUpdateRowIterator::obj_increment(
|
|
const common::ObObj &delta,
|
|
const common::ObObj &src,
|
|
const sql::ObExprResType target_type,
|
|
common::ObObj &target)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_LIKELY(ob_is_int_tc(delta.get_type()))) {
|
|
int64_t delta_int = delta.get_int();
|
|
ObObjType src_type = src.get_type();
|
|
switch (src_type) {
|
|
case ObNullType: {
|
|
// the result is set to delta when src is NULL
|
|
ObObjType result_type = target_type.get_type();
|
|
if (ob_is_int_tc(result_type)) {
|
|
ret = int_add_int_with_check(0, delta_int, result_type, target);
|
|
} else if (ob_is_uint_tc(result_type)) {
|
|
ret = uint_add_int_with_check(0, delta_int, result_type, target);
|
|
} else {
|
|
ret = OB_OBJ_TYPE_ERROR;
|
|
}
|
|
break;
|
|
}
|
|
case ObTinyIntType:
|
|
case ObSmallIntType:
|
|
case ObMediumIntType:
|
|
case ObInt32Type:
|
|
case ObIntType: {
|
|
// signed := signed + signed
|
|
ret = int_add_int_with_check(src.get_int(), delta_int, src_type, target);
|
|
break;
|
|
}
|
|
case ObUTinyIntType:
|
|
case ObUSmallIntType:
|
|
case ObUMediumIntType:
|
|
case ObUInt32Type:
|
|
case ObUInt64Type: {
|
|
// unsigned := usigned + signed
|
|
ret = uint_add_int_with_check(src.get_uint64(), delta_int, src_type, target);
|
|
break;
|
|
}
|
|
default:
|
|
ret = OB_OBJ_TYPE_ERROR;
|
|
break;
|
|
} // end switch
|
|
} else {
|
|
ret = OB_OBJ_TYPE_ERROR;
|
|
LOG_WARN("delta should only be signed integer type", K(ret), K(delta));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTableApiUpdateRowIterator::obj_append(
|
|
const common::ObObj &delta,
|
|
const common::ObObj &src,
|
|
const sql::ObExprResType target_type,
|
|
common::ObObj &target)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (delta.is_null()) {
|
|
ret = OB_OBJ_TYPE_ERROR;
|
|
LOG_WARN("append NULL is illegal", K(ret), K(delta));
|
|
} else if (OB_UNLIKELY(ObVarcharType != delta.get_type())) {
|
|
ret = OB_OBJ_TYPE_ERROR;
|
|
LOG_WARN("can only append varchar/varbinary type", K(ret), K(delta));
|
|
} else {
|
|
const char *result_ptr = NULL;
|
|
int32_t result_len = 0;
|
|
|
|
if (src.is_null()) {
|
|
// the result is set the delta when src is NULL
|
|
if (OB_UNLIKELY(ObVarcharType != target_type.get_type())
|
|
&& OB_UNLIKELY(ObTextTC != ob_obj_type_class(target_type.get_type()))) {
|
|
ret = OB_OBJ_TYPE_ERROR;
|
|
LOG_WARN("can only appended to string type", K(ret), K(target_type));
|
|
} else {
|
|
result_ptr = delta.get_string_ptr();
|
|
result_len = delta.get_string_len();
|
|
}
|
|
} else if (OB_UNLIKELY(ObVarcharType != src.get_type())
|
|
&& OB_UNLIKELY(ObTextTC != ob_obj_type_class(src.get_type()))) {
|
|
ret = OB_OBJ_TYPE_ERROR;
|
|
LOG_WARN("can only appended to string type", K(ret), K(src));
|
|
} else {
|
|
const int32_t len1 = src.get_string_len();
|
|
const int32_t len2 = delta.get_string_len();
|
|
const int32_t total_len = len1 + len2;
|
|
// the actual length will be checked in ObTableOperationTypeChecker
|
|
if (len1 <= 0) {
|
|
result_ptr = delta.get_string_ptr();
|
|
result_len = delta.get_string_len();
|
|
} else if (len2 <= 0) {
|
|
target = src;
|
|
result_len = -1; // no need to set the target
|
|
} else {
|
|
char *buf = NULL;
|
|
if (OB_ISNULL(buf = static_cast<char*>(row_allocator_.alloc(total_len)))) {
|
|
ret = OB_ALLOCATE_MEMORY_FAILED;
|
|
LOG_ERROR("alloc memory failed", K(ret), K(total_len));
|
|
} else {
|
|
MEMCPY(buf, src.get_string_ptr(), len1);
|
|
MEMCPY(buf + len1, delta.get_string_ptr(), len2);
|
|
result_ptr = buf;
|
|
result_len = total_len;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (OB_SUCC(ret) && result_len >= 0) {
|
|
if (ob_is_text_tc(target_type.get_type())) { // LOB
|
|
target.set_lob_value(target_type.get_type(), result_ptr, result_len);
|
|
target.set_meta_type(target_type);
|
|
} else { // Varchar/Varbinary
|
|
target.set_varchar_value(result_ptr, result_len);
|
|
target.set_meta_type(target_type);
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTableApiUpdateRowIterator::int_add_int_with_check(
|
|
int64_t old_int,
|
|
int64_t delta_int,
|
|
common::ObObjType result_type,
|
|
common::ObObj &result)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
int64_t result_int = old_int + delta_int;
|
|
if (sql::ObExprAdd::is_int_int_out_of_range(old_int, delta_int, result_int)) {
|
|
ret = OB_DATA_OUT_OF_RANGE;
|
|
LOG_WARN("result of increment out of range", K(ret),
|
|
K(delta_int), K(old_int), K(result_int));
|
|
} else if (result_int < INT_MIN_VAL[result_type]
|
|
|| result_int > INT_MAX_VAL[result_type]) {
|
|
ret = OB_DATA_OUT_OF_RANGE;
|
|
LOG_WARN("result of increment out of range", K(ret),
|
|
K(delta_int), K(old_int), K(result_int),
|
|
"min", INT_MIN_VAL[result_type],
|
|
"max", INT_MAX_VAL[result_type]);
|
|
} else {
|
|
result.set_type(result_type);
|
|
result.set_int_value(result_int);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
|
|
int ObTableApiUpdateRowIterator::uint_add_int_with_check(
|
|
uint64_t old_uint,
|
|
int64_t delta_int,
|
|
common::ObObjType result_type,
|
|
common::ObObj &result)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
uint64_t result_uint = old_uint + delta_int;
|
|
if (sql::ObExprAdd::is_int_uint_out_of_range(delta_int, old_uint, result_uint)) {
|
|
ret = OB_DATA_OUT_OF_RANGE;
|
|
LOG_WARN("result of increment out of range", K(ret),
|
|
K(delta_int), K(old_uint), K(result_uint));
|
|
} else if (result_uint > UINT_MAX_VAL[result_type]) {
|
|
ret = OB_DATA_OUT_OF_RANGE;
|
|
LOG_WARN("result of increment out of range", K(ret),
|
|
K(delta_int), K(old_uint), K(result_uint),
|
|
"max", UINT_MAX_VAL[result_type]);
|
|
} else {
|
|
result.set_type(result_type);
|
|
result.set_uint64_value(result_uint);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* ------------------------------------------------------------------ObTableApiMultiUpdateRowIterator---------------------------------------------------------
|
|
*/
|
|
ObTableApiMultiUpdateRowIterator::ObTableApiMultiUpdateRowIterator()
|
|
: batch_operation_(NULL),
|
|
batch_cnt_(0),
|
|
batch_idx_(0),
|
|
cur_update_idx_(-1),
|
|
is_iter_pause_(false)
|
|
{
|
|
}
|
|
|
|
ObTableApiMultiUpdateRowIterator::~ObTableApiMultiUpdateRowIterator()
|
|
{
|
|
}
|
|
|
|
void ObTableApiMultiUpdateRowIterator::reset()
|
|
{
|
|
batch_operation_ = NULL;
|
|
batch_cnt_ = 0;
|
|
batch_idx_ = 0;
|
|
cur_update_idx_ = -1;
|
|
is_iter_pause_ = false;
|
|
ObTableApiUpdateRowIterator::reset();
|
|
}
|
|
|
|
int ObTableApiMultiUpdateRowIterator::open(const ObTableBatchOperation &batch_operation)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (!is_inited_) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("The table api update row iterator has not been inited, ", K(ret));
|
|
} else if (OB_FAIL(cons_all_columns(batch_operation.at(0).entity()))) {
|
|
LOG_WARN("Fail to construct all columns, ", K(ret));
|
|
} else if (OB_FAIL(cons_update_columns(false/*need_update_rowkey*/))) {
|
|
LOG_WARN("Fail to construct update columns, ", K(ret));
|
|
} else if (OB_FAIL(fill_multi_get_param(*ctx_, batch_operation, scan_param_, table_param_))) {
|
|
LOG_WARN("Fail to fill get param, ", K(ret));
|
|
} else if (OB_FAIL(part_service_->table_scan(scan_param_, scan_iter_))) {
|
|
if (OB_TRY_LOCK_ROW_CONFLICT != ret) {
|
|
LOG_WARN("fail to scan table", K(ret));
|
|
}
|
|
} else {
|
|
batch_operation_ = &batch_operation;
|
|
batch_cnt_ = batch_operation.count();
|
|
batch_idx_ = 0;
|
|
cur_update_idx_ = -1;
|
|
is_iter_pause_ = false;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTableApiMultiUpdateRowIterator::get_next_row(ObNewRow *&row)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (!is_inited_) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("The table api update row iterator has not been inited, ", K(ret));
|
|
} else if (OB_ISNULL(batch_operation_)) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("The table api update row iterator has not been opened, ", K(ret));
|
|
} else if (batch_idx_ >= batch_cnt_ || is_iter_pause_) {
|
|
ret = OB_ITER_END;
|
|
} else {
|
|
row_allocator_.reuse();
|
|
if (0 == row_idx_ % 2) {
|
|
if (OB_FAIL(scan_iter_->get_next_row(row))) {
|
|
if (OB_ITER_END != ret) {
|
|
LOG_WARN("Fail to scan next row, ", K(ret), K_(row_idx));
|
|
} else {
|
|
batch_idx_ = batch_cnt_;
|
|
}
|
|
old_row_ = NULL;
|
|
} else {
|
|
old_row_ = row;
|
|
}
|
|
} else {
|
|
ObRowkey old_row_key(old_row_->cells_, rowkey_column_cnt_);
|
|
row = NULL;
|
|
while(batch_idx_ < batch_cnt_) {
|
|
entity_ = &(batch_operation_->at(batch_idx_).entity());
|
|
if (old_row_key.simple_equal((const_cast<ObITableEntity*>(entity_))->get_rowkey())) {
|
|
break;
|
|
} else {
|
|
batch_idx_++;
|
|
}
|
|
}
|
|
|
|
if (batch_idx_ < batch_cnt_) {
|
|
if (OB_FAIL(cons_new_row(batch_operation_->at(batch_idx_), row))) {
|
|
LOG_WARN("Fail to construct new row, ", K(ret));
|
|
} else {
|
|
cur_update_idx_ = batch_idx_;
|
|
batch_idx_++;
|
|
is_iter_pause_ = true;
|
|
}
|
|
} else {
|
|
ret = OB_ITER_END;
|
|
}
|
|
}
|
|
|
|
if (OB_SUCC(ret)) {
|
|
row_idx_++;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
|
|
/**
|
|
* ------------------------------------------------------------------ObTableApiDeleteRowIterator---------------------------------------------------------
|
|
*/
|
|
ObTableApiDeleteRowIterator::ObTableApiDeleteRowIterator()
|
|
: scan_param_(),
|
|
table_param_(stmt_allocator_),
|
|
scan_iter_(NULL)
|
|
{
|
|
}
|
|
|
|
ObTableApiDeleteRowIterator::~ObTableApiDeleteRowIterator()
|
|
{
|
|
if (NULL != scan_iter_) {
|
|
if (NULL != part_service_) {
|
|
part_service_->revert_scan_iter(scan_iter_);
|
|
scan_iter_ = NULL;
|
|
} else {
|
|
LOG_ERROR("The part service is NULL, but the scan iter is NOT NULL!");
|
|
}
|
|
}
|
|
}
|
|
|
|
void ObTableApiDeleteRowIterator::reset()
|
|
{
|
|
if (NULL != scan_iter_) {
|
|
if (NULL != part_service_) {
|
|
part_service_->revert_scan_iter(scan_iter_);
|
|
scan_iter_ = NULL;
|
|
} else {
|
|
LOG_ERROR("The part service is NULL, but the scan iter is NOT NULL!");
|
|
}
|
|
}
|
|
scan_param_.destroy();
|
|
table_param_.reset();
|
|
|
|
ObTableApiRowIterator::reset();
|
|
}
|
|
|
|
int ObTableApiDeleteRowIterator::open(const ObTableOperation &table_operation)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObRowkey rowkey = const_cast<ObITableEntity &>(table_operation.entity()).get_rowkey();
|
|
if (!is_inited_) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("The table api update row iterator has not been inited, ", K(ret));
|
|
} else if (OB_FAIL(cons_all_columns(table_operation.entity()))) {
|
|
LOG_WARN("Fail to construct all columns, ", K(ret));
|
|
} else if (OB_FAIL(fill_get_param(*ctx_, table_operation.type(), rowkey,
|
|
scan_param_, table_param_))) {
|
|
LOG_WARN("Fail to fill get param, ", K(ret));
|
|
} else if (OB_FAIL(part_service_->table_scan(scan_param_, scan_iter_))) {
|
|
if (OB_TRY_LOCK_ROW_CONFLICT != ret) {
|
|
LOG_WARN("fail to scan table", K(ret));
|
|
}
|
|
} else {
|
|
entity_ = &(table_operation.entity());
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTableApiDeleteRowIterator::get_next_row(common::ObNewRow *&row)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (NULL == scan_iter_) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("The delete row iterator has not been inited, ", K(ret));
|
|
} else {
|
|
if (OB_FAIL(scan_iter_->get_next_row(row))) {
|
|
if (OB_ITER_END != ret) {
|
|
LOG_WARN("Fail to get next delete row, ", K(ret));
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* ------------------------------------------------------------------ObTableApiMultiDeleteRowIterator---------------------------------------------------------
|
|
*/
|
|
ObTableApiMultiDeleteRowIterator::ObTableApiMultiDeleteRowIterator()
|
|
: batch_operation_(NULL),
|
|
batch_cnt_(0),
|
|
batch_idx_(0),
|
|
cur_delete_idx_(-1),
|
|
is_iter_pause_(false)
|
|
{
|
|
}
|
|
|
|
ObTableApiMultiDeleteRowIterator::~ObTableApiMultiDeleteRowIterator()
|
|
{
|
|
}
|
|
|
|
void ObTableApiMultiDeleteRowIterator::reset()
|
|
{
|
|
batch_operation_ = NULL;
|
|
batch_cnt_ = 0;
|
|
batch_idx_ = 0;
|
|
cur_delete_idx_ = -1;
|
|
is_iter_pause_ = false;
|
|
ObTableApiDeleteRowIterator::reset();
|
|
}
|
|
|
|
int ObTableApiMultiDeleteRowIterator::open(const ObTableBatchOperation &batch_operation)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (!is_inited_) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("The multi delte row iterator has not been inited, ", K(ret));
|
|
} else if (OB_FAIL(cons_all_columns(batch_operation.at(0).entity()))) {
|
|
LOG_WARN("Fail to construct all columns, ", K(ret));
|
|
} else if (OB_FAIL(fill_multi_get_param(*ctx_, batch_operation, scan_param_, table_param_))) {
|
|
LOG_WARN("Fail to fill multi get param, ", K(ret));
|
|
} else if (OB_FAIL(part_service_->table_scan(scan_param_, scan_iter_))) {
|
|
if (OB_TRY_LOCK_ROW_CONFLICT != ret) {
|
|
LOG_WARN("fail to scan table", K(ret));
|
|
}
|
|
} else {
|
|
batch_operation_ = &batch_operation;
|
|
batch_cnt_ = batch_operation.count();
|
|
batch_idx_ = 0;
|
|
cur_delete_idx_ = -1;
|
|
is_iter_pause_ = false;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTableApiMultiDeleteRowIterator::get_next_row(ObNewRow *&row)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
row = NULL;
|
|
if (!is_inited_) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("The table api multi delete row iterator has not been inited, ", K(ret));
|
|
} else if (OB_ISNULL(batch_operation_)) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("The table api multi delete row iterator has not been opened, ", K(ret));
|
|
} else if (batch_idx_ >= batch_cnt_ || is_iter_pause_) {
|
|
ret = OB_ITER_END;
|
|
} else {
|
|
if (OB_FAIL(scan_iter_->get_next_row(row))) {
|
|
if (OB_ITER_END != ret) {
|
|
LOG_WARN("Fail to get next delete row, ", K(ret));
|
|
} else {
|
|
batch_idx_ = batch_cnt_;
|
|
}
|
|
} else {
|
|
ObRowkey row_key(row->cells_, rowkey_column_cnt_);
|
|
while(batch_idx_ < batch_cnt_) {
|
|
entity_ = &(batch_operation_->at(batch_idx_).entity());
|
|
if (row_key.simple_equal((const_cast<ObITableEntity*>(entity_))->get_rowkey())) {
|
|
cur_delete_idx_ = batch_idx_;
|
|
break;
|
|
} else {
|
|
batch_idx_++;
|
|
}
|
|
}
|
|
batch_idx_++;
|
|
is_iter_pause_ = true;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
/**
|
|
* ------------------------------------------------------------------ObTableApiGetRowIterator---------------------------------------------------------
|
|
*/
|
|
ObTableApiGetRowIterator::ObTableApiGetRowIterator()
|
|
: scan_param_(),
|
|
table_param_(stmt_allocator_),
|
|
scan_iter_(NULL)
|
|
{
|
|
}
|
|
|
|
ObTableApiGetRowIterator::~ObTableApiGetRowIterator()
|
|
{
|
|
if (NULL != scan_iter_) {
|
|
if (NULL != part_service_) {
|
|
part_service_->revert_scan_iter(scan_iter_);
|
|
scan_iter_ = NULL;
|
|
} else {
|
|
LOG_ERROR("The part service is NULL, but the scan iter is NOT NULL!");
|
|
}
|
|
}
|
|
}
|
|
|
|
void ObTableApiGetRowIterator::reset()
|
|
{
|
|
scan_param_.destroy();
|
|
table_param_.reset();
|
|
if (NULL != scan_iter_) {
|
|
if (NULL != part_service_) {
|
|
part_service_->revert_scan_iter(scan_iter_);
|
|
scan_iter_ = NULL;
|
|
} else {
|
|
LOG_ERROR("The part service is NULL, but the scan iter is NOT NULL!");
|
|
}
|
|
}
|
|
ObTableApiRowIterator::reset();
|
|
}
|
|
|
|
int ObTableApiGetRowIterator::open(const ObTableOperation &table_operation)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
const bool ignore_missing_column = true;
|
|
ObRowkey rowkey = const_cast<ObITableEntity &>(table_operation.entity()).get_rowkey();
|
|
if (!is_inited_) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("The table api update row iterator has not been inited, ", K(ret));
|
|
} else if (OB_FAIL(cons_all_columns(table_operation.entity(), ignore_missing_column))) {
|
|
LOG_WARN("Fail to construct all columns, ", K(ret));
|
|
} else if (OB_FAIL(fill_get_param(*ctx_, table_operation.type(), rowkey,
|
|
scan_param_, table_param_))) {
|
|
LOG_WARN("Fail to fill get param, ", K(ret));
|
|
} else if (OB_FAIL(part_service_->table_scan(scan_param_, scan_iter_))) {
|
|
if (OB_TRY_LOCK_ROW_CONFLICT != ret) {
|
|
LOG_WARN("fail to scan table", K(ret));
|
|
}
|
|
} else {
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTableApiGetRowIterator::get_next_row(common::ObNewRow *&row)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (NULL == scan_iter_) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("The table api get row iterator has not been inited, ", K(ret));
|
|
} else if (OB_FAIL(scan_iter_->get_next_row(row))) {
|
|
if (OB_ITER_END != ret) {
|
|
LOG_WARN("Fail to get next row, ", K(ret));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* ------------------------------------------------------------------ObTableApiMultiGetRowIterator---------------------------------------------------------
|
|
*/
|
|
ObTableApiMultiGetRowIterator::ObTableApiMultiGetRowIterator()
|
|
{
|
|
}
|
|
|
|
ObTableApiMultiGetRowIterator::~ObTableApiMultiGetRowIterator()
|
|
{
|
|
}
|
|
|
|
int ObTableApiMultiGetRowIterator::open(const ObTableBatchOperation &batch_operation)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
const bool ignore_missing_column = true;
|
|
if (!is_inited_) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("The table api multi get row iterator has not been inited, ", K(ret));
|
|
} else if (OB_FAIL(cons_all_columns(batch_operation.at(0).entity(), ignore_missing_column))) {
|
|
LOG_WARN("Fail to construct all columns, ", K(ret));
|
|
} else if (OB_FAIL(fill_multi_get_param(*ctx_, batch_operation, scan_param_, table_param_))) {
|
|
LOG_WARN("Fail to fill get param, ", K(ret));
|
|
} else if (OB_FAIL(part_service_->table_scan(scan_param_, scan_iter_))) {
|
|
if (OB_TRY_LOCK_ROW_CONFLICT != ret) {
|
|
LOG_WARN("fail to scan table", K(ret));
|
|
}
|
|
} else {
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
}
|
|
}
|