diff --git a/src/observer/table/ob_table_cache.cpp b/src/observer/table/ob_table_cache.cpp index 32fcf0b817..7e4637b0b7 100644 --- a/src/observer/table/ob_table_cache.cpp +++ b/src/observer/table/ob_table_cache.cpp @@ -142,9 +142,13 @@ int ObTableApiCacheGuard::create_cache_key(ObTableCtx *tb_ctx) || operation_type == ObTableOperationType::Type::INSERT_OR_UPDATE || operation_type == ObTableOperationType::Type::INCREMENT || operation_type == ObTableOperationType::Type::APPEND) { - const ObTableCtx::ObAssignIds &assign_ids = tb_ctx->get_assign_ids(); - for (int64_t i = 0; OB_SUCC(ret) && i < assign_ids.count(); i++) { - if (OB_FAIL(cache_key_.op_column_ids_.push_back(assign_ids.at(i).column_id_))) { + const ObIArray &assigns = tb_ctx->get_assignments(); + for (int64_t i = 0; OB_SUCC(ret) && i < assigns.count(); i++) { + const ObTableAssignment &tmp_assign = assigns.at(i); + if (OB_ISNULL(tmp_assign.column_item_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("assign column item is null", K(ret), K(tmp_assign)); + } else if (OB_FAIL(cache_key_.op_column_ids_.push_back(tmp_assign.column_item_->column_id_))) { LOG_WARN("fail to add assign column id", K(ret), K(i)); } } diff --git a/src/observer/table/ob_table_cache.h b/src/observer/table/ob_table_cache.h index 9ad0e9f596..f1ecb4e840 100644 --- a/src/observer/table/ob_table_cache.h +++ b/src/observer/table/ob_table_cache.h @@ -55,7 +55,7 @@ struct ObTableApiCacheKey: public ObILibCacheKey int64_t schema_version_; ObTableOperationType::Type operation_type_; bool is_ttl_table_; - common::ObArray op_column_ids_; + common::ObSEArray op_column_ids_; }; class ObTableApiCacheNode: public ObILibCacheNode diff --git a/src/observer/table/ob_table_cg_service.cpp b/src/observer/table/ob_table_cg_service.cpp index 87814cc49a..55a268066b 100644 --- a/src/observer/table/ob_table_cg_service.cpp +++ b/src/observer/table/ob_table_cg_service.cpp @@ -17,274 +17,87 @@ #include "share/system_variable/ob_system_variable.h" // for ObBinlogRowImage::FULL #include "sql/engine/expr/ob_expr_autoinc_nextval.h" // for ObAutoincNextvalExtra +using namespace oceanbase::common; +using namespace oceanbase::share; +using namespace oceanbase::sql; + namespace oceanbase { namespace table { - -ObRawExpr* ObTableExprCgService::get_ref_raw_expr(const ObIArray &all_exprs, - const ObString &col_name) -{ - bool found = false; - ObColumnRefRawExpr *expr = nullptr; - for (int64_t i = 0; i < all_exprs.count() && !found; i++) { - if (all_exprs.at(i)->is_column_ref_expr()) { - expr = static_cast(all_exprs.at(i)); - if (0 == col_name.case_compare(expr->get_column_name())) { - found = true; - } - } - } - - return expr; -} - -int ObTableExprCgService::build_generated_column_expr(ObTableCtx &ctx, - ObColumnRefRawExpr &col_expr, - const ObString &expr_str, - const ObIArray &exprs) +/* + generate column ref exprs. + 1. generate column reference expr which order is same as schema. + 2. generate stored generated column assign item expr + when update stored generated column directly or update its reference exprs. such as: + create table t(`c1` int primary key, `c2` varchar(10), `c3` varchar(10) generated always as (substring(`c2`, 1, 4) stored))); + - update t set `c3`='abc' where `c1`=1; + - update t set `c2`='abc' where `c1`=1; + both need assign `c3` +*/ +int ObTableExprCgService::generate_all_column_exprs(ObTableCtx &ctx) { int ret = OB_SUCCESS; + ObIArray &items = ctx.get_column_items(); const ObTableSchema *table_schema = ctx.get_table_schema(); + const uint64_t column_cnt = table_schema->get_column_count(); if (OB_ISNULL(table_schema)) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("table schema is null", K(ret), K(ctx)); - } else { - ObArray columns; - ObSchemaChecker schema_checker; - ObSchemaGetterGuard &schema_guard = ctx.get_schema_guard(); - ObRawExprFactory &expr_factory = ctx.get_expr_factory(); - ObSQLSessionInfo &sess_info = ctx.get_session_info(); - ObRawExpr *gen_expr = nullptr; - if (OB_FAIL(schema_checker.init(schema_guard))) { - LOG_WARN("fail to init schema checker", K(ret)); - } else if (OB_FAIL(ObRawExprUtils::build_generated_column_expr(expr_str, - expr_factory, - sess_info, - gen_expr, - columns, - table_schema, - false, /* allow_sequence */ - nullptr, - &schema_checker))) { - LOG_WARN("fail to build generated expr", K(ret), K(expr_str), K(ctx)); - } else if (OB_ISNULL(gen_expr)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("generated expr is null", K(ret)); - } else { - ObRawExpr *real_ref_expr = nullptr; - bool is_inc_or_append_replace = !ctx.get_delta_exprs().empty(); - if (is_inc_or_append_replace && 2 != columns.count()) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("invalid column for increment or append", K(ret), K(columns.count())); - } - ObIArray &gen_dependants_pairs = ctx.get_gen_dependants_pairs(); - ObTableCtx::ObGenDenpendantsPair pair; - pair.first = &col_expr; // 记录生成列 - const ObIArray *src_exprs = &exprs; - for (int64_t i = 0; OB_SUCC(ret) && i < columns.count(); i++) { - if (1 == i && is_inc_or_append_replace) { - src_exprs = &ctx.get_delta_exprs(); - } - if (OB_ISNULL(real_ref_expr = get_ref_raw_expr(*src_exprs, - columns.at(i).col_name_))) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("fail to get ref expr", K(ret), K(columns.at(i).ref_expr_->get_column_id())); - } else if (OB_FAIL(ObRawExprUtils::replace_ref_column(gen_expr, - columns.at(i).ref_expr_, - real_ref_expr))) { - LOG_WARN("fail to replace column reference expr", K(ret)); - } else if (OB_FAIL(add_var_to_array_no_dup(pair.second, real_ref_expr))) { // 记录依赖的列 - LOG_WARN("fail to add expr to array", K(ret)); - } - } - - if (OB_SUCC(ret)) { - if (OB_FAIL(gen_expr->formalize(&sess_info))) { - LOG_WARN("fail to formailize column reference expr", K(ret)); - } else if (ObRawExprUtils::need_column_conv(col_expr.get_result_type(), *gen_expr)) { - if (OB_FAIL(ObRawExprUtils::build_column_conv_expr(expr_factory, - ctx.get_allocator(), - col_expr, - gen_expr, - &sess_info))) { - LOG_WARN("fail to build column convert expr", K(ret)); - } - } - } - - if (OB_SUCC(ret)) { - gen_expr->set_for_generated_column(); - col_expr.set_dependant_expr(gen_expr); - if (OB_FAIL(gen_dependants_pairs.push_back(pair))) { - LOG_WARN("fail to push back generate ref expr pair", K(ret), K(gen_dependants_pairs)); - } - } - } - } - - return ret; -} - -int ObTableExprCgService::resolve_generated_column_expr(ObTableCtx &ctx) -{ - int ret = OB_SUCCESS; - const ObIArray &exprs = (ctx.is_for_update() || ctx.is_for_insertup()) ? - ctx.get_old_row_exprs() : ctx.get_all_exprs().get_expr_array(); - - for (int64_t i = 0; OB_SUCC(ret) && i < exprs.count(); i++) { - if (exprs.at(i)->is_column_ref_expr()) { - ObColumnRefRawExpr *ref_expr = static_cast(exprs.at(i)); - if (ref_expr->is_generated_column()) { - const ObColumnSchemaV2 *gen_col_schema = nullptr; - if (OB_ISNULL(gen_col_schema = ctx.get_table_schema()->get_column_schema(ref_expr->get_column_id()))) { - ret = OB_SCHEMA_ERROR; - LOG_WARN("fail to get generated column schema", K(ret), K(ref_expr->get_column_id())); - } else if (OB_FAIL(build_generated_column_expr(ctx, - *ref_expr, - gen_col_schema->get_cur_default_value().get_string(), - exprs))) { - LOG_WARN("fail to build generated raw expr", K(ret), K(*ref_expr)); - } - } - } - } - - return ret; -} - -int ObTableExprCgService::generate_column_ref_raw_expr(ObTableCtx &ctx, - const ObColumnSchemaV2 &col_schema, - ObRawExpr *&expr) -{ - int ret = OB_SUCCESS; - - ObColumnRefRawExpr *col_ref_expr = NULL; - // 存储最开始生成的列原生表达式, 用于后续生成主键冲突 - ObIArray &all_column_exprs = ctx.get_all_column_ref_exprs(); - // 在update场景下, 会多次调用该函数,我们只需要存最开始生成的列引用表达式,记录下是否存储满 - bool is_full = (ctx.get_table_schema()->get_column_count() == all_column_exprs.count()); - - if (OB_FAIL(ObRawExprUtils::build_column_expr(ctx.get_expr_factory(), - col_schema, - col_ref_expr))) { - LOG_WARN("fail to build column expr", K(ret), K(col_schema)); - } else if (OB_ISNULL(col_ref_expr)) { + LOG_WARN("table schema is null", K(ret)); + } else if (items.count() != column_cnt) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("expr is null", K(ret)); + LOG_WARN("column item count not equal to column count", K(ret), K(items), K(column_cnt)); } else { - expr = col_ref_expr; - if (!is_full && OB_FAIL(all_column_exprs.push_back(col_ref_expr))) { - LOG_WARN("fail to push back column ref expr to all column exprs", K(ret)); - } else { - // delete/update/get/scan操作只需要生成列引用表达式 - // 自增表达式结构为: con_conv_expr - auto_inc_expr - con_conv_expr - if (col_schema.is_autoincrement() && ctx.need_auto_inc_expr()) { - if (OB_FAIL(ObRawExprUtils::build_column_conv_expr(ctx.get_expr_factory(), - ctx.get_allocator(), - *col_ref_expr, - expr, - &ctx.get_session_info()))) { - LOG_WARN("fail to build column conv expr", K(ret), K(*col_ref_expr)); - } else if (OB_FAIL(generate_autoinc_nextval_expr(ctx, expr, col_schema))) { - LOG_WARN("fail to generate auto inc next val expr", K(ret)); - } else if (OB_FAIL(ObRawExprUtils::build_column_conv_expr(ctx.get_expr_factory(), - ctx.get_allocator(), - *col_ref_expr, - expr, - &ctx.get_session_info()))) { - LOG_WARN("fail to build column conv expr", K(ret)); - } - } - } - } - - return ret; -} - -int ObTableExprCgService::genreate_filter_exprs(ObTableCtx &ctx) -{ - int ret = OB_SUCCESS; - - // won't put filter exprs into all exprs here - if (ctx.is_ttl_table()) { - ObIArray &filter_exprs = ctx.get_filter_exprs(); - ObRawExpr *expire_expr = nullptr; - if (OB_FAIL(build_expire_expr(ctx, expire_expr))) { - LOG_WARN("fail to build expire expr", K(ret), K(ctx)); - } else if(OB_FAIL(filter_exprs.push_back(expire_expr))) { - LOG_WARN("fail to push back expire expr", K(ret), K(filter_exprs)); - } - } - - return ret; -} - -int ObTableExprCgService::generate_exprs(ObTableCtx &ctx, - oceanbase::common::ObIAllocator &allocator, - oceanbase::sql::ObExprFrameInfo &expr_frame_info) -{ - int ret = OB_SUCCESS; - if (ctx.is_for_update() || ctx.is_for_insertup()) { - if (OB_FAIL(generate_update_raw_exprs(ctx))) { - LOG_WARN("fail to generate update raw exprs", K(ret), K(ctx)); - } - } else if (OB_FAIL(generate_column_raw_exprs(ctx))) { - LOG_WARN("fail to generate column raw exprs", K(ret), K(ctx)); - } - - if (OB_SUCC(ret)) { - if (OB_FAIL(genreate_filter_exprs(ctx))) { - LOG_WARN("fail to generate filter exprs", K(ret), K(ctx)); - } else if (OB_FAIL(generate_expr_frame_info(ctx, allocator, expr_frame_info))) { - LOG_WARN("fail to generate expr frame info", K(ret), K(ctx)); - } - } - - return ret; -} - -int ObTableExprCgService::generate_column_raw_exprs(ObTableCtx &ctx) -{ - int ret = OB_SUCCESS; - const ObTableSchema *table_schema = ctx.get_table_schema(); - ObIArray *exprs = (ctx.is_for_update() || ctx.is_for_insertup()) ? - &ctx.get_old_row_exprs() : const_cast *>(&ctx.get_all_exprs().get_expr_array()); - - if (OB_ISNULL(table_schema)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("table schema is null", K(ret), K(ctx)); - } else { - ObRawExpr *col_ref_expr = nullptr; - const ObColumnSchemaV2 *column_schema = nullptr; - const uint64_t column_cnt = table_schema->get_column_count(); + const ObColumnSchemaV2 *col_schema = nullptr; for (int64_t i = 0; OB_SUCC(ret) && i < column_cnt; i++) { - if (OB_ISNULL(column_schema = table_schema->get_column_schema_by_idx(i))) { + ObTableColumnItem &item = items.at(i); + if (OB_ISNULL(col_schema = table_schema->get_column_schema_by_idx(i))) { ret = OB_SCHEMA_ERROR; LOG_WARN("fail to get column schema", K(ret)); - } else if (OB_FAIL(generate_column_ref_raw_expr(ctx, *column_schema, col_ref_expr))) { - LOG_WARN("fail to generate column ref raw expr", K(ret), K(*column_schema)); - } else if (OB_FAIL(exprs->push_back(col_ref_expr))) { - LOG_WARN("fail to push back column ref raw expr", K(ret)); + } else if (OB_FAIL(ObRawExprUtils::build_column_expr(ctx.get_expr_factory(), + *col_schema, + item.expr_))) { + LOG_WARN("fail to build column expr", K(ret), K(*col_schema)); } } } - if (OB_SUCC(ret) && table_schema->has_generated_column()) { - if (OB_FAIL(resolve_generated_column_expr(ctx))) { - LOG_WARN("fail to resolver generated column expr", K(ret)); + // generate stored generated column assign item expr + if (OB_SUCC(ret)) { + const ObColumnSchemaV2 *col_schema = nullptr; + ObIArray &assigns = ctx.get_assignments(); + for (int64_t i = 0; OB_SUCC(ret) && i < assigns.count(); i++) { + ObTableAssignment &assign = assigns.at(i); + if (OB_ISNULL(assign.column_item_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("assign column item is null", K(ret), K(assign)); + } else if (!assign.column_item_->is_stored_generated_column_) { + // do nothing + } else if (OB_ISNULL(col_schema = table_schema->get_column_schema(assign.column_item_->column_id_))) { + ret = OB_SCHEMA_ERROR; + LOG_WARN("fail to get column schema", K(ret), K(assign)); + } else if (OB_FAIL(ObRawExprUtils::build_column_expr(ctx.get_expr_factory(), + *col_schema, + assign.column_item_->expr_))) { + LOG_WARN("fail to build column expr", K(ret), K(*col_schema)); + } } } return ret; } -int ObTableExprCgService::build_expire_expr(ObTableCtx &ctx, ObRawExpr *&expire_expr) +/* + expr tree: + T_OP_LE + / \ + ttl_gen_expr T_FUN_SYS_CUR_TIMESTAMP +*/ +int ObTableExprCgService::generate_expire_expr(ObTableCtx &ctx, + ObRawExpr *&expr) { int ret = OB_SUCCESS; - const ObIArray &exprs = (ctx.is_for_update() || ctx.is_for_insertup()) ? - ctx.get_old_row_exprs() : ctx.get_all_exprs().get_expr_array(); const ObTableSchema *table_schema = ctx.get_table_schema(); ObRawExprFactory &expr_factory = ctx.get_expr_factory(); ObSysFunRawExpr *now_func_expr = nullptr; @@ -318,15 +131,18 @@ int ObTableExprCgService::build_expire_expr(ObTableCtx &ctx, ObRawExpr *&expire_ LOG_WARN("fail to build expire expr", K(ret), K(ttl_definition)); } else { // 找到生成列引用的列并替换为真正的列 - ObRawExpr *real_ref_expr = nullptr; - const ObIArray *src_exprs = &exprs; for (int64_t i = 0; OB_SUCC(ret) && i < columns.count(); i++) { - if (OB_ISNULL(real_ref_expr = get_ref_raw_expr(*src_exprs, columns.at(i).col_name_))) { + const ObQualifiedName &tmp_column = columns.at(i); + const ObString &col_name = tmp_column.col_name_; + ObRawExpr *tmp_expr = nullptr; + if (OB_FAIL(ctx.get_expr_from_column_items(col_name, tmp_expr))) { + LOG_WARN("fail to get expr from column items", K(ret), K(col_name)); + } + if (OB_FAIL(ret)) { + } else if (OB_ISNULL(tmp_expr)) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("fail to get ref expr", K(ret), K(columns.at(i).ref_expr_->get_column_id())); - } else if (OB_FAIL(ObRawExprUtils::replace_ref_column(ttl_gen_expr, - columns.at(i).ref_expr_, - real_ref_expr))) { + LOG_WARN("expr to replace is null", K(ret)); + } else if (OB_FAIL(ObRawExprUtils::replace_ref_column(ttl_gen_expr, tmp_column.ref_expr_, tmp_expr))) { LOG_WARN("fail to replace column reference expr", K(ret)); } } @@ -337,7 +153,7 @@ int ObTableExprCgService::build_expire_expr(ObTableCtx &ctx, ObRawExpr *&expire_ } else if (OB_FAIL(expire_expr_tmp->formalize(&sess_info))) { LOG_WARN("fail to formailize expire expr", K(ret)); } else { - expire_expr = expire_expr_tmp; + expr = expire_expr_tmp; } } } @@ -346,114 +162,198 @@ int ObTableExprCgService::build_expire_expr(ObTableCtx &ctx, ObRawExpr *&expire_ return ret; } +/* + expr tree: + autoinc_nextval expr + | + column_conv expr +*/ +int ObTableExprCgService::generate_autoinc_nextval_expr(ObTableCtx &ctx, + const ObTableColumnItem &item, + ObRawExpr *&expr) +{ + int ret = OB_SUCCESS; + ObRawExpr *column_cnv_expr = item.expr_; -int ObTableExprCgService::generate_full_assign_raw_exprs(ObTableCtx &ctx) + if (!item.is_auto_increment_) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid column item", K(ret), K(item)); + } else if (OB_ISNULL(item.expr_)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("column item expr is null", K(ret), K(item)); + } else if (OB_FAIL(ObRawExprUtils::build_column_conv_expr(ctx.get_expr_factory(), + ctx.get_allocator(), + *item.expr_, + column_cnv_expr, + &ctx.get_session_info()))) { + LOG_WARN("fail to build column conv expr", K(ret), K(item)); + } else { + ObSysFunRawExpr *autoinc_nextval_expr = NULL; + if (OB_FAIL(ctx.get_expr_factory().create_raw_expr(T_FUN_SYS_AUTOINC_NEXTVAL, autoinc_nextval_expr))) { + LOG_WARN("fail to create nextval expr", K(ret)); + } else { + autoinc_nextval_expr->set_func_name(ObString::make_string(N_AUTOINC_NEXTVAL)); + if (OB_FAIL(autoinc_nextval_expr->add_param_expr(column_cnv_expr))) { + LOG_WARN("fail to add collumn conv expr to function param", K(ret)); + } else if (OB_FAIL(autoinc_nextval_expr->formalize(&ctx.get_session_info()))) { + LOG_WARN("fail to extract info", K(ret)); + } else if (OB_FAIL(ObAutoincNextvalExtra::init_autoinc_nextval_extra(&ctx.get_allocator(), + reinterpret_cast(autoinc_nextval_expr), + item.table_id_, + item.column_id_, + ctx.get_table_name(), + item.column_name_))) { + LOG_WARN("fail to init autoinc_nextval_extra", K(ret), K(ctx.get_table_name()), K(item)); + } else { + expr = autoinc_nextval_expr; + } + } + } + + return ret; +} + +/* + expr tree: + column conv expr + | + cur timestamp expr +*/ +int ObTableExprCgService::generate_current_timestamp_expr(ObTableCtx &ctx, + const ObTableColumnItem &item, + ObRawExpr *&expr) +{ + int ret = OB_SUCCESS; + ObSysFunRawExpr *tmp_expr = NULL; + + if (!IS_DEFAULT_NOW_OBJ(item.default_value_)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid column item", K(ret), K(item)); + } else if (OB_ISNULL(item.expr_)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("column item expr is null", K(ret), K(item)); + } else if (OB_FAIL(ctx.get_expr_factory().create_raw_expr(T_FUN_SYS_CUR_TIMESTAMP, tmp_expr))) { + LOG_WARN("fail to create cur timestamp expr", K(ret)); + } else { + tmp_expr->set_data_type(ObTimestampType); + tmp_expr->set_accuracy(item.expr_->get_accuracy()); + tmp_expr->set_func_name(ObString::make_string(N_CUR_TIMESTAMP)); + if (OB_FAIL(tmp_expr->formalize(&ctx.get_session_info()))) { + LOG_WARN("fail to formalize cur_timestamp_expr", K(ret)); + } else if (OB_FAIL(ObRawExprUtils::build_column_conv_expr(ctx.get_expr_factory(), + ctx.get_allocator(), + *item.expr_, + reinterpret_cast(tmp_expr), + &ctx.get_session_info()))) { + LOG_WARN("fail to build column conv expr", K(ret), K(item)); + } else { + // need clear IS_CONST_EXPR flag, cause StoredRow.to_expr will skip const expr in insertUp/replace executor + tmp_expr->clear_flag(IS_CONST_EXPR); + expr = tmp_expr; + } + } + + return ret; +} + +/* + build generate column expr + - delta_expr is for increment or append operation + - item.expr_ is column ref expr, gen_expr is real calculate expr. +*/ +int ObTableExprCgService::build_generated_column_expr(ObTableCtx &ctx, + ObTableColumnItem &item, + const ObString &expr_str, + ObRawExpr *&expr, + sql::ObRawExpr *delta_expr/* = nullptr*/) { int ret = OB_SUCCESS; const ObTableSchema *table_schema = ctx.get_table_schema(); - ObIArray &full_assign_exprs = ctx.get_full_assign_exprs(); - bool is_inc_or_append = ctx.is_inc_or_append(); - bool has_stored_gen_col = false; if (OB_ISNULL(table_schema)) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("table schema is null", K(ret), K(ctx)); - } else { - ObRawExpr *col_ref_expr = nullptr; - const ObColumnSchemaV2 *column_schema = nullptr; - const uint64_t column_cnt = table_schema->get_column_count(); - for (int64_t i = 0; OB_SUCC(ret) && i < column_cnt; i++) { - bool is_virtual_col = false; - if (OB_ISNULL(column_schema = table_schema->get_column_schema_by_idx(i))) { - ret = OB_SCHEMA_ERROR; - LOG_WARN("fail to get column schema", K(ret), K(i)); - } else if (column_schema->is_virtual_generated_column()) { - is_virtual_col = true; - } else if (column_schema->is_stored_generated_column()) { - has_stored_gen_col = true; - } - if (OB_FAIL(ret)) { - } else if (OB_FAIL(!is_virtual_col && generate_column_ref_raw_expr(ctx, *column_schema, col_ref_expr))) { - LOG_WARN("fail to generate column ref raw expr", K(ret), K(*column_schema)); - } else if (OB_FAIL(!is_virtual_col && full_assign_exprs.push_back(col_ref_expr))) { - LOG_WARN("fail to push back column ref raw expr", K(ret)); - } - } - } - - if (OB_SUCC(ret) && has_stored_gen_col) { - for (int64_t i = 0; OB_SUCC(ret) && i < full_assign_exprs.count(); i++) { - if (full_assign_exprs.at(i)->is_column_ref_expr()) { - ObColumnRefRawExpr *ref_expr = static_cast(full_assign_exprs.at(i)); - if (ref_expr->is_stored_generated_column()) { - const ObColumnSchemaV2 *gen_col_schema = nullptr; - if (OB_ISNULL(gen_col_schema = ctx.get_table_schema()->get_column_schema(ref_expr->get_column_id()))) { - ret = OB_SCHEMA_ERROR; - LOG_WARN("fail to get generated column schema", K(ret), K(ref_expr->get_column_id())); - } else if (OB_FAIL(build_generated_column_expr(ctx, - *ref_expr, - gen_col_schema->get_cur_default_value().get_string(), - full_assign_exprs))) { - LOG_WARN("fail to build generated column expr", K(ret), K(*ref_expr)); - } - } - } - } - } - - // 构造delta expr,作为生成列表达式的参数表达式 - // 针对increment和append场景,将对应的列表达式设置为stored生成列表达式,并且构造生成列 - if (OB_SUCC(ret) && is_inc_or_append) { - const ObColumnSchemaV2 *column_schema = nullptr; - ObRawExpr *col_ref_expr = nullptr; - ObIArray &delta_exprs = ctx.get_delta_exprs(); - const ObIArray &expr_strs = ctx.get_expr_strs(); - const ObTableCtx::ObAssignIds &assign_ids = ctx.get_assign_ids(); - const int64_t N = assign_ids.count(); - for (int64_t i = 0; OB_SUCC(ret) && i < N; i++) { - uint64_t idx = assign_ids.at(i).idx_; - uint64_t column_id = assign_ids.at(i).column_id_; - if (OB_ISNULL(column_schema = table_schema->get_column_schema(column_id))) { - ret = OB_SCHEMA_ERROR; - LOG_WARN("fail to get column schema", K(ret), K(column_id)); - } else if (column_schema->is_autoincrement()) { // do not support delta on auto increment column currently - ret = OB_NOT_SUPPORTED; - LOG_WARN("auto increment column do not support delta", K(ret), K(*column_schema)); - } else if (OB_FAIL(generate_column_ref_raw_expr(ctx, *column_schema, col_ref_expr))) { - LOG_WARN("fail to generate column ref raw expr", K(ret), K(*column_schema)); - } else if (OB_FAIL(delta_exprs.push_back(col_ref_expr))) { - LOG_WARN("fail to push back column ref raw expr", K(ret)); - } else { - ObColumnRefRawExpr *ref_expr = static_cast(full_assign_exprs.at(idx)); - ref_expr->set_column_flags(ref_expr->get_column_flags() | STORED_GENERATED_COLUMN_FLAG); - if (OB_FAIL(build_generated_column_expr(ctx, - *ref_expr, - expr_strs.at(i), - ctx.get_old_row_exprs()))) { - LOG_WARN("fail to build generated column expr", K(ret), K(*ref_expr), K(expr_strs.at(i))); - } - } - } - } - - return ret; -} - -int ObTableExprCgService::generate_assign_exprs(ObTableCtx &ctx, - const ObTableCtx::ObAssignIds &assign_ids, - common::ObIArray &assign_exprs) -{ - int ret = OB_SUCCESS; - const ObIArray &full_exprs = ctx.get_full_assign_exprs(); - - if (assign_ids.count() > full_exprs.count()) { + LOG_WARN("table schema is null", K(ret)); + } else if (ctx.is_inc_or_append() && OB_ISNULL(delta_expr)) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("invalid assign ids count", K(ret), K(assign_ids.count()), K(full_exprs.count())); + LOG_WARN("delta expr should not be null when do append or increment", K(ret)); } else { - for (int64_t i = 0; OB_SUCC(ret) && i < assign_ids.count(); i++) { - const ObTableCtx::ObAssignId &assign_id = assign_ids.at(i); - if (OB_FAIL(assign_exprs.push_back(full_exprs.at(assign_id.idx_)))) { - LOG_WARN("fail to push back assign expr", K(ret), K(i), K(assign_id)); + ObArray columns; + ObSchemaChecker schema_checker; + ObSchemaGetterGuard &schema_guard = ctx.get_schema_guard(); + ObRawExprFactory &expr_factory = ctx.get_expr_factory(); + ObSQLSessionInfo &sess_info = ctx.get_session_info(); + ObRawExpr *gen_expr = nullptr; + + if (OB_FAIL(schema_checker.init(schema_guard))) { + LOG_WARN("fail to init schema checker", K(ret)); + } else if (OB_FAIL(ObRawExprUtils::build_generated_column_expr(expr_str, + expr_factory, + sess_info, + gen_expr, + columns, + table_schema, + false, /* allow_sequence */ + nullptr, + &schema_checker))) { + LOG_WARN("fail to build generated expr", K(ret), K(expr_str), K(ctx)); + } else { + /* + 1 replace ref columns and add exprs to dependant_exprs. + such as: + `K` varbinary(1024), + `G` varbinary(1024) generated always as (substring(`K`, 1, 4)) + 1.1. gen_expr is substring(`K`, 1, 4) which is reference to `K` + 1.2. `G` is depend on `K`, so we record it. + 2. replace second expr with delta expr when do increment or append. + 2.1 increment expr: (IFNULL(`%s`, 0) + `%s`) - %s is column name + 2.2 append expr:(concat_ws('', `%s`, `%s`)) - %s is column name + 3. get replace expr from assignments firstly. + such as: + `c2` varchar(20), + `c3` varchar(20), + `g` varchar(30) generated always as (concat(`c2`,`c3`)) stored + 3.1 when only update `c2`, 'g' should update as well. + 3.2 `g` expr should be concat(`c2_assign`,`c3`) + */ + for (int64_t i = 0; OB_SUCC(ret) && i < columns.count(); i++) { + const ObQualifiedName &tmp_column = columns.at(i); + const ObString &col_name = tmp_column.col_name_; + ObRawExpr *tmp_expr = nullptr; + if (1 == i && ctx.is_inc_or_append()) { + tmp_expr = delta_expr; + } else if (OB_FAIL(ctx.get_expr_from_assignments(col_name, tmp_expr))) { + LOG_WARN("fail to get expr from assignments", K(ret), K(col_name)); + } else if (OB_ISNULL(tmp_expr) && OB_FAIL(ctx.get_expr_from_column_items(col_name, tmp_expr))) { + LOG_WARN("fail to get expr from column items", K(ret), K(col_name)); + } + if (OB_FAIL(ret)) { + } else if (OB_ISNULL(tmp_expr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("expr to replace is null", K(ret)); + } else if (OB_FAIL(ObRawExprUtils::replace_ref_column(gen_expr, tmp_column.ref_expr_, tmp_expr))) { + LOG_WARN("fail to replace column reference expr", K(ret)); + } else if (OB_FAIL(add_var_to_array_no_dup(item.dependant_exprs_, tmp_expr))) { + LOG_WARN("fail to add expr to array", K(ret), K(item), K(*tmp_expr)); + } + } + + if (OB_SUCC(ret)) { + if (OB_FAIL(gen_expr->formalize(&sess_info))) { + LOG_WARN("fail to formailize column reference expr", K(ret)); + } else if (ObRawExprUtils::need_column_conv(item.expr_->get_result_type(), *gen_expr) + && OB_FAIL(ObRawExprUtils::build_column_conv_expr(expr_factory, + ctx.get_allocator(), + *item.expr_, + gen_expr, + &sess_info))) { + LOG_WARN("fail to build column conv expr", K(ret)); + } else if (ctx.is_inc_or_append()) { + expr = gen_expr; // expr should be a calculate expr in increment or append operation + } else { + gen_expr->set_for_generated_column(); + item.expr_->set_dependant_expr(gen_expr); + expr = item.expr_; + } } } } @@ -461,45 +361,271 @@ int ObTableExprCgService::generate_assign_exprs(ObTableCtx &ctx, return ret; } -int ObTableExprCgService::generate_update_raw_exprs(ObTableCtx &ctx) +/* + construct exprs, include column ref expr and calculate expr. + calculate expr: + - auto increment expr + - current timestamp expr + - generate expr +*/ +int ObTableExprCgService::resolve_exprs(ObTableCtx &ctx) +{ + int ret = OB_SUCCESS; + const ObTableSchema *table_schema = ctx.get_table_schema(); + ObIArray &items = ctx.get_column_items(); + bool is_dml = ctx.is_dml(); + + if (OB_ISNULL(table_schema)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("table schema is null", K(ret)); + } else if (items.empty()) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("column items is empty", K(ret)); + } else { + ObIArray &all_exprs = ctx.get_all_exprs_array(); + ObRawExpr *expr = nullptr; + for (int64_t i = 0; OB_SUCC(ret) && i < items.count(); i++) { + ObTableColumnItem &item = items.at(i); + if (is_dml) { + if (item.is_auto_increment_ && ctx.need_auto_inc_expr()) { + if (OB_FAIL(generate_autoinc_nextval_expr(ctx, item, expr))) { + LOG_WARN("fail to generate autoinc nextval expr", K(ret)); + } + } else if (IS_DEFAULT_NOW_OBJ(item.default_value_)) { // defualt current time + if (OB_FAIL(generate_current_timestamp_expr(ctx, item, expr))) { + LOG_WARN("fail to generate autoinc nextval expr", K(ret)); + } + } else if (item.is_generated_column_) { + const ObString &expr_str = item.default_value_.get_string(); + if (OB_FAIL(build_generated_column_expr(ctx, item, expr_str, expr))) { + LOG_WARN("fail to build generated column expr", K(ret), K(item), K(expr_str)); + } + } else { + expr = item.expr_; + } + } else { + if (item.is_generated_column_) { + const ObString &expr_str = item.default_value_.get_string(); + if (OB_FAIL(build_generated_column_expr(ctx, item, expr_str, expr))) { + LOG_WARN("fail to build generated column expr", K(ret), K(item), K(expr_str)); + } + } else { + expr = item.expr_; + } + } + + if (OB_SUCC(ret)) { + item.raw_expr_ = expr; + if (OB_FAIL(all_exprs.push_back(expr))) { + LOG_WARN("fail to push back expr to all exprs", K(ret)); + } + } + } + } + + return ret; +} + + +// generate assign expr(column ref expr or calculate expr) for assignment. +int ObTableExprCgService::generate_assign_expr(ObTableCtx &ctx, ObTableAssignment &assign) +{ + int ret = OB_SUCCESS; + ObRawExpr *tmp_expr = nullptr; + ObTableColumnItem *item = assign.column_item_; + + if (OB_ISNULL(item)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("column item is null", K(ret)); + } else if (FALSE_IT(assign.column_expr_ = item->expr_)) { + } else if (item->is_auto_increment_ && ctx.need_auto_inc_expr()) { + if (OB_FAIL(generate_autoinc_nextval_expr(ctx, *item, tmp_expr))) { + LOG_WARN("fail to generate autoinc nextval expr", K(ret)); + } + } else if (IS_DEFAULT_NOW_OBJ(item->default_value_)) { // defualt current time + if (OB_FAIL(generate_current_timestamp_expr(ctx, *item, tmp_expr))) { + LOG_WARN("fail to generate autoinc nextval expr", K(ret)); + } + } else if (item->is_generated_column_) { + if (!item->is_stored_generated_column_) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("assign virtual generated column is not supported", K(ret)); + } else { + if (OB_FAIL(build_generated_column_expr(ctx, *item, item->generated_expr_str_, tmp_expr))) { + LOG_WARN("fail to build generated column expr", K(ret), K(*item)); + } + } + } else if (assign.is_inc_or_append_) { + if (OB_FAIL(build_generated_column_expr(ctx, *item, item->generated_expr_str_, tmp_expr, assign.delta_expr_))) { + LOG_WARN("fail to build generated column expr", K(ret), K(*item)); + } + } else { + // generate column ref expr + const ObTableSchema *table_schema = ctx.get_table_schema(); + const ObColumnSchemaV2 *col_schema = nullptr; + ObColumnRefRawExpr *tmp_ref_expr = nullptr; + if (OB_ISNULL(table_schema)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("table schema is null", K(ret)); + } else if (OB_ISNULL(col_schema = table_schema->get_column_schema(item->column_id_))) { + ret = OB_SCHEMA_ERROR; + LOG_WARN("fail to get column schema", K(ret), K(*item)); + } else if (OB_FAIL(ObRawExprUtils::build_column_expr(ctx.get_expr_factory(), *col_schema, tmp_ref_expr))) { + LOG_WARN("fail to build column expr", K(ret)); + } + tmp_expr = tmp_ref_expr; + } + + if (OB_SUCC(ret)) { + assign.expr_ = tmp_expr; + } + + return ret; +} + +/* + generate delta expr for increment or append operation. + increment expr: IFNULL(`c1`, 0) + `c1_delta` + append expr: concat_ws('', `c1`, `c1_delta`) +*/ +int ObTableExprCgService::generate_delta_expr(ObTableCtx &ctx, ObTableAssignment &assign) +{ + int ret = OB_SUCCESS; + ObTableColumnItem *item = assign.column_item_; + + if (OB_ISNULL(item)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("column item is null", K(ret)); + } else if (!assign.is_inc_or_append_) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("invalid assignment", K(ret), K(assign)); + } else { + // generate column ref expr + const ObTableSchema *table_schema = ctx.get_table_schema(); + const ObColumnSchemaV2 *col_schema = nullptr; + ObColumnRefRawExpr *tmp_ref_expr = nullptr; + if (OB_ISNULL(table_schema)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("table schema is null", K(ret)); + } else if (OB_ISNULL(col_schema = table_schema->get_column_schema(item->column_id_))) { + ret = OB_SCHEMA_ERROR; + LOG_WARN("fail to get column schema", K(ret), K(*item)); + } else if (OB_FAIL(ObRawExprUtils::build_column_expr(ctx.get_expr_factory(), *col_schema, tmp_ref_expr))) { + LOG_WARN("fail to build column expr", K(ret)); + } + assign.delta_expr_ = tmp_ref_expr; + assign.column_expr_ = item->expr_; // column_expr_ ref to old expr + } + + return ret; +} + +/* + generate assign exprs for update or insertup operation. + - increment and append operations use insertup executor. + - generate delta expr for increment and append operations. + - generate assign expr. + - push back assign expr to all exprs, assign expr need alloc frame as well. +*/ +int ObTableExprCgService::generate_assignments(ObTableCtx &ctx) +{ + int ret = OB_SUCCESS; + ObIArray &assigns = ctx.get_assignments(); + ObIArray &all_exprs = ctx.get_all_exprs_array(); + + if (!ctx.is_for_update() && !ctx.is_for_insertup()) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected operation", K(ret), K(ctx)); + } else if (assigns.empty()) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("assigns is empty", K(ret)); + } else { + for (int64_t i = 0; OB_SUCC(ret) && i < assigns.count(); i++) { + ObTableAssignment &assign = assigns.at(i); + if (assign.is_inc_or_append_ && OB_FAIL(generate_delta_expr(ctx, assign))) { + LOG_WARN("fail to generate delta expr", K(ret), K(assign)); + } else if (OB_FAIL(generate_assign_expr(ctx, assign))) { + LOG_WARN("fail to generate assign expr", K(ret), K(assign)); + } else if (OB_FAIL(all_exprs.push_back(assign.expr_))) { + LOG_WARN("fail to push back expr to all exprs", K(ret)); + } else if (assign.is_inc_or_append_ && OB_FAIL(all_exprs.push_back(assign.expr_))) { + LOG_WARN("fail to push back delta expr to all exprs", K(ret)); + } + } + } + + return ret; +} + +// generate filter exprs and push back to all exprs. +// currently there is only expire expr in filter exprs. +int ObTableExprCgService::generate_filter_exprs(ObTableCtx &ctx) { int ret = OB_SUCCESS; - if (OB_FAIL(generate_column_raw_exprs(ctx))) { - LOG_WARN("fail to generate column raw exprs", K(ret), K(ctx)); - } else if (OB_FAIL(generate_full_assign_raw_exprs(ctx))) { - LOG_WARN("fail to generate assign raw exprs", K(ret), K(ctx)); - } else { - ObRawExprUniqueSet &all_exprs = ctx.get_all_exprs(); - ObIArray &old_row_exprs = ctx.get_old_row_exprs(); - ObIArray &assign_exprs = ctx.get_full_assign_exprs(); - ObIArray &delta_exprs = ctx.get_delta_exprs(); - - // 将 old row exprs加到all exprs里面 - for (int64_t i = 0; OB_SUCC(ret) && i < old_row_exprs.count(); i++) { - if (OB_FAIL(all_exprs.append(old_row_exprs.at(i)))) { - LOG_WARN("fail to append old row expr to all exprs", K(ret), K(i)); - } - } - - // 将 assign row exprs加到all exprs里面 - for (int64_t i = 0; OB_SUCC(ret) && i < assign_exprs.count(); i++) { - if (OB_FAIL(all_exprs.append(assign_exprs.at(i)))) { - LOG_WARN("fail to append assign expr to all exprs", K(ret), K(i)); - } - } - - // 将 delta exprs加到all exprs里面 - for (int64_t i = 0; OB_SUCC(ret) && i < delta_exprs.count(); i++) { - if (OB_FAIL(all_exprs.append(delta_exprs.at(i)))) { - LOG_WARN("fail to append delta expr to all exprs", K(ret), K(i)); - } + if (ctx.is_ttl_table()) { + ObIArray &all_exprs = ctx.get_all_exprs_array(); + ObIArray &filter_exprs = ctx.get_filter_exprs(); + ObRawExpr *expire_expr = nullptr; + if (OB_FAIL(generate_expire_expr(ctx, expire_expr))) { + LOG_WARN("fail to generate expire expr", K(ret), K(ctx)); + } else if(OB_FAIL(filter_exprs.push_back(expire_expr))) { + LOG_WARN("fail to push back expire expr", K(ret), K(filter_exprs)); + } else if (OB_FAIL(all_exprs.push_back(expire_expr))) { + LOG_WARN("fail to push back expire expr to all exprs", K(ret)); } } return ret; } +/* + generate all expressions. + - generate all column exprs firstly. + - resolve_exprs is for generate calculate expr if need, and push back expr to all_exprs. + - generate assign expr when update. + - generate expr frame info finally. +*/ +int ObTableExprCgService::generate_exprs(ObTableCtx &ctx, + oceanbase::common::ObIAllocator &allocator, + oceanbase::sql::ObExprFrameInfo &expr_frame_info) +{ + int ret = OB_SUCCESS; + + if (OB_FAIL(generate_all_column_exprs(ctx))) { // 1. generate all column exprs and add to column item array + LOG_WARN("fail to generate all column exprs", K(ret), K(ctx)); + } else if (OB_FAIL(resolve_exprs(ctx))) { // 2. resolve exprs, such as generate expr. + LOG_WARN("fail to resolve exprs", K(ret), K(ctx)); + } else if ((ctx.is_for_update() || ctx.is_for_insertup()) && OB_FAIL(generate_assignments(ctx))) { + LOG_WARN("fail to generate assign infos", K(ret), K(ctx)); + } else if (OB_FAIL(generate_filter_exprs(ctx))) { + LOG_WARN("fail to generate filer exprs", K(ret), K(ctx)); + } else if (OB_FAIL(generate_expr_frame_info(ctx, allocator, expr_frame_info))) { + LOG_WARN("fail to generate expr frame info", K(ret), K(ctx)); + } + + return ret; +} + +// we need to make sure all column ref exprs have beed added, cause scan need column ref exprs. +int ObTableExprCgService::add_extra_column_exprs(ObTableCtx &ctx) +{ + int ret = OB_SUCCESS; + ObIArray &all_exprs = ctx.get_all_exprs_array(); + ObIArray &items = ctx.get_column_items(); + for (int64_t i = 0; OB_SUCC(ret) && i < items.count(); i++) { + const ObTableColumnItem &item = items.at(i); + if (item.is_auto_increment_) { + // do nothing, auto_increment column ref expr has been add in column conv expr param + } else if (OB_FAIL(add_var_to_array_no_dup(all_exprs, static_cast(item.expr_)))) { + LOG_WARN("fail to add column expr", K(ret), K(all_exprs), K(item)); + } + } + + return ret; +} + +// generate expr frame info, expr frame info represents the memory layout of the expr. int ObTableExprCgService::generate_expr_frame_info(ObTableCtx &ctx, common::ObIAllocator &allocator, ObExprFrameInfo &expr_frame_info) @@ -511,25 +637,16 @@ int ObTableExprCgService::generate_expr_frame_info(ObTableCtx &ctx, 0, 0, ctx.get_cur_cluster_version()); - - if (ctx.get_filter_exprs().empty()) { - if (OB_FAIL(expr_cg.generate(ctx.get_all_exprs(), expr_frame_info))) { - LOG_WARN("fail to generate expr frame info by expr cg", K(ret), K(ctx)); - } - } else { - ObRawExprUniqueSet exprs(false/* need_unique */); - if (OB_FAIL(exprs.append(ctx.get_all_exprs().get_expr_array()))) { - LOG_WARN("fail to append all exprs", K(ret), K(ctx.get_all_exprs().get_expr_array())); - } else if (OB_FAIL(exprs.append(ctx.get_filter_exprs()))) { - LOG_WARN("fail to append filter exprs", K(ret), K(ctx.get_filter_exprs())); - } else if (OB_FAIL(expr_cg.generate(exprs, expr_frame_info))) { - LOG_WARN("fail to generate expr frame info by expr cg", K(ret), K(ctx)); - } + if (OB_FAIL(add_extra_column_exprs(ctx))) { + LOG_WARN("fail to add extra column exprs", K(ret), K(ctx)); + } else if (OB_FAIL(expr_cg.generate(ctx.get_all_exprs(), expr_frame_info))) { + LOG_WARN("fail to generate expr frame info by expr cg", K(ret), K(ctx)); } return ret; } +// alloc expr's memory according to expr_frame_info. int ObTableExprCgService::alloc_exprs_memory(ObTableCtx &ctx, ObExprFrameInfo &expr_frame_info) { int ret = OB_SUCCESS; @@ -622,24 +739,10 @@ int ObTableLocCgService::generate_table_loc_meta(const ObTableCtx &ctx, } int ObTableExprCgService::refresh_update_exprs_frame(ObTableCtx &ctx, - const ObIArray &old_row, const ObIArray &new_row, - const ObIArray &full_assign_row, - const ObTableCtx::ObAssignIds &assign_ids, const ObTableEntity &entity) { - int ret = OB_SUCCESS; - - if (OB_FAIL(refresh_assign_exprs_frame(ctx, - old_row, - new_row, - full_assign_row, - assign_ids, - entity))) { - LOG_WARN("fail to refresh assign exprs frame", K(ret), K(assign_ids)); - } - - return ret; + return refresh_assign_exprs_frame(ctx, new_row, entity); } int ObTableExprCgService::refresh_ttl_exprs_frame(ObTableCtx &ctx, @@ -652,7 +755,7 @@ int ObTableExprCgService::refresh_ttl_exprs_frame(ObTableCtx &ctx, int ObTableExprCgService::refresh_insert_up_exprs_frame(ObTableCtx &ctx, const ObIArray &ins_new_row, - const ObIArray &delta_exprs, + const ObIArray &delta_row, const ObTableEntity &entity) { int ret = OB_SUCCESS; @@ -661,9 +764,9 @@ int ObTableExprCgService::refresh_insert_up_exprs_frame(ObTableCtx &ctx, if (OB_FAIL(refresh_rowkey_exprs_frame(ctx, ins_new_row, rowkey))) { LOG_WARN("fail to init rowkey exprs frame", K(ret), K(ctx), K(rowkey)); } else if (OB_FAIL(refresh_properties_exprs_frame(ctx, ins_new_row, entity))) { - LOG_WARN("fail to init properties exprs frame", K(ret), K(ctx)); - } else if (ctx.is_inc_or_append() && OB_FAIL(refresh_delta_exprs_frame(ctx, delta_exprs, entity))) { - LOG_WARN("fail to init delta exprs frame", K(ret), K(ctx)); + LOG_WARN("fail to init properties exprs frame", K(ret), K(ctx), K(ins_new_row), K(entity)); + } else if (ctx.is_inc_or_append() && OB_FAIL(refresh_delta_exprs_frame(ctx, delta_row, entity))) { + LOG_WARN("fail to init delta exprs frame", K(ret), K(ctx), K(delta_row), K(entity)); } return ret; @@ -721,6 +824,48 @@ int ObTableExprCgService::refresh_delete_exprs_frame(ObTableCtx &ctx, return ret; } +/* + write auto increment expr datum. + - auto increment expr tree: + auto increment expr + | + column conv expr + - specific value from user should fill to column conv expr. +*/ +int ObTableExprCgService::write_autoinc_datum(ObTableCtx &ctx, + const ObExpr &expr, + ObEvalCtx &eval_ctx, + const ObObj &obj) +{ + int ret = OB_SUCCESS; + + if (T_FUN_SYS_AUTOINC_NEXTVAL != expr.type_) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("invalid expr type", K(ret), K(expr)); + } else if (expr.arg_cnt_ != 1) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("invalid arg count for auto inc expr", K(ret), K(expr)); + } else if (expr.get_eval_info(eval_ctx).evaluated_ == true) { + // do nothing + } else { + const ObExpr *conlumn_conv_expr = expr.args_[0]; + if (OB_ISNULL(conlumn_conv_expr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("column conv expr below auto inc expr is null", K(ret)); + } else { + ObDatum &datum = conlumn_conv_expr->locate_datum_for_write(eval_ctx); + if (OB_FAIL(datum.from_obj(obj))) { + LOG_WARN("fail to convert object from datum", K(ret), K(obj)); + } else { + conlumn_conv_expr->get_eval_info(eval_ctx).evaluated_ = true; + conlumn_conv_expr->get_eval_info(eval_ctx).projected_ = true; + } + } + } + + return ret; +} + int ObTableExprCgService::write_datum(ObTableCtx &ctx, ObIAllocator &allocator, const ObExpr &expr, @@ -728,57 +873,17 @@ int ObTableExprCgService::write_datum(ObTableCtx &ctx, const ObObj &obj) { int ret = OB_SUCCESS; - const ObExpr *write_expr = &expr; if (is_lob_storage(obj.get_type()) && (obj.has_lob_header() != expr.obj_meta_.has_lob_header())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("fail to check lob header", K(ret), K(expr), K(obj)); - } else if (expr.type_ == T_FUN_COLUMN_CONV && ctx.has_auto_inc()) { // 为列转换表达式, 且为自增场景下 - if (expr.arg_cnt_ != 6) { - ret = OB_ERR_UNDEFINED; - LOG_WARN("invalid arg count for auto inc expr", K(ret), K(expr)); - } else { - const ObExpr *auto_inc_expr = expr.args_[4]; // 取出中间的列自增表达式 - if (OB_ISNULL(auto_inc_expr)) { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("auto inc expr is null", K(ret)); - } else if (auto_inc_expr->get_eval_info(eval_ctx).evaluated_ == true) { - // do nothing - } else if (auto_inc_expr->arg_cnt_ != 1) { - ret = OB_ERR_UNDEFINED; - LOG_WARN("invalid arg count for auto inc expr", K(ret), K(*auto_inc_expr)); - } else { - write_expr = auto_inc_expr->args_[0]; // 取出底部的列转换表达式 - if (OB_ISNULL(write_expr)) { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("column conv expr below auto inc expr is null", K(ret)); - } else { - // 用于生成自增主键冲突的列引用表达式,在write_datum时刷值 - ObExpr *auto_inc_ref_col_expr = write_expr->args_[4]; - if (OB_ISNULL(auto_inc_ref_col_expr)) { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("auto_inc_ref_col_expr is null", K(ret)); - } else { - ObDatum &datum = auto_inc_ref_col_expr->locate_datum_for_write(eval_ctx); - if (OB_FAIL(datum.from_obj(obj))) { - LOG_WARN("fail to convert object from datum", K(ret), K(obj)); - } else { - auto_inc_ref_col_expr->get_eval_info(eval_ctx).evaluated_ = true; - auto_inc_ref_col_expr->get_eval_info(eval_ctx).projected_ = true; - } - } - } - } - } - } - - if (OB_SUCC(ret)) { - ObDatum &datum = write_expr->locate_datum_for_write(eval_ctx); + } else { + ObDatum &datum = expr.locate_datum_for_write(eval_ctx); if (OB_FAIL(datum.from_obj(obj))) { LOG_WARN("fail to convert object from datum", K(ret), K(obj)); } else { - write_expr->get_eval_info(eval_ctx).evaluated_ = true; - write_expr->get_eval_info(eval_ctx).projected_ = true; + expr.get_eval_info(eval_ctx).evaluated_ = true; + expr.get_eval_info(eval_ctx).projected_ = true; } } @@ -801,217 +906,130 @@ int ObTableExprCgService::refresh_exprs_frame(ObTableCtx &ctx, return ret; } -// exprs必须是按照schema序的完整行 +/* + refresh rowkey frame + 1. The number of entity's rowkey may not equal the number of schema's rowkey + when there is auto_increment column in primary keys. + 2. auto_increment expr tree is autoinc_nextval_expr - column_conv_expr, + we need to fill value to column_conv_expr when user had set value. + 3. "IS_DEFAULT_NOW_OBJ(item.default_value_)" means default current_timestamp in column, + we need to fill eval current timestamp when user not fill value. +*/ int ObTableExprCgService::refresh_rowkey_exprs_frame(ObTableCtx &ctx, const ObIArray &exprs, const ObIArray &rowkey) { int ret = OB_SUCCESS; + const ObIArray &items = ctx.get_column_items(); const int64_t schema_rowkey_cnt = ctx.get_table_schema()->get_rowkey_column_num(); const int64_t entity_rowkey_cnt = rowkey.count(); + bool is_full_filled = (schema_rowkey_cnt == entity_rowkey_cnt); // did user fill all rowkey columns or not ObEvalCtx eval_ctx(ctx.get_exec_ctx()); - bool is_full_filled = schema_rowkey_cnt == entity_rowkey_cnt; - // 不存在自增列的情况下,按照用户的值填datum - // 存在自增列,用户填了值的情况下,使用用户的值刷datum - // 存在自增列,用户没有填值的情况下,使用null obj刷datum - // idx 是为了在主键中存在自增列是为了解决使用i访问obj_ptr会出现访问越界的问题,因为在主键存在自增列场景下,用户可以 - // 不填自增列值,这时rowkey中的obj数量少于schema上的rowkey数量 - for (int64_t i = 0, idx = 0; OB_SUCC(ret) && i < schema_rowkey_cnt; i++) { + if (exprs.count() < schema_rowkey_cnt) { + ret = OB_ERR_UNDEFINED; + LOG_WARN("invalid expr count", K(ret), K(exprs), K(schema_rowkey_cnt)); + } else if (items.count() < schema_rowkey_cnt) { + ret = OB_ERR_UNDEFINED; + LOG_WARN("invalid column item count", K(ret), K(items), K(schema_rowkey_cnt)); + } + + for (int64_t i = 0, rowkey_idx = 0; OB_SUCC(ret) && i < schema_rowkey_cnt; i++) { + const ObTableColumnItem &item = items.at(i); const ObExpr *expr = exprs.at(i); - if (OB_ISNULL(expr)) { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("expr is null", K(ret)); - } else if (ctx.has_auto_inc() && !is_full_filled && expr->type_ == T_FUN_COLUMN_CONV) { // 自增列,用户未填值 + if (T_FUN_SYS_AUTOINC_NEXTVAL == expr->type_) { ObObj null_obj; null_obj.set_null(); - if (OB_FAIL(write_datum(ctx, ctx.get_allocator(), *expr, eval_ctx, null_obj))) { - LOG_WARN("fail to write datum", K(ret), K(rowkey.at(i)), K(*expr)); + const ObObj *tmp_obj = is_full_filled ? &rowkey.at(rowkey_idx) : &null_obj; + if (OB_FAIL(write_autoinc_datum(ctx, *expr, eval_ctx, *tmp_obj))) { + LOG_WARN("fail to write auto increment datum", K(ret), K(is_full_filled), K(*expr), K(*tmp_obj)); + } + if (is_full_filled) { + rowkey_idx++; + } + } else if (!is_full_filled && IS_DEFAULT_NOW_OBJ(item.default_value_)) { + ObDatum *tmp_datum = nullptr; + if (OB_FAIL(expr->eval(eval_ctx, tmp_datum))) { + LOG_WARN("fail to eval current timestamp expr", K(ret)); } - } else if (idx >= entity_rowkey_cnt) { - ret = OB_INDEX_OUT_OF_RANGE; - LOG_WARN("idx out of range", K(ret), K(idx), K(entity_rowkey_cnt)); - } else if (OB_FAIL(write_datum(ctx, ctx.get_allocator(), *expr, eval_ctx, rowkey.at(idx)))) { - LOG_WARN("fail to write datum", K(ret), K(rowkey.at(i)), K(*expr)); } else { - idx++; + if (rowkey_idx >= entity_rowkey_cnt) { + ret = OB_INDEX_OUT_OF_RANGE; + LOG_WARN("idx out of range", K(ret), K(i), K(entity_rowkey_cnt)); + } else if (OB_ISNULL(expr)) { + ret = OB_ERR_UNDEFINED; + LOG_WARN("expr is null", K(ret)); + } else if (OB_FAIL(write_datum(ctx, ctx.get_allocator(), *expr, eval_ctx, rowkey.at(rowkey_idx)))) { + LOG_WARN("fail to write datum", K(ret), K(rowkey_idx), K(rowkey.at(rowkey_idx)), K(*expr)); + } else { + rowkey_idx++; + } } } return ret; } -// exprs必须是按照schema序的完整行 +/* + refresh properties's exprs frame. + - generate column expr eval. + - auto increment expr fill user value or null obj to child expr(column conv expr). + - current timestamp expr eval if user not fill value. + - column ref expr fill user value or default value. +*/ int ObTableExprCgService::refresh_properties_exprs_frame(ObTableCtx &ctx, const ObIArray &exprs, const ObTableEntity &entity) { int ret = OB_SUCCESS; + const ObIArray &items = ctx.get_column_items(); const ObTableSchema *table_schema = ctx.get_table_schema(); ObEvalCtx eval_ctx(ctx.get_exec_ctx()); if (OB_ISNULL(table_schema)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("table schema is null", K(ret)); + } else if (items.count() < table_schema->get_column_count()) { + ret = OB_ERR_UNDEFINED; + LOG_WARN("invalid column item count", K(ret), K(items), K(table_schema->get_column_count())); + } else if (exprs.count() < table_schema->get_column_count()) { + ret = OB_ERR_UNDEFINED; + LOG_WARN("invalid expr count", K(ret), K(exprs), K(table_schema->get_column_count())); } else { ObObj prop_value; - ObObj *obj = nullptr; + const ObObj *obj = nullptr; const int64_t rowkey_column_cnt = table_schema->get_rowkey_column_num(); - for (int64_t i = rowkey_column_cnt; OB_SUCC(ret) && i < exprs.count(); i++) { + for (int64_t i = rowkey_column_cnt; OB_SUCC(ret) && i < items.count(); i++) { + const ObTableColumnItem &item = items.at(i); const ObExpr *expr = exprs.at(i); - const ObColumnSchemaV2 *col_schema = nullptr; - if (OB_ISNULL(col_schema = table_schema->get_column_schema_by_idx(i))) { - ret = OB_SCHEMA_ERROR; - LOG_WARN("fail to get column schema", K(ret), K(i), K(*table_schema)); - } else if (col_schema->is_generated_column()) { // 生成列需要eval一次 + if (item.is_generated_column_) { // generate column need eval first ObDatum *tmp_datum = nullptr; if (OB_FAIL(expr->eval(eval_ctx, tmp_datum))) { LOG_WARN("fail to eval generate expr", K(ret)); } } else { - const ObString &col_name = col_schema->get_column_name_str(); // 这里使用schema的列名在entity中查找property,有可能出现本身entity中的prop_name是不对的,导致找不到 - bool use_default = (OB_SEARCH_NOT_FOUND == entity.get_property(col_name, prop_value)); - if (use_default) { - obj = const_cast(&col_schema->get_cur_default_value()); + bool not_found = (OB_SEARCH_NOT_FOUND == entity.get_property(item.column_name_, prop_value)); + if (not_found) { + obj = &item.default_value_; } else { obj = &prop_value; } - if (OB_FAIL(write_datum(ctx, ctx.get_allocator(), *expr, eval_ctx, *obj))) { - LOG_WARN("fail to write datum", K(ret), K(*obj), K(*expr)); - } - } - } - } - - return ret; -} - -// 将生成列引用的,并且entity没有填充的列刷成旧值 -// eg: create table t(c1 int primary key, -// c2 varchar(10), -// c3 varchar(10), -// gen varchar(30) generated always as (concat(c2,c3)) stored); -// update t set c3 = ? where c1 = ?; -// full row: c1(old) | c2(old) | c3(old) | gen(old) concat(c1(old), c2(old)) -// c1(new) | c2(new) | c3(new) | gen(new) concat(c1(new), c2(new)) -// 这个时候,只是更新了c3的值,gen引用的是c2,c3的值,这里将c2(old)填到c2(new)中 -int ObTableExprCgService::refresh_generated_column_related_frame(ObTableCtx &ctx, - const ObIArray &old_row, - const ObIArray &full_assign_row, - const ObTableCtx::ObAssignIds &assign_ids, - const ObColumnSchemaV2 &col_schema) -{ - int ret = OB_SUCCESS; - const ObTableSchema *table_schema = ctx.get_table_schema(); - ObEvalCtx eval_ctx(ctx.get_exec_ctx()); - ObArray schema_column_ids; - ObArray ref_column_ids; - - if (!col_schema.is_stored_generated_column()) { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("invalid expr", K(ret), K(col_schema)); - } else if (OB_ISNULL(table_schema)) { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("table schema is null", K(ret)); - } else if (OB_FAIL(table_schema->get_column_ids(schema_column_ids))) { - LOG_WARN("fail to get schema column ids", K(ret)); - } else if (OB_FAIL(col_schema.get_cascaded_column_ids(ref_column_ids))) { - LOG_WARN("fail to get cascade column ids", K(ret)); - } else { - ObArray not_upd_col_ids; - // 查询生成列依赖的列是否都被更新,记下未被更新的列到not_upd_col_ids - for (int64_t i = 0; OB_SUCC(ret) && i < ref_column_ids.count(); i++) { - bool found = false; - uint64_t col_id = ref_column_ids.at(i); - for (int64_t j = 0; OB_SUCC(ret) && j < assign_ids.count() && !found; j++) { - if (col_id == assign_ids.at(j).column_id_) { - found = true; - } - } - if (!found && OB_FAIL(not_upd_col_ids.push_back(col_id))) { - LOG_WARN("fail to push back not update column id", K(ret), K(col_id)); - } - } - - // 通过column id找到old row对应的列 - for (int64_t i = 0; OB_SUCC(ret) && i < not_upd_col_ids.count(); i++) { - for (int64_t j = 0; OB_SUCC(ret) && j < schema_column_ids.count(); j++) { - if (schema_column_ids.at(j) == not_upd_col_ids.at(i)) { - if (j >= old_row.count()) { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("invalid column id", K(ret), K(j), K(old_row.count())); - } else if (j >= full_assign_row.count()) { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("invalid column id", K(ret), K(j), K(full_assign_row.count())); - } else { - ObExpr *old_expr = old_row.at(j); - ObExpr *new_expr = full_assign_row.at(j); - new_expr->locate_expr_datum(eval_ctx) = old_expr->locate_expr_datum(eval_ctx); - new_expr->get_eval_info(eval_ctx).evaluated_ = true; - new_expr->get_eval_info(eval_ctx).projected_ = true; + if (T_FUN_SYS_AUTOINC_NEXTVAL == expr->type_) { + ObObj null_obj; + null_obj.set_null(); + obj = not_found ? &null_obj : &prop_value; + if (OB_FAIL(write_autoinc_datum(ctx, *expr, eval_ctx, *obj))) { + LOG_WARN("fail to write auto increment datum", K(ret), K(not_found), K(*expr), K(*obj)); } - } - } - } - } - - return ret; -} - -int ObTableExprCgService::refresh_assign_exprs_frame(ObTableCtx &ctx, - const ObIArray &old_row, - const ObIArray &new_row, - const ObIArray &full_assign_row, - const ObTableCtx::ObAssignIds &assign_ids, - const ObTableEntity &entity) -{ - int ret = OB_SUCCESS; - const ObTableSchema *table_schema = ctx.get_table_schema(); - ObEvalCtx eval_ctx(ctx.get_exec_ctx()); - - if (OB_ISNULL(table_schema)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("table schema is null", K(ret)); - } else { - ObObj prop_value; - const int64_t N = assign_ids.count(); - for (int64_t i = 0; OB_SUCC(ret) && i < N; i++) { - const ObColumnSchemaV2 *col_schema = nullptr; - uint64_t assign_id = assign_ids.at(i).idx_; - if (OB_ISNULL(col_schema = table_schema->get_column_schema_by_idx(assign_id))) { - ret = OB_SCHEMA_ERROR; - LOG_WARN("fail to get column schema", K(ret), K(assign_id), K(*table_schema)); - } else if (col_schema->is_virtual_generated_column()) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("should not have virtual generated expr", K(ret)); - } else if (col_schema->is_stored_generated_column()) { - if (OB_FAIL(refresh_generated_column_related_frame(ctx, - old_row, - full_assign_row, - assign_ids, - *col_schema))) { - LOG_WARN("fail to refresh generated column related frame", K(ret)); - } else { // 计算一次 - ObExpr *expr = full_assign_row.at(assign_id); + } else if (not_found && IS_DEFAULT_NOW_OBJ(item.default_value_)) { ObDatum *tmp_datum = nullptr; if (OB_FAIL(expr->eval(eval_ctx, tmp_datum))) { - LOG_WARN("fail to eval datum", K(ret), K(*expr)); + LOG_WARN("fail to eval current timestamp expr", K(ret)); } - } - } else if (OB_FAIL(entity.get_property(col_schema->get_column_name_str(), prop_value))) { - LOG_WARN("fail to get assign propertity value", K(ret), K(col_schema->get_column_name_str())); - } else { - if (assign_id >= new_row.count()) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("invalid assign idx", K(ret), K(assign_id), K(new_row.count())); } else { - const ObExpr *expr = new_row.at(assign_id); - if (OB_ISNULL(expr)) { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("expr is null", K(ret)); - } else if (OB_FAIL(write_datum(ctx, ctx.get_allocator(), *expr, eval_ctx, prop_value))) { - LOG_WARN("fail to write datum", K(ret), K(prop_value), K(*expr)); + if (OB_FAIL(write_datum(ctx, ctx.get_allocator(), *expr, eval_ctx, *obj))) { + LOG_WARN("fail to write datum", K(ret), K(*obj), K(*expr)); } } } @@ -1021,34 +1039,101 @@ int ObTableExprCgService::refresh_assign_exprs_frame(ObTableCtx &ctx, return ret; } + +// refresh delta expr's frame with user specific value. int ObTableExprCgService::refresh_delta_exprs_frame(ObTableCtx &ctx, - const ObIArray &delta_exprs, + const ObIArray &delta_row, const ObTableEntity &entity) { int ret = OB_SUCCESS; - const ObTableSchema *table_schema = ctx.get_table_schema(); + const ObIArray &assigns = ctx.get_assignments(); ObEvalCtx eval_ctx(ctx.get_exec_ctx()); + ObObj prop_value; if (!ctx.is_inc_or_append()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid operation type", K(ret), K(ctx)); - } else if (OB_ISNULL(table_schema)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("table schema is null", K(ret)); + } else if (delta_row.count() > assigns.count()) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid delta row length", K(ret), K(delta_row), K(assigns)); } else { - ObObj prop_value; - const ObTableCtx::ObAssignIds &assign_ids = ctx.get_assign_ids(); - const int64_t N = assign_ids.count(); - for (int64_t i = 0; OB_SUCC(ret) && i < N; i++) { - const ObColumnSchemaV2 *col_schema = nullptr; - uint64_t column_id = assign_ids.at(i).column_id_; - if (OB_ISNULL(col_schema = table_schema->get_column_schema(column_id))) { - ret = OB_SCHEMA_ERROR; - LOG_WARN("fail to get column schema", K(ret), K(column_id), K(*table_schema)); - } else if (OB_FAIL(entity.get_property(col_schema->get_column_name_str(), prop_value))) { - LOG_WARN("fail to get assign propertity value", K(ret), K(col_schema->get_column_name_str())); + for (int64_t i = 0, idx = 0; OB_SUCC(ret) && i < assigns.count(); i++) { + const ObTableAssignment &assign = assigns.at(i); + if (OB_ISNULL(assign.column_item_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("assign column item is null", K(ret), K(assign)); + } else if (assign.column_item_->auto_filled_timestamp_) { + // do nothing + } else if (idx >= delta_row.count()) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("index out of range", K(ret), K(assign), K(delta_row)); } else { - const ObExpr *expr = delta_exprs.at(i); + bool not_found = (OB_SEARCH_NOT_FOUND == entity.get_property(assign.column_item_->column_name_, prop_value)); + const ObExpr *expr = delta_row.at(idx); + if (OB_ISNULL(expr)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("expr is null", K(ret)); + } else if (not_found) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("not found delta value", K(ret), K(assign)); + } else if (OB_FAIL(write_datum(ctx, ctx.get_allocator(), *expr, eval_ctx, prop_value))) { + LOG_WARN("fail to write datum", K(ret), K(prop_value), K(*expr)); + } else { + idx++; + } + } + } + } + + return ret; +} + +/* + refresh assign expr's frame when do update. + - assign virtual generated column is not support. + - eval current timestamp expr if user not assign specific value. + - fill other expr's datum with user value. +*/ +int ObTableExprCgService::refresh_assign_exprs_frame(ObTableCtx &ctx, + const ObIArray &new_row, + const ObTableEntity &entity) +{ + int ret = OB_SUCCESS; + const ObIArray &assigns = ctx.get_assignments(); + ObEvalCtx eval_ctx(ctx.get_exec_ctx()); + ObObj prop_value; + + for (int64_t i = 0; OB_SUCC(ret) && i < assigns.count(); i++) { + const ObTableAssignment &assign = assigns.at(i); + if (OB_ISNULL(assign.column_item_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("assign column item is null", K(ret), K(assign)); + } else if (new_row.count() < assign.column_item_->col_idx_) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected assign projector_index_", K(ret), K(new_row), K(assign.column_item_)); + } else if (assign.column_item_->is_virtual_generated_column_) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("virtual generated column not support to update", K(ret), K(assign)); + } else { + // on update current timestamp will not find value + bool not_found = (OB_SEARCH_NOT_FOUND == entity.get_property(assign.column_item_->column_name_, prop_value)); + const ObExpr *expr = new_row.at(assign.column_item_->col_idx_); + if (OB_ISNULL(expr)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("expr is null", K(ret)); + } else if (not_found) { + if (!assign.column_item_->auto_filled_timestamp_ && !assign.column_item_->is_stored_generated_column_) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("fail to get assign propertity value", K(ret), K(assign)); + } else if (assign.column_item_->is_stored_generated_column_) { + // do nothing, stored generated column not need to fill + } else { // on update current timestamp + ObDatum *tmp_datum = nullptr; + if (OB_FAIL(expr->eval(eval_ctx, tmp_datum))) { + LOG_WARN("fail to eval current timestamp expr", K(ret)); + } + } + } else { // found if (OB_FAIL(write_datum(ctx, ctx.get_allocator(), *expr, eval_ctx, prop_value))) { LOG_WARN("fail to write datum", K(ret), K(prop_value), K(*expr)); } @@ -1059,35 +1144,53 @@ int ObTableExprCgService::refresh_delta_exprs_frame(ObTableCtx &ctx, return ret; } -int ObTableDmlCgService::replace_exprs_with_dependant(const ObIArray &src_exprs, +/* + create table t(c1 int primary key, + c2 varchar(10), + c3 varchar(10), + c4 varchar(30) generated always as (concat(c2, c3))); + generated expr: c4 + dependant_expr: concat(`c2`, `c3`) + DAS need dependant_expr to calculate result, so we use dependant_expr. +*/ +int ObTableDmlCgService::replace_exprs_with_dependant(ObTableCtx &ctx, ObIArray &dst_exprs) { int ret = OB_SUCCESS; - for (int64_t i = 0; i < src_exprs.count() && OB_SUCC(ret); i++) { - ObRawExpr *expr = src_exprs.at(i); - if (OB_ISNULL(expr)) { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("expr is null", K(ret)); - } else if (expr->is_column_ref_expr()) { - ObColumnRefRawExpr *col_ref_expr = static_cast(expr); - if (col_ref_expr->is_generated_column()) { - expr = col_ref_expr->get_dependant_expr(); - } - if (OB_FAIL(dst_exprs.push_back(expr))) { - LOG_WARN("fail to push back expr", K(ret), K(dst_exprs)); - } - } else if (expr->get_expr_type() == T_FUN_COLUMN_CONV) { // 兼容自增场景下的列转换表达式 - if (OB_FAIL(dst_exprs.push_back(expr))) { - LOG_WARN("fail to push back expr", K(ret), K(dst_exprs)); - } + const ObIArray &all_exprs = ctx.get_all_exprs_array(); + ObIArray &items = ctx.get_column_items(); + + if (all_exprs.count() < items.count()) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("invalid expr count", K(ret), K(all_exprs), K(items)); + } + + for (int64_t i = 0; i < items.count() && OB_SUCC(ret); i++) { + const ObTableColumnItem &item = items.at(i); + ObRawExpr *tmp_expr = nullptr; + if (item.is_generated_column_) { + ObColumnRefRawExpr *col_ref_expr = static_cast(all_exprs.at(i)); + tmp_expr = col_ref_expr->get_dependant_expr(); } else { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("invalid expr type", K(ret), K(*expr)); + tmp_expr = all_exprs.at(i); + } + if (OB_FAIL(dst_exprs.push_back(tmp_expr))) { + LOG_WARN("fail to push back expr", K(ret)); } } + return ret; } +/* + genreate insert ctdef + - replace exprs with depenedant expr if there are generated column. + - construct new row. + - old row is empty in insert ctdef + - generate base ctdef which include column_ids, old_row and new_row. + - generate das insert ctdef which include projector, table_id and so on. + - generate related(index) insert ctdef. +*/ int ObTableDmlCgService::generate_insert_ctdef(ObTableCtx &ctx, ObIAllocator &allocator, ObTableInsCtDef &ins_ctdef) @@ -1095,17 +1198,13 @@ int ObTableDmlCgService::generate_insert_ctdef(ObTableCtx &ctx, int ret = OB_SUCCESS; ObSEArray old_row; ObSEArray new_row; - const ObIArray &exprs = ctx.is_for_insertup() ? - ctx.get_old_row_exprs() : ctx.get_all_exprs().get_expr_array(); ObSEArray tmp_exprs; - if (OB_FAIL(replace_exprs_with_dependant(exprs, tmp_exprs))) { - LOG_WARN("fail to replace exprs with dependant", K(ret), K(exprs)); + + if (OB_FAIL(replace_exprs_with_dependant(ctx, tmp_exprs))) { + LOG_WARN("fail to replace exprs with dependant", K(ret), K(ctx)); } else if (OB_FAIL(new_row.assign(tmp_exprs))) { LOG_WARN("fail to assign new row", K(ret)); - } else if (OB_FAIL(generate_base_ctdef(ctx, - ins_ctdef, - old_row, - new_row))) { + } else if (OB_FAIL(generate_base_ctdef(ctx, ins_ctdef, old_row, new_row))) { LOG_WARN("fail to generate dml base ctdef", K(ret)); } else if (OB_FAIL(generate_das_ins_ctdef(ctx, ctx.get_ref_table_id(), @@ -1122,76 +1221,59 @@ int ObTableDmlCgService::generate_insert_ctdef(ObTableCtx &ctx, return ret; } +/* + create table t(c1 int primary key, c2 int default null, c3 int default null); + insert into t values(1,1,1); + update t set c3=2 where c1=1; + + assign expr: c3' + old row: c1, c2, c3 + new row: c1, c2, c3' + full row: c1, c2, c3, c3' +*/ int ObTableDmlCgService::generate_update_ctdef(ObTableCtx &ctx, ObIAllocator &allocator, - const ObTableCtx::ObAssignIds &assign_ids, ObTableUpdCtDef &upd_ctdef) { int ret = OB_SUCCESS; ObSEArray old_row; ObSEArray new_row; ObSEArray full_row; - ObSEArray assign_exprs; + ObSEArray delta_row; ObStaticEngineCG cg(ctx.get_cur_cluster_version()); - ObIArray &old_exprs = ctx.get_old_row_exprs(); ObSEArray tmp_old_exprs; ObSEArray tmp_full_assign_exprs; - if (OB_FAIL(replace_exprs_with_dependant(old_exprs, tmp_old_exprs))) { - LOG_WARN("fail to replace exprs with dependant", K(ret), K(old_exprs)); + if (OB_FAIL(replace_exprs_with_dependant(ctx, tmp_old_exprs))) { + LOG_WARN("fail to replace exprs with dependant", K(ret)); } else if (OB_FAIL(old_row.assign(tmp_old_exprs))) { LOG_WARN("fail to assign old row expr", K(ret)); } else if (OB_FAIL(new_row.assign(old_row))) { LOG_WARN("fail to assign new row", K(ret)); } else if (OB_FAIL(append(full_row, old_row))) { LOG_WARN("fail to append old row expr to full row", K(ret), K(old_row)); - } else if (OB_FAIL(ObTableExprCgService::generate_assign_exprs(ctx, assign_ids, assign_exprs))) { - LOG_WARN("fail to generate assign exprs", K(ret), K(ctx), K(assign_ids)); } else { - ObColumnRefRawExpr *col_ref_expr = nullptr; - for (int64_t i = 0; OB_SUCC(ret) && i < assign_exprs.count(); i++) { - ObRawExpr *expr = assign_exprs.at(i); - if (OB_ISNULL(expr)) { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("expr is null", K(ret)); - } else if (expr->get_expr_type() == T_FUN_COLUMN_CONV && ctx.has_auto_inc()) { // 兼容自增场景下的列转换表达式 - if (OB_FAIL(full_row.push_back(expr))) { - LOG_WARN("fail to add assign expr to full row", K(ret), K(i)); - } - for (int64_t j = 0; OB_SUCC(ret) && j < old_exprs.count(); j++) { - if (old_exprs.at(j)->get_expr_type() == T_FUN_COLUMN_CONV) { - new_row.at(j) = expr; - } - } + ObRawExpr *tmp_expr = nullptr; + ObIArray &assigns = ctx.get_assignments(); + for (int64_t i = 0; OB_SUCC(ret) && i < assigns.count(); i++) { + const ObTableAssignment &assign = assigns.at(i); + if (assign.column_expr_->is_generated_column()) { + tmp_expr = assign.column_expr_->get_dependant_expr(); } else { - if (!expr->is_column_ref_expr()) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpected expr type", K(ret), K(*expr)); - } else if (FALSE_IT(col_ref_expr = static_cast(expr))) { - } else if (col_ref_expr->is_generated_column()) { - expr = col_ref_expr->get_dependant_expr(); - } - if (OB_FAIL(ret)) { - } else if (OB_FAIL(full_row.push_back(expr))) { - LOG_WARN("fail to add assign expr to full row", K(ret), K(i)); - } else { - ObColumnRefRawExpr *old_col_expr = nullptr; - for (int64_t j = 0; OB_SUCC(ret) && j < old_exprs.count(); j++) { - ObRawExpr *old_expr = old_exprs.at(j); - if (OB_ISNULL(old_expr)) { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("old_expr is null", K(ret)); - } else if (!old_expr->is_column_ref_expr() && (old_expr->get_expr_type() != T_FUN_COLUMN_CONV)) { // 兼容自增场景下的列转换表达式 - ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpected expr type", K(ret), K(*old_exprs.at(i))); - } else if (old_expr->get_expr_type() == T_FUN_COLUMN_CONV) { - // do nothing - } else if (FALSE_IT(old_col_expr = static_cast(old_expr))) { - } else if (old_col_expr->get_column_id() == col_ref_expr->get_column_id()) { - new_row.at(j) = expr; - } - } - } + tmp_expr = assign.expr_; + } + if (OB_FAIL(full_row.push_back(tmp_expr))) { + LOG_WARN("fail to add assign expr to full row", K(ret), K(i)); + } else if (assign.is_inc_or_append_ && OB_FAIL(delta_row.push_back(assign.delta_expr_))) { + LOG_WARN("fail to add delta expr to delta row", K(ret), K(assign)); + } else if (OB_ISNULL(assign.column_item_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("assign column item is null", K(ret), K(assign)); + } else if (assign.column_item_->col_idx_ >= new_row.count()) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("invalid column index", K(ret), K(assign), K(new_row)); + } else { + new_row.at(assign.column_item_->col_idx_) = tmp_expr; } } } @@ -1205,15 +1287,10 @@ int ObTableDmlCgService::generate_update_ctdef(ObTableCtx &ctx, LOG_WARN("fail to generate dml base ctdef", K(ret)); } else if (OB_FAIL(cg.generate_rt_exprs(full_row, upd_ctdef.full_row_))) { LOG_WARN("fail to generate dml update full row exprs", K(ret), K(full_row)); - } else if (OB_FAIL(replace_exprs_with_dependant(ctx.get_full_assign_exprs(), tmp_full_assign_exprs))) { - LOG_WARN("fail to replace exprs with dependant", K(ret)); - } else if (OB_FAIL(cg.generate_rt_exprs(tmp_full_assign_exprs, upd_ctdef.full_assign_row_))) { - LOG_WARN("fail to generate full assign row exprs", K(ret)); - } else if (ctx.is_inc_or_append() && OB_FAIL(cg.generate_rt_exprs(ctx.get_delta_exprs(), upd_ctdef.delta_exprs_))) { - LOG_WARN("fail to generate delta exprs", K(ret)); + } else if (!delta_row.empty() && OB_FAIL(cg.generate_rt_exprs(delta_row, upd_ctdef.delta_row_))) { + LOG_WARN("fail to generate dml update delta row exprs", K(ret), K(delta_row)); } else if (OB_FAIL(generate_das_upd_ctdef(ctx, ctx.get_ref_table_id(), - assign_exprs, upd_ctdef.das_ctdef_, old_row, new_row, @@ -1221,19 +1298,16 @@ int ObTableDmlCgService::generate_update_ctdef(ObTableCtx &ctx, LOG_WARN("fail to generate das upd ctdef", K(ret)); } else if (OB_FAIL(generate_related_upd_ctdef(ctx, allocator, - assign_exprs, old_row, new_row, full_row, upd_ctdef.related_ctdefs_))) { LOG_WARN("fail to generate related upd ctdef", K(ret)); - } else if (OB_FAIL(generate_upd_assign_infos(ctx, allocator, assign_exprs, upd_ctdef))) { + } else if (OB_FAIL(generate_upd_assign_infos(ctx, allocator, upd_ctdef))) { LOG_WARN("fail to generate related upd assign info", K(ret)); } - if (OB_FAIL(ret)) { - // do nothing - } else if (ctx.is_for_insertup()) { + if (OB_SUCC(ret) && ctx.is_for_insertup()) { ObDMLCtDefAllocator ddel_allocator(allocator); ObDMLCtDefAllocator dins_allocator(allocator); if (OB_ISNULL(upd_ctdef.ddel_ctdef_ = ddel_allocator.alloc())) { @@ -1270,7 +1344,6 @@ int ObTableDmlCgService::generate_update_ctdef(ObTableCtx &ctx, int ObTableDmlCgService::generate_das_upd_ctdef(ObTableCtx &ctx, uint64_t index_tid, - const ObIArray &assign_exprs, ObDASUpdCtDef &das_upd_ctdef, const ObIArray &old_row, const ObIArray &new_row, @@ -1281,14 +1354,9 @@ int ObTableDmlCgService::generate_das_upd_ctdef(ObTableCtx &ctx, if (OB_FAIL(generate_das_base_ctdef(index_tid, ctx, das_upd_ctdef))) { LOG_WARN("fail to generate das dml ctdef", K(ret)); - } else if (OB_FAIL(generate_updated_column_ids(ctx, - assign_exprs, - das_upd_ctdef.column_ids_, - das_upd_ctdef.updated_column_ids_))) { + } else if (OB_FAIL(generate_updated_column_ids(ctx, das_upd_ctdef.updated_column_ids_))) { LOG_WARN("fail to add updated column ids", K(ret)); - } else if (OB_FAIL(generate_column_ids(ctx, - ctx.get_old_row_exprs(), - dml_column_ids))) { + } else if (OB_FAIL(generate_column_ids(ctx, dml_column_ids))) { LOG_WARN("fail to generate dml column ids", K(ret)); } else if (OB_FAIL(generate_projector(dml_column_ids, // new row and old row's columns id das_upd_ctdef.column_ids_, // schmea column ids for given index_tid @@ -1303,34 +1371,22 @@ int ObTableDmlCgService::generate_das_upd_ctdef(ObTableCtx &ctx, } int ObTableDmlCgService::generate_updated_column_ids(ObTableCtx &ctx, - const ObIArray &assign_exprs, - const ObIArray &column_ids, ObIArray &updated_column_ids) { int ret = OB_SUCCESS; + ObIArray &assigns = ctx.get_assignments(); updated_column_ids.reset(); - if (!assign_exprs.empty()) { - if (OB_FAIL(updated_column_ids.reserve(assign_exprs.count()))) { - LOG_WARN("fail to init updated column ids array", K(ret), K(assign_exprs.count())); - } else { - ObColumnRefRawExpr *col_expr = NULL; - for (int64_t i = 0; OB_SUCC(ret) && i < assign_exprs.count(); i++) { - if (assign_exprs.at(i)->get_expr_type() == T_FUN_COLUMN_CONV && ctx.has_auto_inc()) { // 兼容自增场景下的列转换表达式 - if (OB_FAIL(updated_column_ids.push_back(ctx.get_auto_inc_column_id()))) { - LOG_WARN("fail to add updated column id", K(ret), K(ctx.get_auto_inc_column_id())); - } - } else { - if (!assign_exprs.at(i)->is_column_ref_expr()) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpected expr type", K(ret), K(assign_exprs.at(i)->get_expr_type())); - } else if (FALSE_IT(col_expr = static_cast(assign_exprs.at(i)))) { - } else if (!has_exist_in_array(column_ids, col_expr->get_column_id())) { - //not found in column ids, ignore it - } else if (OB_FAIL(updated_column_ids.push_back(col_expr->get_column_id()))) { - LOG_WARN("fail to add updated column id", K(ret), K(col_expr->get_column_id())); - } - } + if (OB_FAIL(updated_column_ids.reserve(assigns.count()))) { + LOG_WARN("fail to init updated column ids array", K(ret), K(assigns.count())); + } else { + for (int64_t i = 0; OB_SUCC(ret) && i < assigns.count(); i++) { + const ObTableAssignment &assign = assigns.at(i); + if (OB_ISNULL(assign.column_item_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("assign column item is null", K(ret), K(assign)); + } else if (OB_FAIL(updated_column_ids.push_back(assign.column_item_->column_id_))) { + LOG_WARN("fail to add updated column id", K(ret), K(assign)); } } } @@ -1340,56 +1396,38 @@ int ObTableDmlCgService::generate_updated_column_ids(ObTableCtx &ctx, int ObTableDmlCgService::generate_upd_assign_infos(ObTableCtx &ctx, ObIAllocator &allocator, - const ObIArray &assign_exprs, ObTableUpdCtDef &udp_ctdef) { int ret = OB_SUCCESS; - int64_t assign_cnt = assign_exprs.count(); + ObIArray &assigns = ctx.get_assignments(); + int64_t assign_cnt = assigns.count(); ColContentFixedArray &assign_infos = udp_ctdef.assign_columns_; if (OB_FAIL(assign_infos.init(assign_cnt))) { LOG_WARN("fail to init assign info array", K(ret), K(assign_cnt)); } for (int64_t i = 0; OB_SUCC(ret) && i < assign_cnt; ++i) { + const ObTableAssignment &assign = assigns.at(i); ColumnContent column_content; int64_t idx = 0; - if (assign_exprs.at(i)->get_expr_type() == T_FUN_COLUMN_CONV && ctx.has_auto_inc()) { // 兼容自增场景下的列转换表达式 - column_content.auto_filled_timestamp_ = false; - column_content.is_nullable_ = false; - column_content.is_predicate_column_ = false; - column_content.is_implicit_ = false; - if (OB_FAIL(ob_write_string(allocator, - ctx.get_auto_inc_column_name(), - column_content.column_name_))) { - LOG_WARN("fail to copy column name", K(ret), K(ctx.get_auto_inc_column_name())); - } else if (!has_exist_in_array(udp_ctdef.das_ctdef_.column_ids_, ctx.get_auto_inc_column_id(), &idx)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("assign column not exists in old column", K(ret), K(ctx.get_auto_inc_column_name())); - } else if (FALSE_IT(column_content.projector_index_ = static_cast(idx))) { - //do nothing - } else if (OB_FAIL(assign_infos.push_back(column_content))) { - LOG_WARN("fail to store colum content to assign infos", K(ret), K(column_content)); - } - } else { - ObColumnRefRawExpr *col = static_cast(assign_exprs.at(i)); - column_content.auto_filled_timestamp_ = col->get_result_type().has_result_flag(ON_UPDATE_NOW_FLAG); - column_content.is_nullable_ = !col->get_result_type().is_not_null_for_write(); - column_content.is_predicate_column_ = false; - column_content.is_implicit_ = false; - if (OB_FAIL(ob_write_string(allocator, - col->get_column_name(), - column_content.column_name_))) { - LOG_WARN("fail to copy column name", K(ret), K(col->get_column_name())); - } else if (!has_exist_in_array(udp_ctdef.das_ctdef_.column_ids_, col->get_column_id(), &idx)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("assign column not exists in old column", K(ret), KPC(col)); - } else if (FALSE_IT(column_content.projector_index_ = static_cast(idx))) { - //do nothing - } else if (OB_FAIL(assign_infos.push_back(column_content))) { - LOG_WARN("fail to store colum content to assign infos", K(ret), K(column_content)); - } + column_content.auto_filled_timestamp_ = assign.column_expr_->get_result_type().has_result_flag(ON_UPDATE_NOW_FLAG); + column_content.is_nullable_ = !assign.column_expr_->get_result_type().is_not_null_for_write(); + column_content.is_predicate_column_ = false; + column_content.is_implicit_ = false; + if (OB_FAIL(ob_write_string(allocator, + assign.column_expr_->get_column_name(), + column_content.column_name_))) { + LOG_WARN("fail to copy column name", K(ret), K(assign.column_expr_->get_column_name())); + } else if (!has_exist_in_array(udp_ctdef.das_ctdef_.column_ids_, assign.column_expr_->get_column_id(), &idx)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("assign column not exists in old column", K(ret), KPC(assign.column_expr_)); + } else if (FALSE_IT(column_content.projector_index_ = static_cast(idx))) { + //do nothing + } else if (OB_FAIL(assign_infos.push_back(column_content))) { + LOG_WARN("fail to store colum content to assign infos", K(ret), K(column_content)); } } + return ret; } @@ -1400,17 +1438,13 @@ int ObTableDmlCgService::generate_delete_ctdef(ObTableCtx &ctx, int ret = OB_SUCCESS; ObSEArray old_row; ObSEArray new_row; - ObSEArray tmp_exprs; - const ObIArray &exprs = ctx.get_all_exprs().get_expr_array(); + ObSEArray table_column_exprs; - if (OB_FAIL(replace_exprs_with_dependant(exprs, tmp_exprs))) { + if (OB_FAIL(replace_exprs_with_dependant(ctx, table_column_exprs))) { LOG_WARN("fail to replace exprs with dependant", K(ret)); - } else if (OB_FAIL(old_row.assign(tmp_exprs))) { + } else if (OB_FAIL(old_row.assign(table_column_exprs))) { LOG_WARN("fail to assign old row expr", K(ret)); - } else if (OB_FAIL(generate_base_ctdef(ctx, - del_ctdef, - old_row, - new_row))) { + } else if (OB_FAIL(generate_base_ctdef(ctx, del_ctdef, old_row, new_row))) { LOG_WARN("fail to generate dml base ctdef", K(ret)); } else if (OB_FAIL(generate_das_del_ctdef(ctx, ctx.get_ref_table_id(), @@ -1438,9 +1472,7 @@ int ObTableDmlCgService::generate_das_del_ctdef(ObTableCtx &ctx, if (OB_FAIL(generate_das_base_ctdef(index_tid, ctx, das_del_ctdef))) { LOG_WARN("fail to generate das dml ctdef", K(ret)); - } else if (OB_FAIL(generate_column_ids(ctx, - ctx.get_all_exprs().get_expr_array(), - dml_column_ids))) { + } else if (OB_FAIL(generate_column_ids(ctx, dml_column_ids))) { LOG_WARN("fail to generate dml column ids", K(ret)); } else if (OB_FAIL(generate_projector(dml_column_ids, das_del_ctdef.column_ids_, @@ -1482,6 +1514,12 @@ int ObTableDmlCgService::generate_related_del_ctdef(ObTableCtx &ctx, return ret; } +/* + generate replace ctdef which consists of insert ctdef and delete ctdef. + - generate insert ctdef. + - generate rowkey info which use for fetch duplicated rowkey. + - generate delete ctdef. +*/ int ObTableDmlCgService::generate_replace_ctdef(ObTableCtx &ctx, ObIAllocator &allocator, ObTableReplaceCtDef &replace_ctdef) @@ -1503,6 +1541,7 @@ int ObTableDmlCgService::generate_table_rowkey_info(ObTableCtx &ctx, ObTableInsCtDef &ins_ctdef) { int ret = OB_SUCCESS; + ObIArray &items = ctx.get_column_items(); ObDASInsCtDef &das_ins_ctdef = ins_ctdef.das_ctdef_; ObSEArray rowkey_column_ids; ObSEArray rowkey_exprs; @@ -1510,32 +1549,23 @@ int ObTableDmlCgService::generate_table_rowkey_info(ObTableCtx &ctx, if (OB_FAIL(get_rowkey_exprs(ctx, rowkey_exprs))) { LOG_WARN("fail to get rowkey exprs", K(ret), K(ctx)); + } else if (items.count() < rowkey_exprs.count()) { + ret = OB_ERR_UNDEFINED; + LOG_WARN("invalid column item count", K(ret), K(items), K(rowkey_exprs)); } for (int64_t i = 0; OB_SUCC(ret) && i < rowkey_exprs.count(); ++i) { + const ObTableColumnItem &item = items.at(i); ObRawExpr *expr = rowkey_exprs.at(i); - if (expr->get_expr_type() == T_FUN_COLUMN_CONV && ctx.has_auto_inc()) { // 兼容自增场景下的列转换表达式 - if (OB_FAIL(rowkey_column_ids.push_back(ctx.get_auto_inc_column_id()))) { - LOG_WARN("fail to push base column id", K(ret), K(ctx.get_auto_inc_column_id())); - } else if (OB_FAIL(rowkey_column_types.push_back(expr->get_result_type()))) { - LOG_WARN("fail to push column type", K(ret), KPC(expr)); - } - } else { - if (!expr->is_column_ref_expr()) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("expr type is not column_ref expr", K(ret), KPC(expr)); - } else { - ObColumnRefRawExpr *col_expr = static_cast(expr); - if (OB_FAIL(rowkey_column_ids.push_back(col_expr->get_column_id()))) { - LOG_WARN("fail to push base column id", K(ret), K(col_expr->get_column_id())); - } else if (OB_FAIL(rowkey_column_types.push_back(col_expr->get_result_type()))) { - LOG_WARN("fail to push column type", K(ret), KPC(col_expr)); - } - } + if (OB_FAIL(rowkey_column_ids.push_back(item.column_id_))) { + LOG_WARN("fail to push base column id", K(ret), K(item)); + } else if (OB_FAIL(rowkey_column_types.push_back(item.expr_->get_result_type()))) { + LOG_WARN("fail to push column type", K(ret), K(item)); } } - if (FAILEDx(das_ins_ctdef.table_rowkey_cids_.init(rowkey_column_ids.count()))) { + if (OB_FAIL(ret)) { + } else if (OB_FAIL(das_ins_ctdef.table_rowkey_cids_.init(rowkey_column_ids.count()))) { LOG_WARN("fail to init table rowkey column ids", K(ret), K(rowkey_column_ids.count())); } else if (OB_FAIL(append(das_ins_ctdef.table_rowkey_cids_, rowkey_column_ids))) { LOG_WARN("fail to append table rowkey column id", K(ret), K(rowkey_column_ids)); @@ -1548,8 +1578,7 @@ int ObTableDmlCgService::generate_table_rowkey_info(ObTableCtx &ctx, return ret; } -int ObTableDmlCgService::get_rowkey_exprs(ObTableCtx &ctx, - ObIArray &rowkey_exprs) +int ObTableDmlCgService::get_rowkey_exprs(ObTableCtx &ctx, ObIArray &rowkey_exprs) { int ret = OB_SUCCESS; const ObTableSchema *table_schema = ctx.get_table_schema(); @@ -1559,8 +1588,7 @@ int ObTableDmlCgService::get_rowkey_exprs(ObTableCtx &ctx, LOG_WARN("table schema is null", K(ret)); } else { const int rowkey_cnt = table_schema->get_rowkey_column_num(); - const ObIArray &all_exprs = ctx.is_for_insertup() ? - ctx.get_old_row_exprs() : ctx.get_all_exprs().get_expr_array(); + const ObIArray &all_exprs = ctx.get_all_exprs_array(); for (int64_t i = 0; OB_SUCC(ret) && i < rowkey_cnt; i++) { if (OB_FAIL(rowkey_exprs.push_back(all_exprs.at(i)))) { LOG_WARN("fail to push back rowkey expr", K(ret), K(i)); @@ -1572,53 +1600,36 @@ int ObTableDmlCgService::get_rowkey_exprs(ObTableCtx &ctx, } int ObTableDmlCgService::generate_tsc_ctdef(ObTableCtx &ctx, + ObIArray &access_exprs, ObDASScanCtDef &tsc_ctdef) { int ret = OB_SUCCESS; ObStaticEngineCG cg(ctx.get_cur_cluster_version()); - const ObIArray &all_exprs = ctx.is_for_insertup() ? - ctx.get_old_row_exprs() : ctx.get_all_exprs().get_expr_array(); - ObSEArray access_exprs; - ObIArray &filter_exprs = ctx.get_filter_exprs(); - const ObTableSchema *table_schema = ctx.get_table_schema(); tsc_ctdef.ref_table_id_ = ctx.get_index_table_id(); - const uint64_t tenant_id = MTL_ID(); + const uint64_t tenant_id = ctx.get_tenant_id(); + ObSEArray column_ids; if (OB_FAIL(ctx.get_schema_guard().get_schema_version(TABLE_SCHEMA, tenant_id, tsc_ctdef.ref_table_id_, tsc_ctdef.schema_version_))) { LOG_WARN("fail to get schema version", K(ret), K(tenant_id), K(tsc_ctdef.ref_table_id_)); - } else if (OB_FAIL(access_exprs.assign(all_exprs))) { - LOG_WARN("fail to assign access exprs", K(ret)); - } else if (OB_FAIL(cg.generate_rt_exprs(access_exprs, - tsc_ctdef.pd_expr_spec_.access_exprs_))) { - LOG_WARN("fail to generate rt exprs ", K(ret)); + } else if (OB_FAIL(cg.generate_rt_exprs(access_exprs, tsc_ctdef.pd_expr_spec_.access_exprs_))) { + LOG_WARN("fail to generate rt exprs ", K(ret), K(access_exprs)); } else if (OB_FAIL(tsc_ctdef.access_column_ids_.init(access_exprs.count()))) { LOG_WARN("fail to init access_column_ids_ ", K(ret)); - } else { - ARRAY_FOREACH(access_exprs, i) { - if (access_exprs.at(i)->get_expr_type() == T_FUN_COLUMN_CONV && ctx.has_auto_inc()) { // 兼容自增场景下的列转换表达式 - if (OB_FAIL(tsc_ctdef.access_column_ids_.push_back(ctx.get_auto_inc_column_id()))) { - LOG_WARN("fail to add column id", K(ret), K(ctx.get_auto_inc_column_id())); - } - } else { - ObColumnRefRawExpr *ref_col_expr = static_cast(access_exprs.at(i)); - if (OB_ISNULL(ref_col_expr)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("null column ref expr", K(ret), K(i)); - } else if (OB_FAIL(tsc_ctdef.access_column_ids_.push_back(ref_col_expr->get_column_id()))) { - LOG_WARN("fail to add column id", K(ret), K(ref_col_expr->get_column_id())); - } - } - } + } else if (OB_FAIL(ctx.get_table_schema()->get_column_ids(column_ids))) { + LOG_WARN("fail to get column ids", K(ret)); + } else if (OB_FAIL(tsc_ctdef.access_column_ids_.assign(column_ids))) { + LOG_WARN("fail to assign column ids", K(ret), K(column_ids)); } + if (OB_SUCC(ret)) { + const ObTableSchema *table_schema = ctx.get_table_schema(); tsc_ctdef.table_param_.get_enable_lob_locator_v2() = (ctx.get_cur_cluster_version() >= CLUSTER_VERSION_4_1_0_0); if (OB_FAIL(tsc_ctdef.table_param_.convert(*table_schema, tsc_ctdef.access_column_ids_))) { LOG_WARN("fail to convert table param", K(ret)); - } else if (OB_FAIL(ObTableTscCgService::generate_das_result_output(tsc_ctdef, - tsc_ctdef.access_column_ids_))) { + } else if (OB_FAIL(ObTableTscCgService::generate_das_result_output(tsc_ctdef, tsc_ctdef.access_column_ids_))) { LOG_WARN("generate das result output failed", K(ret)); } } @@ -1632,7 +1643,6 @@ int ObTableDmlCgService::generate_single_constraint_info(ObTableCtx &ctx, ObUniqueConstraintInfo &constraint_info) { int ret = OB_SUCCESS; - constraint_info.table_id_ = table_id; constraint_info.index_tid_ = index_schema.get_table_id(); if (!index_schema.is_index_table()) { @@ -1643,25 +1653,18 @@ int ObTableDmlCgService::generate_single_constraint_info(ObTableCtx &ctx, if (OB_SUCC(ret)) { uint64_t rowkey_column_id = OB_INVALID_ID; - const ObIArray &all_exprs = ctx.is_for_insertup() ? - ctx.get_old_row_exprs() : ctx.get_all_exprs().get_expr_array(); ObIArray &column_exprs = constraint_info.constraint_columns_; const ObRowkeyInfo &rowkey_info = index_schema.get_rowkey_info(); for (int64_t i = 0; OB_SUCC(ret) && i < rowkey_info.get_size(); ++i) { + const ObTableColumnItem *item = nullptr; if (OB_FAIL(rowkey_info.get_column_id(i, rowkey_column_id))) { LOG_WARN("fail to get rowkey column id", K(ret)); - } else { - const ObIArray &all_column_exprs = ctx.get_all_column_ref_exprs(); - for (int64_t j = 0; OB_SUCC(ret) && j < all_column_exprs.count(); j++) { - ObColumnRefRawExpr *ref_expr = all_column_exprs.at(j); - if (OB_ISNULL(ref_expr)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("ref_expr is null", K(ret), K(j)); - } else if (ref_expr->get_column_id() == rowkey_column_id - && OB_FAIL(column_exprs.push_back(ref_expr))) { - LOG_WARN("fail to push back column ref expr to constraint columns", K(ret), K(j)); - } - } + } else if (OB_FAIL(ctx.get_column_item_by_column_id(rowkey_column_id, item))) { + LOG_WARN("fail to get column item", K(ret), K(ctx), K(rowkey_column_id)); + } else if (OB_ISNULL(item)) { + // do nothing, not found + } else if (OB_FAIL(column_exprs.push_back(item->expr_))) { + LOG_WARN("fail to push back column expr", K(ret), K(item)); } } } @@ -1731,6 +1734,7 @@ int ObTableDmlCgService::generate_constraint_ctdefs(ObTableCtx &ctx, ObSEArray cst_infos; ObRowkeyCstCtdef *rowkey_cst_ctdef = nullptr; ObStaticEngineCG cg(ctx.get_cur_cluster_version()); + ObIArray &all_exprs = ctx.get_all_exprs_array(); if (OB_FAIL(generate_constraint_infos(ctx, cst_infos))) { LOG_WARN("fail to generate constraint infos", K(ret), K(ctx)); @@ -1751,8 +1755,15 @@ int ObTableDmlCgService::generate_constraint_ctdefs(ObTableCtx &ctx, LOG_WARN("fail to init rowkey", K(ret), K(cst_columns.count())); } else { for (int64_t j = 0; OB_SUCC(ret) && j < cst_columns.count(); ++j) { + const ObTableColumnItem *item = nullptr; + ObColumnRefRawExpr *ref_expr = cst_columns.at(j); ObExpr *expr = nullptr; - if (OB_FAIL(cg.generate_rt_expr(*cst_columns.at(j), expr))) { + if (OB_FAIL(ctx.get_column_item_by_expr(ref_expr, item))) { + LOG_WARN("fail to column item by expr", K(ret), K(*ref_expr)); + } else if (OB_ISNULL(item)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("column item is null", K(ret), K(ctx)); + } else if (OB_FAIL(cg.generate_rt_expr(*item->raw_expr_, expr))) { LOG_WARN("fail to generate rt expr", K(ret)); } else if (OB_FAIL(rowkey_cst_ctdef->rowkey_expr_.push_back(expr))) { LOG_WARN("fail to push back rt expr", K(ret)); @@ -1773,25 +1784,22 @@ int ObTableDmlCgService::generate_conflict_checker_ctdef(ObTableCtx &ctx, ObConflictCheckerCtdef &conflict_checker_ctdef) { int ret = OB_SUCCESS; - const ObIArray &exprs = ctx.is_for_insertup() ? - ctx.get_old_row_exprs() : ctx.get_all_exprs().get_expr_array(); - ObSEArray table_column_exprs; ObSEArray rowkey_exprs; + ObSEArray table_column_exprs; ObStaticEngineCG cg(ctx.get_cur_cluster_version()); if (OB_FAIL(get_rowkey_exprs(ctx, rowkey_exprs))) { LOG_WARN("fail to get table rowkey exprs", K(ret), K(ctx)); - } else if (OB_FAIL(generate_tsc_ctdef(ctx, conflict_checker_ctdef.das_scan_ctdef_))) { - LOG_WARN("fail to generate das_scan_ctdef", K(ret)); - } else if (OB_FAIL(generate_constraint_ctdefs(ctx, - allocator, - conflict_checker_ctdef.cst_ctdefs_))) { + } else if (OB_FAIL(replace_exprs_with_dependant(ctx, table_column_exprs))) { + LOG_WARN("fail to replace exprs with dependant", K(ret)); + } else if (OB_FAIL(generate_tsc_ctdef(ctx, table_column_exprs, conflict_checker_ctdef.das_scan_ctdef_))) { + LOG_WARN("fail to generate das_scan_ctdef", K(ret), K(table_column_exprs)); + } else if (OB_FAIL(generate_constraint_ctdefs(ctx, allocator, conflict_checker_ctdef.cst_ctdefs_))) { LOG_WARN("fail to generate constraint infos", K(ret), K(ctx)); - } else if (OB_FAIL(cg.generate_rt_exprs(rowkey_exprs, - conflict_checker_ctdef.data_table_rowkey_expr_))) { + } else if (OB_FAIL(cg.generate_rt_exprs(rowkey_exprs, conflict_checker_ctdef.data_table_rowkey_expr_))) { LOG_WARN("fail to generate data table rowkey expr", K(ret), K(rowkey_exprs)); - } else if (OB_FAIL(cg.generate_rt_exprs(exprs, conflict_checker_ctdef.table_column_exprs_))) { - LOG_WARN("fail to generate table columns rt exprs ", K(ret)); + } else if (OB_FAIL(cg.generate_rt_exprs(table_column_exprs, conflict_checker_ctdef.table_column_exprs_))) { + LOG_WARN("fail to generate table columns rt exprs ", K(ret), K(table_column_exprs)); } else { conflict_checker_ctdef.rowkey_count_ = ctx.get_table_schema()->get_rowkey_column_num(); } @@ -1801,7 +1809,6 @@ int ObTableDmlCgService::generate_conflict_checker_ctdef(ObTableCtx &ctx, int ObTableDmlCgService::generate_insert_up_ctdef(ObTableCtx &ctx, ObIAllocator &allocator, - const ObTableCtx::ObAssignIds &assign_ids, ObTableInsUpdCtDef &ins_up_ctdef) { int ret = OB_SUCCESS; @@ -1810,10 +1817,7 @@ int ObTableDmlCgService::generate_insert_up_ctdef(ObTableCtx &ctx, LOG_WARN("fail to generate insert ctdef", K(ret), K(ctx)); } else if (OB_FAIL(generate_table_rowkey_info(ctx, ins_up_ctdef.ins_ctdef_))) { LOG_WARN("fail to generate table rowkey info", K(ret), K(ctx)); - } else if (OB_FAIL(generate_update_ctdef(ctx, - allocator, - assign_ids, - ins_up_ctdef.upd_ctdef_))) { + } else if (OB_FAIL(generate_update_ctdef(ctx, allocator, ins_up_ctdef.upd_ctdef_))) { LOG_WARN("fail to generate update ctdef", K(ret), K(ctx)); } @@ -1834,7 +1838,7 @@ int ObTableDmlCgService::generate_ttl_ctdef(ObTableCtx &ctx, LOG_WARN("fail to generate table rowkey info", K(ret), K(ctx)); } else if (OB_FAIL(generate_delete_ctdef(ctx, allocator, ttl_ctdef.del_ctdef_))) { LOG_WARN("fail to generate delete ctdef", K(ret), K(ctx)); - } else if (OB_FAIL(generate_update_ctdef(ctx, allocator, ctx.get_assign_ids(), ttl_ctdef.upd_ctdef_))) { + } else if (OB_FAIL(generate_update_ctdef(ctx, allocator, ttl_ctdef.upd_ctdef_))) { LOG_WARN("fail to generate update ctdef", K(ret), K(ctx)); } else if (filter_exprs.count() != 1) { ret = OB_ERR_UNEXPECTED; @@ -1852,15 +1856,13 @@ int ObTableDmlCgService::generate_lock_ctdef(ObTableCtx &ctx, int ret = OB_SUCCESS; ObStaticEngineCG cg(ctx.get_cur_cluster_version()); ObArray old_row; - const ObIArray &exprs = ctx.get_all_exprs().get_expr_array(); ObSEArray tmp_exprs; - if (OB_FAIL(replace_exprs_with_dependant(exprs, tmp_exprs))) { + if (OB_FAIL(replace_exprs_with_dependant(ctx, tmp_exprs))) { LOG_WARN("fail to replace exprs with dependant", K(ret)); } else if (OB_FAIL(old_row.assign(tmp_exprs))) { LOG_WARN("fail to assign old row expr", K(ret)); - } else if (OB_FAIL(cg.generate_rt_exprs(old_row, - lock_ctdef.old_row_))) { + } else if (OB_FAIL(cg.generate_rt_exprs(old_row, lock_ctdef.old_row_))) { LOG_WARN("fail to generate lock rt exprs", K(ret), K(old_row)); } else if (OB_FAIL(generate_das_lock_ctdef(ctx, ctx.get_ref_table_id(), @@ -1883,9 +1885,7 @@ int ObTableDmlCgService::generate_das_lock_ctdef(ObTableCtx &ctx, if (OB_FAIL(generate_das_base_ctdef(index_tid, ctx, das_lock_ctdef))) { LOG_WARN("fail to generate das dml ctdef", K(ret)); - } else if (OB_FAIL(generate_column_ids(ctx, - ctx.get_all_exprs().get_expr_array(), - dml_column_ids))) { + } else if (OB_FAIL(generate_column_ids(ctx, dml_column_ids))) { LOG_WARN("fail to generate dml column ids", K(ret)); } else if (OB_FAIL(generate_projector(dml_column_ids, das_lock_ctdef.column_ids_, @@ -1906,15 +1906,13 @@ int ObTableDmlCgService::generate_base_ctdef(ObTableCtx &ctx, { int ret = OB_SUCCESS; ObStaticEngineCG cg(ctx.get_cur_cluster_version()); - const ObIArray &exprs = (ctx.is_for_update() || ctx.is_for_insertup()) ? - ctx.get_old_row_exprs() : ctx.get_all_exprs().get_expr_array(); - if (OB_FAIL(generate_column_ids(ctx, exprs, base_ctdef.column_ids_))) { + if (OB_FAIL(generate_column_ids(ctx, base_ctdef.column_ids_))) { LOG_WARN("fail to generate dml column ids", K(ret)); } else if (OB_FAIL(cg.generate_rt_exprs(old_row, base_ctdef.old_row_))) { - LOG_WARN("fail to generate old row exprs", K(ret)); + LOG_WARN("fail to generate old row exprs", K(ret), K(old_row)); } else if (OB_FAIL(cg.generate_rt_exprs(new_row, base_ctdef.new_row_))) { - LOG_WARN("fail to generate new row exprs", K(ret)); + LOG_WARN("fail to generate new row exprs", K(ret), K(new_row)); } return ret; @@ -1928,14 +1926,10 @@ int ObTableDmlCgService::generate_das_ins_ctdef(ObTableCtx &ctx, int ret = OB_SUCCESS; ObArray dml_column_ids; ObArray empty_old_row; - const ObIArray &exprs = ctx.is_for_insertup() ? - ctx.get_old_row_exprs() : ctx.get_all_exprs().get_expr_array(); if (OB_FAIL(generate_das_base_ctdef(index_tid, ctx, das_ins_ctdef))) { LOG_WARN("fail to generate das dml ctdef", K(ret)); - } else if (OB_FAIL(generate_column_ids(ctx, - exprs, - dml_column_ids))) { + } else if (OB_FAIL(generate_column_ids(ctx, dml_column_ids))) { LOG_WARN("fail to generate dml column ids", K(ret)); } else if (OB_FAIL(generate_projector(dml_column_ids, // new row and old row's columns id das_ins_ctdef.column_ids_, // schmea column ids for given index_tid @@ -2083,32 +2077,20 @@ int ObTableDmlCgService::convert_table_param(ObTableCtx &ctx, return ret; } -int ObTableDmlCgService::generate_column_ids(ObTableCtx &ctx, - const ObIArray &exprs, - ObIArray &column_ids) +int ObTableDmlCgService::generate_column_ids(ObTableCtx &ctx, ObIArray &column_ids) { int ret = OB_SUCCESS; + ObIArray &items = ctx.get_column_items(); column_ids.reset(); - if (!exprs.empty()) { - if (OB_FAIL(column_ids.reserve(exprs.count()))) { - LOG_WARN("fail to reserve column ids capacity", K(ret), K(exprs.count())); - } else { - ARRAY_FOREACH(exprs, i) { - if (exprs.at(i)->get_expr_type() == T_FUN_COLUMN_CONV && (ctx.get_opertion_type() != ObTableOperationType::DEL) // 特判下,若为delete/update/get/scan操作 - && (ctx.get_opertion_type() != ObTableOperationType::UPDATE) // 则走原有的列引用表达式 - && (ctx.get_opertion_type() != ObTableOperationType::GET) - && (ctx.get_opertion_type() != ObTableOperationType::SCAN)) { - if (OB_FAIL(column_ids.push_back(ctx.get_auto_inc_column_id()))) { - LOG_WARN("fail to push back column id", K(ret), K(ctx.get_auto_inc_column_id())); - } - } else { - ObColumnRefRawExpr *col_expr = static_cast(exprs.at(i)); - if (OB_FAIL(column_ids.push_back(col_expr->get_column_id()))) { - LOG_WARN("fail to push back column id", K(ret), K(col_expr->get_column_id())); - } - } - } + if (OB_FAIL(column_ids.reserve(items.count()))) { + LOG_WARN("fail to reserve column ids capacity", K(ret), K(items.count())); + } + + for (int64_t i= 0; OB_SUCC(ret) && i < items.count(); i++) { + const ObTableColumnItem &item = items.at(i); + if (OB_FAIL(column_ids.push_back(item.column_id_))) { + LOG_WARN("fail to push back column id", K(ret)); } } @@ -2216,7 +2198,6 @@ int ObTableDmlCgService::generate_related_ins_ctdef(ObTableCtx &ctx, int ObTableDmlCgService::generate_related_upd_ctdef(ObTableCtx &ctx, ObIAllocator &allocator, - const ObIArray &assign_exprs, const ObIArray &old_row, const ObIArray &new_row, const ObIArray &full_row, @@ -2234,7 +2215,6 @@ int ObTableDmlCgService::generate_related_upd_ctdef(ObTableCtx &ctx, LOG_WARN("fail to allocate update related das ctdef", K(ret)); } else if (OB_FAIL(generate_das_upd_ctdef(ctx, related_index_tids.at(i), - assign_exprs, *related_das_ctdef, old_row, new_row, @@ -2294,12 +2274,11 @@ int ObTableTscCgService::replace_gen_col_exprs(const ObTableCtx &ctx, if (!ctx.get_table_schema()->has_generated_column()) { // do nothing } else { - ObArray res_access_expr; - const ObIArray &pairs = ctx.get_gen_dependants_pairs(); + ObSEArray res_access_expr; + const ObIArray &items = ctx.get_column_items(); ObColumnRefRawExpr *ref_expr = nullptr; - const int64_t N = access_exprs.count(); - for (int64_t i = 0; i < N && OB_SUCC(ret); i++) { + for (int64_t i = 0; i < access_exprs.count() && OB_SUCC(ret); i++) { ObRawExpr *expr = access_exprs.at(i); if (!expr->is_column_ref_expr()) { ret = OB_ERR_UNEXPECTED; @@ -2310,11 +2289,11 @@ int ObTableTscCgService::replace_gen_col_exprs(const ObTableCtx &ctx, LOG_WARN("fail to push back expr", K(ret)); } } else { - for (int j = 0; j < pairs.count() && OB_SUCC(ret); j++) { - if (ref_expr == pairs.at(j).first) { - const ObIArray &ref_exprs = pairs.at(j).second; - if (OB_FAIL(append_array_no_dup(res_access_expr, ref_exprs))) { - LOG_WARN("fail to append array no dup", K(ret), K(res_access_expr), K(ref_exprs)); + for (int j = 0; j < items.count() && OB_SUCC(ret); j++) { + const ObTableColumnItem &item = items.at(j); + if (item.expr_ == expr) { + if (OB_FAIL(append_array_no_dup(res_access_expr, item.dependant_exprs_))) { + LOG_WARN("fail to append array no dup", K(ret), K(res_access_expr), K(item)); } } } @@ -2340,7 +2319,7 @@ int ObTableTscCgService::generate_access_ctdef(const ObTableCtx &ctx, ObDASScanCtDef &das_tsc_ctdef) { int ret = OB_SUCCESS; - ObArray access_exprs; + ObSEArray access_exprs; const ObIArray &select_exprs = ctx.get_select_exprs(); const ObIArray &rowkey_exprs = ctx.get_rowkey_exprs(); const ObIArray &index_exprs = ctx.get_index_exprs(); @@ -2378,18 +2357,30 @@ int ObTableTscCgService::generate_access_ctdef(const ObTableCtx &ctx, if (!is_index_table && OB_FAIL(replace_gen_col_exprs(ctx, access_exprs))) { LOG_WARN("fail to replace generate exprs", K(ret)); } else if (OB_FAIL(generate_rt_exprs(ctx, allocator, access_exprs, das_tsc_ctdef.pd_expr_spec_.access_exprs_))) { - LOG_WARN("fail to generate access rt exprs", K(ret)); + LOG_WARN("fail to generate access rt exprs", K(ret), K(access_exprs)); } else if (OB_FAIL(das_tsc_ctdef.access_column_ids_.init(access_exprs.count()))) { LOG_WARN("fail to init access column ids", K(ret), K(access_exprs.count())); } else { - ObColumnRefRawExpr *col_expr = NULL; for (int64_t i = 0; OB_SUCC(ret) && i < access_exprs.count(); i++) { - if (!access_exprs.at(i)->is_column_ref_expr()) { + ObRawExpr *raw_expr = access_exprs.at(i); + if (OB_ISNULL(raw_expr)) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpected expr type", K(ret), K(access_exprs.at(i)->get_expr_type())); - } else if (FALSE_IT(col_expr = static_cast(access_exprs.at(i)))) { - } else if (OB_FAIL(das_tsc_ctdef.access_column_ids_.push_back(col_expr->get_column_id()))) { - LOG_WARN("fail to push back column id", K(ret)); + LOG_WARN("expr is null", K(ret), K(access_exprs)); + } else if (raw_expr->is_column_ref_expr()) { + ObColumnRefRawExpr *col_ref_expr = static_cast(raw_expr); + if (OB_FAIL(das_tsc_ctdef.access_column_ids_.push_back(col_ref_expr->get_column_id()))) { + LOG_WARN("fail to push back column id", K(ret)); + } + } else { // calculate expr, find in column items + const ObTableColumnItem *item = nullptr; + if (OB_FAIL(ctx.get_column_item_by_expr(raw_expr, item))) { + LOG_WARN("fail to get column item", K(ret), K(*raw_expr)); + } else if (OB_ISNULL(item)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("column item not found", K(ret), K(ctx)); + } else if (OB_FAIL(das_tsc_ctdef.access_column_ids_.push_back(item->column_id_))) { + LOG_WARN("fail to push back column id", K(ret), K(*item)); + } } } } @@ -2433,40 +2424,39 @@ int ObTableTscCgService::generate_table_param(const ObTableCtx &ctx, ObDASScanCtDef &das_tsc_ctdef) { int ret = OB_SUCCESS; - ObArray tsc_out_cols; + ObSEArray tsc_out_cols; const ObTableSchema *table_schema = nullptr; const ObIArray &select_exprs = ctx.get_select_exprs(); if (!ctx.is_index_scan() // 非索引扫描 || (ctx.is_index_scan() && das_tsc_ctdef.ref_table_id_ == ctx.get_ref_table_id()) // 索引扫描回表 || (ctx.is_index_scan() && !ctx.is_index_back())) { //索引扫描不需要回表 - ObColumnRefRawExpr *col_expr = NULL; if (ctx.is_index_scan() && !ctx.is_index_back()) { table_schema = ctx.get_index_schema(); } else { table_schema = ctx.get_table_schema(); } for (int64_t i = 0; OB_SUCC(ret) && i < select_exprs.count(); i++) { - ObRawExpr *expr = select_exprs.at(i); - if (!expr->is_column_ref_expr()) { + ObRawExpr *raw_expr = select_exprs.at(i); + if (OB_ISNULL(raw_expr)) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpected expr type", K(ret), K(*expr)); - } else if (FALSE_IT(col_expr = static_cast(expr))) { - } else if (!col_expr->is_virtual_generated_column()) { - if (OB_FAIL(tsc_out_cols.push_back(col_expr->get_column_id()))) { - LOG_WARN("fail to push back column id", K(ret)); - } + LOG_WARN("expr is null", K(ret)); } else { - // output虚拟生成列转换为ouput其依赖的列 - const ObIArray &pairs = ctx.get_gen_dependants_pairs(); - for (int64_t j = 0; j < pairs.count() && OB_SUCC(ret); j++) { - if (col_expr == pairs.at(j).first) { - const ObIArray &dependant_exprs = pairs.at(j).second; - for (int64_t k = 0; k < dependant_exprs.count() && OB_SUCC(ret); k++) { - ObColumnRefRawExpr *dep_col_expr = static_cast(dependant_exprs.at(k)); - if (OB_FAIL(add_var_to_array_no_dup(tsc_out_cols, dep_col_expr->get_column_id()))) { - LOG_WARN("fail to add column id", K(ret), K(tsc_out_cols), K(*dep_col_expr)); - } + const ObTableColumnItem *item = nullptr; + if (OB_FAIL(ctx.get_column_item_by_expr(raw_expr, item))) { + LOG_WARN("fail to get column item", K(ret), K(*raw_expr)); + } else if (OB_ISNULL(item)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("column item not found", K(ret), K(ctx)); + } else if (!item->is_generated_column_) { + if (OB_FAIL(tsc_out_cols.push_back(item->column_id_))) { + LOG_WARN("fail to push back column id", K(ret), K(tsc_out_cols), K(*item)); + } + } else { // generate column. push dependent column ids + for (int64_t j = 0; j < item->dependant_exprs_.count() && OB_SUCC(ret); j++) { + ObColumnRefRawExpr *dep_col_expr = static_cast(item->dependant_exprs_.at(j)); + if (OB_FAIL(add_var_to_array_no_dup(tsc_out_cols, dep_col_expr->get_column_id()))) { + LOG_WARN("fail to add column id", K(ret), K(tsc_out_cols), K(*dep_col_expr)); } } } @@ -2517,16 +2507,24 @@ int ObTableTscCgService::generate_output_exprs(const ObTableCtx &ctx, { int ret = OB_SUCCESS; ObStaticEngineCG cg(ctx.get_cur_cluster_version()); + const ObIArray &items = ctx.get_column_items(); const ObIArray &select_exprs = ctx.get_select_exprs(); - const int64_t N = select_exprs.count(); - for (int64_t i = 0; i < N && OB_SUCC(ret); i++) { + + for (int64_t i = 0; i < select_exprs.count() && OB_SUCC(ret); i++) { ObExpr *rt_expr = nullptr; - ObRawExpr *expr = select_exprs.at(i); - ObColumnRefRawExpr *col_ref_expr = static_cast(expr); - if (col_ref_expr->is_virtual_generated_column()) { - expr = col_ref_expr->get_dependant_expr(); + ObRawExpr *raw_expr = select_exprs.at(i); + const ObTableColumnItem *item = nullptr; + if (OB_FAIL(ctx.get_column_item_by_expr(raw_expr, item))) { + LOG_WARN("fail to get column item", K(ret), K(*raw_expr)); + } else if (OB_ISNULL(item)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("column item not found", K(ret), K(ctx)); + } else if (item->is_virtual_generated_column_) { // output dependant expr when virtual expr + raw_expr = item->expr_->get_dependant_expr(); } - if (OB_FAIL(cg.generate_rt_expr(*expr, rt_expr))) { + + if (OB_FAIL(ret)) { + } else if (OB_FAIL(cg.generate_rt_expr(*raw_expr, rt_expr))) { LOG_WARN("fail to generate rt expr", K(ret)); } else if (OB_FAIL(output_exprs.push_back(rt_expr))) { LOG_WARN("fail to push back rt expr", K(ret), K(output_exprs)); @@ -2595,29 +2593,14 @@ int ObTableSpecCgService::generate_spec(ObIAllocator &alloc, ObTableCtx &ctx, ObTableApiUpdateSpec &spec) { - int ret = OB_SUCCESS; - - if (OB_FAIL(ObTableDmlCgService::generate_update_ctdef(ctx, - alloc, - ctx.get_assign_ids(), - spec.get_ctdef()))) { - LOG_WARN("fail to generate update ctdef", K(ret)); - } - - return ret; + return ObTableDmlCgService::generate_update_ctdef(ctx, alloc, spec.get_ctdef()); } int ObTableSpecCgService::generate_spec(ObIAllocator &alloc, ObTableCtx &ctx, ObTableApiDelSpec &spec) { - int ret = OB_SUCCESS; - - if (OB_FAIL(ObTableDmlCgService::generate_delete_ctdef(ctx, alloc, spec.get_ctdef()))) { - LOG_WARN("fail to generate delete ctdef", K(ret)); - } - - return ret; + return ObTableDmlCgService::generate_delete_ctdef(ctx, alloc, spec.get_ctdef()); } int ObTableSpecCgService::generate_spec(ObIAllocator &alloc, @@ -2625,9 +2608,8 @@ int ObTableSpecCgService::generate_spec(ObIAllocator &alloc, ObTableApiReplaceSpec &spec) { int ret = OB_SUCCESS; - ObTableReplaceCtDef &ctdef = spec.get_ctdef(); - if (OB_FAIL(ObTableDmlCgService::generate_replace_ctdef(ctx, alloc, ctdef))) { + if (OB_FAIL(ObTableDmlCgService::generate_replace_ctdef(ctx, alloc, spec.get_ctdef()))) { LOG_WARN("fail to generate replace ctdef", K(ret)); } else if (OB_FAIL(ObTableDmlCgService::generate_conflict_checker_ctdef(ctx, alloc, @@ -2643,23 +2625,13 @@ int ObTableSpecCgService::generate_spec(ObIAllocator &alloc, ObTableApiInsertUpSpec &spec) { int ret = OB_SUCCESS; - ObTableInsUpdCtDef &ctdef = spec.get_ctdef(); - if (OB_FAIL(ObTableDmlCgService::generate_insert_up_ctdef(ctx, - alloc, - ctx.get_assign_ids(), - ctdef))) { + if (OB_FAIL(ObTableDmlCgService::generate_insert_up_ctdef(ctx, alloc, spec.get_ctdef()))) { LOG_WARN("fail to generate insert up ctdef", K(ret)); - } else { - const ObIArray &exprs = ctx.get_old_row_exprs(); - ObStaticEngineCG cg(ctx.get_cur_cluster_version()); - if (OB_FAIL(ObTableDmlCgService::generate_conflict_checker_ctdef(ctx, - alloc, - spec.get_conflict_checker_ctdef()))) { - LOG_WARN("fail to generate conflict checker ctdef", K(ret)); - } else if (OB_FAIL(cg.generate_rt_exprs(exprs, spec.get_all_saved_exprs()))) { - LOG_WARN("fail to generate rt exprs ", K(ret)); - } + } else if (OB_FAIL(ObTableDmlCgService::generate_conflict_checker_ctdef(ctx, + alloc, + spec.get_conflict_checker_ctdef()))) { + LOG_WARN("fail to generate conflict checker ctdef", K(ret)); } return ret; @@ -2669,42 +2641,7 @@ int ObTableSpecCgService::generate_spec(common::ObIAllocator &alloc, ObTableCtx &ctx, ObTableApiLockSpec &spec) { - int ret = OB_SUCCESS; - - if (OB_FAIL(ObTableDmlCgService::generate_lock_ctdef(ctx, spec.get_ctdef()))) { - LOG_WARN("fail to generate lock ctdef", K(ret)); - } - - return ret; -} - -int ObTableExprCgService::generate_autoinc_nextval_expr(ObTableCtx &ctx, - ObRawExpr *&expr, - const ObColumnSchemaV2 &col_schema) -{ - int ret = OB_SUCCESS; - - ObSysFunRawExpr *func_expr = NULL; - if (OB_FAIL(ctx.get_expr_factory().create_raw_expr(T_FUN_SYS_AUTOINC_NEXTVAL, func_expr))) { - LOG_WARN("fail to create nextval expr", K(ret)); - } else { - func_expr->set_func_name(ObString::make_string(N_AUTOINC_NEXTVAL)); - if (OB_NOT_NULL(expr) && OB_FAIL(func_expr->add_param_expr(expr))) { // 将最底部的列转换表达式挂到自增列表达式之下 - LOG_WARN("fail to add collumn conv expr to function param", K(ret)); - } else if (OB_FAIL(func_expr->formalize(&ctx.get_session_info()))) { - LOG_WARN("fail to extract info", K(ret)); - } else if (OB_FAIL(ObAutoincNextvalExtra::init_autoinc_nextval_extra(&ctx.get_allocator(), - reinterpret_cast(func_expr), - ctx.get_table_id(), - col_schema.get_column_id(), - ctx.get_table_name(), - col_schema.get_column_name()))) { - LOG_WARN("fail to init autoinc_nextval_extra", K(ret), K(ctx.get_table_name()), K(col_schema)); - } else { - expr = func_expr; - } - } - return ret; + return ObTableDmlCgService::generate_lock_ctdef(ctx, spec.get_ctdef()); } int ObTableSpecCgService::generate_spec(common::ObIAllocator &alloc, diff --git a/src/observer/table/ob_table_cg_service.h b/src/observer/table/ob_table_cg_service.h index 67582ef09c..46a2b2c906 100644 --- a/src/observer/table/ob_table_cg_service.h +++ b/src/observer/table/ob_table_cg_service.h @@ -36,10 +36,6 @@ public: static int generate_exprs(ObTableCtx &ctx, common::ObIAllocator &allocator, ObExprFrameInfo &expr_frame_info); - // 基于table schema构造全表列原生列引用表达式和生成列表达式 - static int generate_column_raw_exprs(ObTableCtx &ctx); - // 构造更新需要的表达式 - static int generate_update_raw_exprs(ObTableCtx &ctx); // 基于原生表达式生成表达式内存布局 static int generate_expr_frame_info(ObTableCtx &ctx, common::ObIAllocator &allocator, @@ -60,26 +56,13 @@ public: const common::ObIArray &delta_exprs, const ObTableEntity &entity); static int refresh_update_exprs_frame(ObTableCtx &ctx, - const common::ObIArray &old_row, const common::ObIArray &new_row, - const common::ObIArray &full_assign_row, - const ObTableCtx::ObAssignIds &assign_ids, const ObTableEntity &entity); static int refresh_insert_up_exprs_frame(ObTableCtx &ctx, const common::ObIArray &ins_new_row, - const common::ObIArray &delta_exprs, + const common::ObIArray &delta_row, const ObTableEntity &entity); - static int refresh_generated_column_related_frame(ObTableCtx &ctx, - const common::ObIArray &old_row, - const common::ObIArray &full_assign_row, - const ObTableCtx::ObAssignIds &assign_ids, - const ObColumnSchemaV2 &col_schema); - static int generate_assign_exprs(ObTableCtx &ctx, - const ObTableCtx::ObAssignIds &assign_ids, - common::ObIArray &assign_exprs); private: - static int init_datum_param_store(ObTableCtx &ctx, - int64_t capacity); static int refresh_exprs_frame(ObTableCtx &ctx, const common::ObIArray &exprs, const ObTableEntity &entity); @@ -90,42 +73,52 @@ private: const common::ObIArray &exprs, const ObTableEntity &entity); static int refresh_assign_exprs_frame(ObTableCtx &ctx, - const common::ObIArray &old_rows, - const common::ObIArray &new_rows, - const common::ObIArray &full_assign_rows, - const ObTableCtx::ObAssignIds &assign_ids, + const common::ObIArray &new_row, const ObTableEntity &entity); static int refresh_delta_exprs_frame(ObTableCtx &ctx, - const common::ObIArray &delta_exprs, + const common::ObIArray &delta_row, const ObTableEntity &entity); - static int generate_full_assign_raw_exprs(ObTableCtx &ctx); - static int genreate_filter_exprs(ObTableCtx &ctx); -private: - // 通过column_name在表达式数组获取列引用表达式 - static ObRawExpr* get_ref_raw_expr(const common::ObIArray &all_exprs, - const common::ObString &col_name); - // 构造生成列表达式 - static int build_generated_column_expr(ObTableCtx &ctx, - sql::ObColumnRefRawExpr &col_expr, - const common::ObString &expr_str, - const common::ObIArray &exprs); - // 处理生成列表达式 - static int resolve_generated_column_expr(ObTableCtx &ctx); - // 构造列引用原生表达式 - static int generate_column_ref_raw_expr(ObTableCtx &ctx, - const ObColumnSchemaV2 &col_schema, - sql::ObRawExpr *&expr); - // 构建列自增表达式 - static int generate_autoinc_nextval_expr(ObTableCtx &ctx, - ObRawExpr *&expr, - const ObColumnSchemaV2 &col_schema); - static int build_expire_expr(ObTableCtx &ctx, sql::ObRawExpr *&expire_expr); + static int generate_assignments(ObTableCtx &ctx); + + static int generate_filter_exprs(ObTableCtx &ctx); + + static int generate_delta_expr(ObTableCtx &ctx, ObTableAssignment &assign); + + static int generate_assign_expr(ObTableCtx &ctx, ObTableAssignment &assign); + + static int build_generated_column_expr(ObTableCtx &ctx, + ObTableColumnItem &item, + const ObString &expr_str, + sql::ObRawExpr *&expr, + sql::ObRawExpr *delta_expr = nullptr); + + static int generate_autoinc_nextval_expr(ObTableCtx &ctx, + const ObTableColumnItem &item, + sql::ObRawExpr *&expr); + + static int generate_expire_expr(ObTableCtx &ctx, sql::ObRawExpr *&expr); + + static int generate_current_timestamp_expr(ObTableCtx &ctx, + const ObTableColumnItem &item, + sql::ObRawExpr *&expr); + + static int generate_all_column_exprs(ObTableCtx &ctx); + + static int resolve_exprs(ObTableCtx &ctx); + + static int add_extra_column_exprs(ObTableCtx &ctx); + static int write_datum(ObTableCtx &ctx, common::ObIAllocator &allocator, const sql::ObExpr &expr, sql::ObEvalCtx &eval_ctx, const ObObj &obj); + + static int write_autoinc_datum(ObTableCtx &ctx, + const sql::ObExpr &expr, + sql::ObEvalCtx &eval_ctx, + const ObObj &obj); private: DISALLOW_COPY_AND_ASSIGN(ObTableExprCgService); }; @@ -148,7 +141,6 @@ public: ObTableInsCtDef &ins_ctdef); static int generate_update_ctdef(ObTableCtx &ctx, ObIAllocator &allocator, - const ObTableCtx::ObAssignIds &assign_ids, ObTableUpdCtDef &upd_ctdef); static int generate_delete_ctdef(ObTableCtx &ctx, ObIAllocator &allocator, @@ -158,7 +150,6 @@ public: ObTableReplaceCtDef &replace_ctdef); static int generate_insert_up_ctdef(ObTableCtx &ctx, ObIAllocator &allocator, - const ObTableCtx::ObAssignIds &assign_ids, ObTableInsUpdCtDef &ins_up_ctdef); static int generate_lock_ctdef(ObTableCtx &ctx, ObTableLockCtDef &lock_ctdef); @@ -173,16 +164,13 @@ private: ObTableDmlBaseCtDef &base_ctdef, common::ObIArray &old_row, common::ObIArray &new_row); - static int generate_column_ids(ObTableCtx &ctx, - const common::ObIArray &exprs, - common::ObIArray &column_ids); + static int generate_column_ids(ObTableCtx &ctx, common::ObIArray &column_ids); static int generate_das_ins_ctdef(ObTableCtx &ctx, uint64_t index_tid, sql::ObDASInsCtDef &das_ins_ctdef, const common::ObIArray &new_row); static int generate_das_upd_ctdef(ObTableCtx &ctx, uint64_t index_tid, - const common::ObIArray &assign_exprs, sql::ObDASUpdCtDef &das_upd_ctdef, const common::ObIArray &old_row, const common::ObIArray &new_row, @@ -196,12 +184,9 @@ private: sql::ObDASLockCtDef &das_lock_ctdef, const common::ObIArray &old_row); static int generate_updated_column_ids(ObTableCtx &ctx, - const common::ObIArray &assign_exprs, - const common::ObIArray &column_ids, common::ObIArray &updated_column_ids); static int generate_upd_assign_infos(ObTableCtx &ctx, ObIAllocator &allocator, - const common::ObIArray &assign_exprs, ObTableUpdCtDef &udp_ctdef); static int generate_das_base_ctdef(uint64_t index_tid, ObTableCtx &ctx, @@ -223,7 +208,6 @@ private: sql::DASInsCtDefArray &ins_ctdefs); static int generate_related_upd_ctdef(ObTableCtx &ctx, ObIAllocator &allocator, - const common::ObIArray &assign_exprs, const common::ObIArray &old_row, const common::ObIArray &new_row, const common::ObIArray &full_row, @@ -232,11 +216,13 @@ private: ObIAllocator &allocator, const common::ObIArray &old_row, sql::DASDelCtDefArray &del_ctdefs); - static int get_rowkey_exprs(ObTableCtx &ctx, - common::ObIArray &rowkey_exprs); + + static int get_rowkey_exprs(ObTableCtx &ctx, common::ObIArray &rowkey_exprs); + static int generate_table_rowkey_info(ObTableCtx &ctx, ObTableInsCtDef &ins_ctdef); static int generate_tsc_ctdef(ObTableCtx &ctx, + common::ObIArray &access_exprs, sql::ObDASScanCtDef &tsc_ctdef); static int generate_single_constraint_info(ObTableCtx &ctx, const share::schema::ObTableSchema &index_schema, @@ -247,7 +233,7 @@ private: static int generate_constraint_ctdefs(ObTableCtx &ctx, ObIAllocator &allocator, sql::ObRowkeyCstCtdefArray &cst_ctdefs); - static int replace_exprs_with_dependant(const common::ObIArray &src_exprs, + static int replace_exprs_with_dependant(ObTableCtx &ctx, common::ObIArray &dst_exprs); private: DISALLOW_COPY_AND_ASSIGN(ObTableDmlCgService); diff --git a/src/observer/table/ob_table_context.cpp b/src/observer/table/ob_table_context.cpp index 6fa7948aa5..3084082ddd 100644 --- a/src/observer/table/ob_table_context.cpp +++ b/src/observer/table/ob_table_context.cpp @@ -55,6 +55,11 @@ int ObTableCtx::get_tablet_by_rowkey(const ObRowkey &rowkey, return ret; } +/* + init session info + 1. expr/das/translation need session. + 2. we use the session pool for authentication because the authentication information is stored in the session pool. +*/ int ObTableCtx::init_sess_info(ObTableApiCredential &credential) { int ret = OB_SUCCESS; @@ -94,6 +99,206 @@ int ObTableCtx::init_common(ObTableApiCredential &credential, return ret; } +/* + 1. ObTableColumnItem record some column info, such as column id、column name、and so on. + 2. we record some specific elements like is_stored_generated_column_ + is_auto_increment_、auto_filled_timestamp_ for specific function. + 3. cascaded_column_ids_ is for update stored generate column. + such as: + - create table t( + `c1` int primary key, + `c2` varchar(20), + `c3` varchar(20) generated always as (substring(`c2`, 1, 4) stored)); + - insert into t(`c1`, `c2`) values(1, 'hello'); + - update t set `c2`='world' where `c1`=1; + `c3` should be updated as well. +*/ +int ObTableCtx::construct_column_items() +{ + int ret = OB_SUCCESS; + + if (OB_ISNULL(table_schema_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("table schema is null", K(ret)); + } else { + const ObColumnSchemaV2 *col_schema = nullptr; + ObTableSchema::const_column_iterator iter = table_schema_->column_begin(); + ObTableSchema::const_column_iterator end = table_schema_->column_end(); + for (int64_t i = 0; OB_SUCC(ret) && iter != end; ++iter, i++) { + col_schema = *iter; + if (OB_ISNULL(col_schema)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("column schema is NULL", K(ret)); + } else { + ObTableColumnItem item; + item.col_idx_ = i; + item.column_id_ = col_schema->get_column_id(); + item.table_id_ = col_schema->get_table_id(); + item.column_name_ = col_schema->get_column_name_str(); + item.default_value_ = col_schema->get_cur_default_value(); + item.is_generated_column_ = col_schema->is_generated_column(); + item.is_stored_generated_column_ = col_schema->is_stored_generated_column(); + item.is_virtual_generated_column_ = col_schema->is_virtual_generated_column(); + item.is_auto_increment_ = col_schema->is_autoincrement(); + item.generated_expr_str_ = item.default_value_.get_string(); + item.auto_filled_timestamp_ = col_schema->is_on_update_current_timestamp(); + if (item.is_auto_increment_ && OB_FAIL(add_auto_inc_param(*col_schema))) { + LOG_WARN("fail to add auto inc param", K(ret), K(item)); + } else if (item.is_generated_column_ + && OB_FAIL(col_schema->get_cascaded_column_ids(item.cascaded_column_ids_))) { + LOG_WARN("fail to get cascaded column ids", K(ret), K(item), K(*col_schema)); + } else if (OB_FAIL(column_items_.push_back(item))) { + LOG_WARN("fail to push back column item", K(ret), K_(column_items), K(item)); + } + } + } + } + + return ret; +} + +int ObTableCtx::get_column_item_by_column_id(uint64_t column_id, const ObTableColumnItem *&item) const +{ + int ret = OB_SUCCESS; + + if (column_items_.empty()) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("column items is empty", K(ret)); + } else { + bool found = false; + for (int64_t i = 0; i < column_items_.count() && !found; i++) { + const ObTableColumnItem &tmp_item = column_items_.at(i); + if (tmp_item.column_id_ == column_id) { + found = true; + item = &tmp_item; + } + } + } + + return ret; +} + +int ObTableCtx::get_column_item_by_expr(ObRawExpr *raw_expr, const ObTableColumnItem *&item) const +{ + int ret = OB_SUCCESS; + + if (OB_ISNULL(raw_expr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("raw_expr is null", K(ret)); + } else if (column_items_.empty()) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("column items is empty", K(ret)); + } else { + bool found = false; + for (int64_t i = 0; i < column_items_.count() && !found; i++) { + const ObTableColumnItem &tmp_item = column_items_.at(i); + if (tmp_item.raw_expr_ == raw_expr) { + found = true; + item = &tmp_item; + } + } + } + + return ret; +} + +int ObTableCtx::get_column_item_by_expr(ObColumnRefRawExpr *expr, const ObTableColumnItem *&item) const +{ + int ret = OB_SUCCESS; + + if (OB_ISNULL(expr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("raw_expr is null", K(ret)); + } else if (column_items_.empty()) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("column items is empty", K(ret)); + } else { + bool found = false; + for (int64_t i = 0; i < column_items_.count() && !found; i++) { + const ObTableColumnItem &tmp_item = column_items_.at(i); + if (tmp_item.expr_ == expr) { + found = true; + item = &tmp_item; + } + } + } + + return ret; +} + +int ObTableCtx::get_expr_from_column_items(const ObString &col_name, ObRawExpr *&expr) const +{ + int ret = OB_SUCCESS; + + if (column_items_.empty()) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("column items is empty", K(ret)); + } else { + bool found = false; + for (int64_t i = 0; OB_SUCC(ret) && i < column_items_.count() && !found; i++) { + const ObTableColumnItem &item = column_items_.at(i); + if (0 == item.column_name_.case_compare(col_name)) { + if (OB_ISNULL(item.expr_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("item expr is null", K(ret), K(item)); + } else { + found = true; + expr = item.expr_; + } + } + } + } + + return ret; +} + +int ObTableCtx::get_expr_from_assignments(const ObString &col_name, ObRawExpr *&expr) const +{ + int ret = OB_SUCCESS; + + bool found = false; + for (int64_t i = 0; OB_SUCC(ret) && i < assigns_.count() && !found; i++) { + const ObTableAssignment &assign = assigns_.at(i); + if (OB_ISNULL(assign.column_item_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("assign column item is null", K(ret)); + } else if (0 == assign.column_item_->column_name_.case_compare(col_name)) { + found = true; + expr = assign.expr_; + } + } + + return ret; +} + +/* + 1. ObConflictChecker need ObPhysicalPlanCtx. + 2. now() expr need ObPhysicalPlanCtx.cur_time_. + 3. das need ObPhysicalPlanCtx to check task should retry or not. +*/ +int ObTableCtx::init_physical_plan_ctx(int64_t timeout_ts, int64_t tenant_schema_version) +{ + int ret = OB_SUCCESS; + void *buf = allocator_.alloc(sizeof(ObPhysicalPlanCtx)); + if (OB_ISNULL(buf)) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to alloc ObPhysicalPlanCtx", K(ret), K(sizeof(ObPhysicalPlanCtx))); + } else { + ObPhysicalPlanCtx *phy_plan_ctx = new(buf) ObPhysicalPlanCtx(allocator_); + phy_plan_ctx->set_timeout_timestamp(timeout_ts); // ObConflictChecker::init_das_scan_rtdef 需要 + phy_plan_ctx->set_tenant_schema_version(tenant_schema_version); + phy_plan_ctx->set_cur_time(ObTimeUtility::current_time()); + exec_ctx_.set_physical_plan_ctx(phy_plan_ctx); + } + return ret; +} + +/* + init table context common param, such as tenant_id_, database_id_,and so on. we also do extra things: + - get session info + - construct column items + - adjust entity +*/ int ObTableCtx::init_common(ObTableApiCredential &credential, const common::ObTabletID &arg_tablet_id, const common::ObString &arg_table_name, @@ -110,7 +315,7 @@ int ObTableCtx::init_common(ObTableApiCredential &credential, arg_table_name, false, /* is_index */ table_schema_))) { - LOG_WARN("fail to get table schema", K(ret), K(tenant_id), "database_id", credential.database_id_, K(arg_table_name)); + LOG_WARN("fail to get table schema", K(ret), K(tenant_id), K(database_id), K(arg_table_name)); } else if (OB_FAIL(inner_init_common(credential, arg_tablet_id, arg_table_name, timeout_ts))) { LOG_WARN("fail to inner init common", KR(ret), K(credential), K(arg_tablet_id), K(arg_table_name), K(timeout_ts)); @@ -127,19 +332,22 @@ int ObTableCtx::inner_init_common(ObTableApiCredential &credential, int ret = OB_SUCCESS; bool is_cache_hit = false; const ObTenantSchema *tenant_schema = nullptr; - const uint64_t tenant_id = credential.tenant_id_; - const uint64_t database_id = credential.database_id_; + tenant_id_ = credential.tenant_id_; + database_id_ = credential.database_id_; ObTabletID tablet_id = arg_tablet_id; + if (OB_ISNULL(table_schema_)) { ret = OB_ERR_UNKNOWN_TABLE; - LOG_WARN("table schema is null", K(ret), K(tenant_id), K(table_name)); - } else if (OB_FAIL(schema_guard_.get_tenant_info(tenant_id, tenant_schema))) { - LOG_WARN("fail to get tenant schema", K(ret), K(tenant_id)); + LOG_WARN("table schema is null", K(ret), K(table_name)); + } else if (OB_FAIL(schema_guard_.get_tenant_info(tenant_id_, tenant_schema))) { + LOG_WARN("fail to get tenant schema", K(ret), K_(tenant_id)); } else if (OB_ISNULL(tenant_schema)) { ret = OB_SCHEMA_ERROR; LOG_WARN("tenant schema is null", K(ret)); } else if (OB_FAIL(init_sess_info(credential))) { LOG_WARN("fail to init session info", K(ret), K(credential)); + } else if (OB_FAIL(init_physical_plan_ctx(timeout_ts, tenant_schema->get_schema_version()))) { + LOG_WARN("fail to init physical plan ctx", K(ret)); } else if (!arg_tablet_id.is_valid()) { if (is_scan_) { // 扫描场景使用table_schema上的tablet id,客户端已经做了路由分发 if (table_schema_->is_partitioned_table()) { // 不支持分区表 @@ -161,17 +369,17 @@ int ObTableCtx::inner_init_common(ObTableApiCredential &credential, } if (OB_FAIL(ret)) { - } else if (OB_FAIL(GCTX.location_service_->get(tenant_id, + } else if (OB_FAIL(GCTX.location_service_->get(tenant_id_, tablet_id, 0, /* expire_renew_time */ is_cache_hit, ls_id_))) { LOG_WARN("fail to get ls id", K(ret), K(tablet_id), K(table_name)); + } else if (OB_FAIL(construct_column_items())) { + LOG_WARN("fail to construct column items", K(ret)); } else if (!is_scan_ && OB_FAIL(adjust_entity())) { LOG_WARN("fail to adjust entity", K(ret)); } else { - tenant_id_ = tenant_id; - database_id_ = database_id; table_name_ = table_name; ref_table_id_ = table_schema_->get_table_id(); index_table_id_ = ref_table_id_; @@ -182,14 +390,10 @@ int ObTableCtx::inner_init_common(ObTableApiCredential &credential, is_ttl_table_ = !table_schema_->get_ttl_definition().empty(); } - if (OB_SUCC(ret) && OB_FAIL(init_phy_plan_ctx())) { - LOG_WARN("fail to init physical plan ctx", KR(ret)); - } - return ret; } -// 获取rowkey或者二级索引的columns type +// get columns type from index_schema or primary table schema int ObTableCtx::generate_columns_type(ObIArray &columns_type) { int ret = OB_SUCCESS; @@ -284,6 +488,13 @@ int ObTableCtx::read_real_lob(ObIAllocator &allocator, ObObj &obj) return ret; } +/* + check column type + - nullable + - check data type mismatch or not + - check collation for string type and convert obj type to the column type (char, varchar or text) + - check accuracy +*/ int ObTableCtx::adjust_column_type(const ObExprResType &column_type, ObObj &obj) { @@ -339,6 +550,13 @@ int ObTableCtx::adjust_column_type(const ObExprResType &column_type, return ret; } +/* + check user obj is valid or not, we check: + - column type + - collation type + - nullable + - accuracy. +*/ int ObTableCtx::adjust_column(const ObColumnSchemaV2 &col_schema, ObObj &obj) { int ret = OB_SUCCESS; @@ -353,6 +571,11 @@ int ObTableCtx::adjust_column(const ObColumnSchemaV2 &col_schema, ObObj &obj) return ret; } +/* + check user rowkey is valid or not. + 1. rowkey count should equal schema rowkey count, except for auto increment. + 2. rowkey value should be valid. +*/ int ObTableCtx::adjust_rowkey() { int ret = OB_SUCCESS; @@ -365,16 +588,11 @@ int ObTableCtx::adjust_rowkey() const int64_t schema_rowkey_cnt = table_schema_->get_rowkey_column_num(); const int64_t entity_rowkey_cnt = rowkey.get_obj_cnt(); bool has_auto_inc = false; // only one auto increment column in a table - bool is_full_filled = entity_rowkey_cnt == schema_rowkey_cnt; // 是否把主键值填全,存在自增列场景下可以不填全 + bool is_full_filled = entity_rowkey_cnt == schema_rowkey_cnt; // allow not full filled when rowkey has auto_increment; const ObRowkeyInfo &rowkey_info = table_schema_->get_rowkey_info(); const ObColumnSchemaV2 *col_schema = nullptr; uint64_t column_id = OB_INVALID_ID; ObObj *obj_ptr = rowkey.get_obj_ptr(); - // 不存在自增列的情况下,全部校验 - // 存在自增列情况下,用户填了值,全部校验 - // 存在自增列情况下,用户没有填值,自增列不校验,其他列校验 - // idx 是为了在主键中存在自增列是为了解决使用i访问obj_ptr会出现访问越界的问题,因为在主键存在自增列场景下,用户可以 - // 不填自增列值,这时rowkey中的obj数量少于schema上的rowkey数量 for (int64_t i = 0, idx = 0; OB_SUCC(ret) && i < schema_rowkey_cnt; i++) { bool need_check = true; if (OB_FAIL(rowkey_info.get_column_id(i, column_id))) { @@ -387,7 +605,7 @@ int ObTableCtx::adjust_rowkey() if (col_schema->is_part_key_column()) { ret = OB_NOT_SUPPORTED; LOG_WARN("auto increment column could not be partition column", K(ret), K(*col_schema)); - } else if (!is_full_filled) { // 当前列是自增列,但是用户没有填值,不需要校验 + } else if (!is_full_filled) { // curr column is auto_increment and user not fill,no need to check need_check = false; } } @@ -416,11 +634,16 @@ int ObTableCtx::adjust_rowkey() return ret; } +/* + check user properties is valid or not. + 1. rowkey column should not appear in properties, except for get operation. + 2. we do not check column when do get operation, cause property value is empty. +*/ int ObTableCtx::adjust_properties() { int ret = OB_SUCCESS; - bool is_get = (ObTableOperationType::Type::GET == operation_type_); + if (OB_ISNULL(table_schema_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("table schema is null", K(ret)); @@ -449,6 +672,10 @@ int ObTableCtx::adjust_properties() return ret; } +/* + check the legality of entity. + - we do not check htable's rowkey, cause htable's rowkey is in properties. +*/ int ObTableCtx::adjust_entity() { int ret = OB_SUCCESS; @@ -482,6 +709,11 @@ bool ObTableCtx::has_exist_in_columns(const ObIArray &columns, return exist; } +/* + genreate key range when do scan. + 1. check the legality of column obj in query range. + 2. fill primary key object when do index scan when user not filled them. +*/ int ObTableCtx::generate_key_range(const ObIArray &scan_ranges) { int ret = OB_SUCCESS; @@ -580,6 +812,14 @@ int ObTableCtx::generate_key_range(const ObIArray &scan_ranges) return ret; } +/* + init scan parameters. + 1. init some common scan parameters such as is_weak_read_、scan_order_、limit_、is_index_back_ and so on. + 2. genreate key range。 + 3. check is_index_back_ when do index scan, need index back if the query column is not in the index table. + 4. select_col_ids_ is same order with schema, + query_col_ids_ and query_col_names_ is same with user query column order. +*/ int ObTableCtx::init_scan(const ObTableQuery &query, const bool &is_wead_read) { @@ -624,7 +864,7 @@ int ObTableCtx::init_scan(const ObTableQuery &query, } else if (query.is_aggregate_query() && OB_FAIL(init_agg_cell_proj(query.get_aggregations().count()))) { LOG_WARN("fail to init agg cell proj", K(ret)); } else { - // select_col_ids用schema序 + // select_col_ids_ is same order with schema int64_t cell_idx = 0; for (ObTableSchema::const_column_iterator iter = table_schema_->column_begin(); OB_SUCC(ret) && iter != table_schema_->column_end(); ++iter, cell_idx++) { @@ -645,14 +885,14 @@ int ObTableCtx::init_scan(const ObTableQuery &query, LOG_WARN("failed to add aggregate projector", K(ret), K(cell_idx), K(column_name)); } else if (is_index_scan_ && !is_index_back_ && OB_ISNULL(column_schema = index_schema_->get_column_schema(column_name))) { - is_index_back_ = true; // 判断是否需要回表,查询的列不在索引表上即需要回表 + is_index_back_ = true; } } else if (has_exist_in_columns(select_columns, column_schema->get_column_name_str())) { if (OB_FAIL(select_col_ids_.push_back(column_schema->get_column_id()))) { LOG_WARN("fail to add column id", K(ret)); } else if (is_index_scan_ && !is_index_back_ && OB_ISNULL(column_schema = index_schema_->get_column_schema(column_name))) { - is_index_back_ = true; // 判断是否需要回表,查询的列不在索引表上即需要回表 + is_index_back_ = true; } } } @@ -662,7 +902,7 @@ int ObTableCtx::init_scan(const ObTableQuery &query, LOG_WARN("select_col_ids or select_metas count is not equal to select_columns", K(select_columns), K(select_col_ids_)); } else if (!select_all_columns) { - // query_col_ids_是用户查询序 + // query_col_ids_ is user query order for (int64_t i = 0; OB_SUCC(ret) && i < select_columns.count(); i++) { if (OB_ISNULL(column_schema = table_schema_->get_column_schema(select_columns.at(i)))) { ret = OB_SCHEMA_ERROR; @@ -682,56 +922,94 @@ int ObTableCtx::init_scan(const ObTableQuery &query, } int ObTableCtx::init_insert() +{ + return init_dml_related_tid(); +} + +/* + stored generate column should be updated when reference column was updated. + such as: + - create table t( + `c1` int primary key, + `c2` varchar(20), + `c3` varchar(20) generated always as (substring(`c2`, 1, 4) stored)); + - insert into t(`c1`, `c2`) values(1, 'hello'); + - update t set `c2`='world' where `c1`=1; + c3 should be update. + 1. match stored generated column by column_id, generated column record cascaded_column_ids_. + c1-16 c2-17 c3-18 + cascaded_column_ids_-(17) + 2. alloc ObTableColumnItem for new ObTableAssignment. +*/ +int ObTableCtx::add_stored_generated_column_assignment(const ObTableAssignment &assign) { int ret = OB_SUCCESS; - ObPhysicalPlanCtx *phy_plan_ctx = get_physical_plan_ctx(); - if (OB_ISNULL(phy_plan_ctx)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("phy_plan_ctx is null", K(ret)); - } else if (OB_FAIL(add_auto_inc_param(*phy_plan_ctx))) { - LOG_WARN("fail to add auto inc param", K(ret), K(phy_plan_ctx)); + + for (int64_t i = 0; OB_SUCC(ret) && i < column_items_.count(); i++) { + ObTableColumnItem &item = column_items_.at(i); + if (item.is_stored_generated_column_) { + bool match = false; + for (int64_t j = 0; j < item.cascaded_column_ids_.count() && !match; j++) { + const uint64_t column_id = item.cascaded_column_ids_.at(j); + if (column_id == assign.column_item_->column_id_) { + match = true; + } + } + if (match) { + void *buf = ctx_allocator_.alloc(sizeof(ObTableColumnItem)); + if (OB_ISNULL(buf)) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to alloc ObTableColumnItem", K(ret), K(sizeof(ObTableColumnItem))); + } else { + ObTableColumnItem *tmp_item = new(buf) ObTableColumnItem(); + *tmp_item = item; + ObTableAssignment tmp_assign(tmp_item); + if (OB_FAIL(assigns_.push_back(tmp_assign))) { + ctx_allocator_.free(buf); + LOG_WARN("fail to push back assignment", K(ret), K_(assigns), K(tmp_assign)); + } + } + } + } } return init_dml_related_tid(); } -int ObTableCtx::init_assign_ids(ObAssignIds &assign_ids, - const ObTableEntity &entity) +/* + init assignments when do update or insertUp. + 1. user assignment should be add. + 2. stored generate column should be add when reference column is updated. + such as: + - create table t( + `c1` int primary key, + `c2` varchar(20), + `c3` varchar(20) generated always as (substring(`c2`, 1, 4) stored)); + - insert into t(`c1`, `c2`) values(1, 'hello'); + - update t set `c2`='world' where `c1`=1; + c3 should be update. + 3. on update current timestamp should be add. +*/ +int ObTableCtx::init_assignments(const ObTableEntity &entity) { int ret = OB_SUCCESS; - ObArray storage_col_ids; + ObObj prop_obj; - if (OB_ISNULL(table_schema_)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("table schema is null", K(ret)); - } else if (OB_FAIL(table_schema_->get_column_ids(storage_col_ids))) { - LOG_WARN("fail to get column ids", K(ret)); - } else if (OB_FAIL(assign_ids.init(storage_col_ids.count()))) { - LOG_WARN("fail to init assign_ids capacity", K(ret), K(storage_col_ids.count())); - } else { - ObObj prop_value; // useless - const share::schema::ObColumnSchemaV2 *col_schema = NULL; - for (int64_t i = 0; OB_SUCC(ret) && i < storage_col_ids.count(); i++) { - ObString cname; - ObAssignId assign_id; - if (OB_ISNULL(col_schema = table_schema_->get_column_schema(storage_col_ids.at(i)))) { - ret = OB_ERR_COLUMN_NOT_FOUND; - LOG_WARN("column not exists", K(ret), K(cname)); - } else if (col_schema->is_stored_generated_column()) { - assign_id.column_id_ = storage_col_ids.at(i); - assign_id.idx_ = i; - if (OB_FAIL(assign_ids.push_back(assign_id))) { - LOG_WARN("fail to push back assign id", K(ret), K(assign_id)); - } - } else if (FALSE_IT(cname = col_schema->get_column_name_str())) { - // do nothing - } else if (OB_SUCCESS != entity.get_property(cname, prop_value)) { - // 这一列没有被更新,跳过 - } else { - assign_id.column_id_ = storage_col_ids.at(i); - assign_id.idx_ = i; - if (OB_FAIL(assign_ids.push_back(assign_id))) { - LOG_WARN("fail to push back assign id", K(ret), K(assign_id)); - } + for (int64_t i = 0; OB_SUCC(ret) && i < column_items_.count(); i++) { + ObTableColumnItem &item = column_items_.at(i); + if (OB_SUCCESS == entity.get_property(item.column_name_, prop_obj)) { + ObTableAssignment assign(&item); + assign.assign_value_ = prop_obj; // shadow copy when prop_obj is string type + assign.is_assigned_ = true; + if (OB_FAIL(assigns_.push_back(assign))) { + LOG_WARN("fail to push back assignment", K(ret), K_(assigns), K(assign)); + } else if (table_schema_->has_generated_column() + && OB_FAIL(add_stored_generated_column_assignment(assign))) { + LOG_WARN("fail to add soterd generated column assignment", K(ret), K(assign)); + } + } else if (item.auto_filled_timestamp_) { // on update current timestamp + ObTableAssignment assign(&item); + if (OB_FAIL(assigns_.push_back(assign))) { + LOG_WARN("fail to push back assignment", K(ret), K_(assigns), K(assign)); } } } @@ -739,38 +1017,51 @@ int ObTableCtx::init_assign_ids(ObAssignIds &assign_ids, return ret; } +/* + init scan parameters. + 1. init assignments + 2. init scan parameters for child executor(scan executor) of update executor. + 3. init related index table ids, cause we need to write index table as well. +*/ int ObTableCtx::init_update() { int ret = OB_SUCCESS; is_for_update_ = true; - const bool is_batch = OB_ISNULL(batch_op_) ? false : true; - const ObTableEntity *entity = nullptr; - ObAssignIds assign_ids(allocator_); - // 1. init assign_ids_ - if (OB_FAIL(init_assign_ids(assign_ids_, static_cast(*entity_)))) { - LOG_WARN("fail to init assign ids", K(ret), K(*entity_)); - } - // 2. init scan - if (OB_SUCC(ret)) { + // 1. init assignments + if (OB_FAIL(init_assignments(static_cast(*entity_)))) { + LOG_WARN("fail to init assignments", K(ret), K(*entity_)); + } else { + // 2. init scan index_table_id_ = ref_table_id_; is_index_scan_ = false; is_index_back_ = false; is_get_ = true; scan_order_ = ObQueryFlag::Forward; - if (OB_FAIL(table_schema_->get_column_ids(select_col_ids_))) { // init select_col_ids_ + if (OB_FAIL(table_schema_->get_column_ids(select_col_ids_))) { LOG_WARN("fail to get column ids", K(ret)); + } else if (OB_FAIL(init_dml_related_tid())) { // 3. init related index table id + LOG_WARN("fail to init dml related table ids", K(ret)); } } - // 3. init related index table id - if (OB_SUCC(ret) && OB_FAIL(init_dml_related_tid())) { - LOG_WARN("fail to init dml related table ids", K(ret)); - } - return ret; } +/* + init delete parameters. + 1. init scan parameters for child executor(scan executor) of delete executor. + - in htable, we should not query stored generate column. + create table if not exists htable1_cf1 ( + `K` varbinary(1024), + `Q` varbinary(256), + `T` bigint, + `V` varbinary(1024), + `K_PREFIX` varbinary(1024) GENERATED ALWAYS AS (substr(`K`,1,32)) STORED, primary key(`K`, `Q`, `T`)); + `K_PREFIX` should not be query. + - htable use query and delete, is_get_ should not be set. + 2. init related index table ids, cause we need to delete index table as well. +*/ int ObTableCtx::init_delete() { int ret = OB_SUCCESS; @@ -788,7 +1079,7 @@ int ObTableCtx::init_delete() if (OB_ISNULL(column_schema = table_schema_->get_column_schema_by_idx(i))) { ret = OB_SCHEMA_ERROR; LOG_WARN("fail to get column schema bu idx", K(ret), K(i)); - } else if (column_schema->is_generated_column()) { + } else if (column_schema->is_virtual_generated_column()) { // skip } else if (OB_FAIL(select_col_ids_.push_back(column_schema->get_column_id()))) { LOG_WARN("fail to push back column id", K(ret), K(column_schema->get_column_id())); @@ -805,42 +1096,6 @@ int ObTableCtx::init_delete() return ret; } -int ObTableCtx::init_phy_plan_ctx() -{ - int ret = OB_SUCCESS; - void *buf = allocator_.alloc(sizeof(ObPhysicalPlanCtx)); - if (OB_ISNULL(buf)) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("fail to alloc ObPhysicalPlanCtx", K(ret), K(sizeof(ObPhysicalPlanCtx))); - } else { - ObPhysicalPlanCtx *phy_plan_ctx = new(buf) ObPhysicalPlanCtx(allocator_); - phy_plan_ctx->set_timeout_timestamp(timeout_ts_); // ObConflictChecker::init_das_scan_rtdef 需要 - phy_plan_ctx->set_tenant_schema_version(tenant_schema_version_); - phy_plan_ctx->set_cur_time(ObTimeUtility::current_time()); - exec_ctx_.set_physical_plan_ctx(phy_plan_ctx); - } - return ret; -} - -int ObTableCtx::init_replace() -{ - int ret = OB_SUCCESS; - - if (OB_FAIL(init_dml_related_tid())) { - LOG_WARN("fail to init dml related tids", K(ret)); - } else { - ObPhysicalPlanCtx *phy_plan_ctx = get_physical_plan_ctx(); - if (OB_ISNULL(phy_plan_ctx)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("phy_plan_ctx is null", K(ret)); - } else if (OB_FAIL(add_auto_inc_param(*phy_plan_ctx))) { - LOG_WARN("fail to add auto inc param", K(ret), K(phy_plan_ctx)); - } - } - - return ret; -} - int ObTableCtx::init_ttl_delete(ObRowkey &start_key) { int ret = OB_SUCCESS; @@ -870,6 +1125,20 @@ int ObTableCtx::init_ttl_delete(ObRowkey &start_key) return ret; } +/* + init replace parameters. + - init related index table ids, cause we need to replace index table as well. +*/ +int ObTableCtx::init_replace() +{ + return init_dml_related_tid(); +} + +/* + init insertUp parameters. + 1. init update + 2. reset for is_for_update_ flag, cause init_update() had set is_for_update_=true +*/ int ObTableCtx::init_insert_up() { int ret = OB_SUCCESS; @@ -877,14 +1146,6 @@ int ObTableCtx::init_insert_up() if (OB_FAIL(init_update())) { LOG_WARN("fail to init update", K(ret)); - } else { - ObPhysicalPlanCtx *phy_plan_ctx = get_physical_plan_ctx(); - if (OB_ISNULL(phy_plan_ctx)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("phy_plan_ctx is null", K(ret)); - } else if (OB_FAIL(add_auto_inc_param(*phy_plan_ctx))) { - LOG_WARN("fail to add auto inc param", K(ret), K(phy_plan_ctx)); - } } // reset for update flag @@ -892,6 +1153,11 @@ int ObTableCtx::init_insert_up() return ret; } +/* + init get parameters, get operation use scan executor. + 1. init scan parameters + 2. get all column when user not filled select columns. +*/ int ObTableCtx::init_get() { int ret = OB_SUCCESS; @@ -927,143 +1193,160 @@ int ObTableCtx::init_get() return ret; } +/* + init append parameters, append operation use insertUp executor. + 1. init return_affected_entity_ and return_rowkey_ + 2. init insertUp, cause append operation use insertUp executor. + 3. construct generated_expr_str, cause append column use stored to generate columns for functionality. + - expr string: concat_ws('', `%s`, `%s`), `%s` mean column name + 3.1 no record in database + do: append(c1, "abc") + expr: concat_ws('', `c1`, `c1-delta`) + result: "abc", cause c1 is null + 3.1 "abc" in database + do: append(c1, "efg") + expr: concat_ws('', `c1`, `c1-delta`) + result: "abcefg" +*/ int ObTableCtx::init_append(bool return_affected_entity, bool return_rowkey) { int ret = OB_SUCCESS; return_affected_entity_ = return_affected_entity; return_rowkey_ = return_rowkey; - ObSEArray, 8> properties; if (OB_FAIL(init_insert_up())) { LOG_WARN("fail to init insert up", K(ret)); - } else if (OB_FAIL(entity_->get_properties(properties))) { - LOG_WARN("fail to get properties", K(ret)); } else { - const int64_t N = properties.count(); - for (int64_t i = 0; OB_SUCC(ret) && i < N; i++) { - ObObj &delta = properties.at(i).second; - if (delta.is_null()) { + for (int64_t i = 0; OB_SUCC(ret) && i < assigns_.count(); i++) { + ObTableAssignment &assign = assigns_.at(i); + const ObObj &delta = assign.assign_value_; + if (OB_ISNULL(assign.column_item_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("column item is null", K(ret), K(assign)); + } else if (assign.column_item_->auto_filled_timestamp_) { + // do nothing + } else if (delta.is_null()) { ret = OB_OBJ_TYPE_ERROR; LOG_WARN("append NULL is illegal", K(ret), K(delta)); } else if (OB_UNLIKELY(!ob_is_string_type(delta.get_type()))) { ret = OB_OBJ_TYPE_ERROR; LOG_WARN("can only append string type", K(ret), K(delta)); - } - } - } - - if (OB_SUCC(ret)) { - // 构造生成列表达式字符串"concat_ws('', `column_name`, `column_name`)" - const share::schema::ObColumnSchemaV2 *col_schema = NULL; - for (int64_t i = 0; OB_SUCC(ret) && i < assign_ids_.count(); i++) { - uint64_t column_id = assign_ids_.at(i).column_id_; - ObString column_name; - if (OB_ISNULL(col_schema = table_schema_->get_column_schema(column_id))) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("fail to get column schema", K(ret), K(column_id)); - } else if (FALSE_IT(column_name = col_schema->get_column_name_str())) { } else { - const int64_t total_len = 22 + column_name.length() + column_name.length(); + const ObString &column_name = assign.column_item_->column_name_; + const int64_t total_len = strlen("concat_ws('', ``, ``)") + 1 + + column_name.length() + column_name.length(); int64_t actual_len = -1; char *buf = NULL; if (OB_ISNULL(buf = static_cast(allocator_.alloc(total_len)))) { ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_ERROR("fail to alloc memory", K(ret), K(total_len)); + LOG_WARN("fail to alloc memory", K(ret), K(total_len)); } else if ((actual_len = snprintf(buf, total_len, "concat_ws('', `%s`, `%s`)", column_name.ptr(), column_name.ptr())) < 0) { ret = OB_SIZE_OVERFLOW; - LOG_WARN("fail to construct concat_ws expr string", K(ret), K(total_len)); + LOG_WARN("fail to construct concat_ws expr string", K(ret), K(total_len), K(delta)); } else { - ObString expr_str(actual_len, buf); - if (OB_FAIL(expr_strs_.push_back(expr_str))) { - LOG_WARN("fail to push back expr str", K(ret)); - } + ObString generated_expr_str(actual_len, buf); + assign.column_item_->generated_expr_str_ = generated_expr_str; + assign.is_inc_or_append_ = true; } } } } + return ret; } +/* + init increment parameters, append operation use insertUp executor. + 1. init return_affected_entity_ and return_rowkey_ + 2. init insertUp, cause increment operation use insertUp executor. + 3. construct generated_expr_str, cause increment column use stored to generate columns for functionality. + - expr string: IFNULL(`%s`, 0) + `%s`, `%s` mean column name + 3.1 no record in database + do: increment(c1, 1) + expr: IFNULL(`c1`, 0) + `c1_delta` + result: 1, cause c1 is null + 3.1 1 in database + do: increment(c1, 1) + expr: IFNULL(`c1`, 0) + `c1_delta` + result: 2, cause c1 is null +*/ int ObTableCtx::init_increment(bool return_affected_entity, bool return_rowkey) { int ret = OB_SUCCESS; return_affected_entity_ = return_affected_entity; return_rowkey_ = return_rowkey; - ObSEArray, 8> properties; if (OB_FAIL(init_insert_up())) { LOG_WARN("fail to init insert up", K(ret)); - } else if (OB_FAIL(entity_->get_properties(properties))) { - LOG_WARN("fail to get properties", K(ret)); } else { - for (int64_t i = 0; OB_SUCC(ret) && i < properties.count(); i++) { - ObObj &delta = properties.at(i).second; - if (!ob_is_int_tc(delta.get_type())) { + for (int64_t i = 0; OB_SUCC(ret) && i < assigns_.count(); i++) { + ObTableAssignment &assign = assigns_.at(i); + const ObObj &delta = assign.assign_value_; + if (OB_ISNULL(assign.column_item_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("column item is null", K(ret), K(assign)); + } else if (assign.column_item_->is_auto_increment_) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("not support increment auto increment column", K(ret), K(assign)); + } else if (assign.column_item_->auto_filled_timestamp_) { + // do nothing + } else if (!ob_is_int_tc(delta.get_type())) { ret = OB_OBJ_TYPE_ERROR; LOG_WARN("delta should only be signed integer type", K(ret), K(delta)); - } - } - } - - if (OB_SUCC(ret)) { - // 构造生成列表达式字符串"ifnull(C1, 0) + C1" - const share::schema::ObColumnSchemaV2 *col_schema = NULL; - for (int64_t i = 0; OB_SUCC(ret) && i < assign_ids_.count(); i++) { - uint64_t column_id = assign_ids_.at(i).column_id_; - ObString column_name; - if (OB_ISNULL(col_schema = table_schema_->get_column_schema(column_id))) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("fail to get column schema", K(ret), K(column_id)); - } else if (FALSE_IT(column_name = col_schema->get_column_name_str())) { } else { - const int64_t total_len = column_name.length() + column_name.length() + 16; + const ObString &column_name = assign.column_item_->column_name_; + const int64_t total_len = strlen("IFNULL(``, 0) + ``") + 1 + + column_name.length() + column_name.length(); int64_t actual_len = -1; char *buf = NULL; if (OB_ISNULL(buf = static_cast(allocator_.alloc(total_len)))) { ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_ERROR("fail to alloc memory", K(ret), K(total_len)); - } else if ((actual_len = snprintf(buf, total_len, "IFNULL(%s, 0) + %s", + LOG_WARN("fail to alloc memory", K(ret), K(total_len)); + } else if ((actual_len = snprintf(buf, total_len, "IFNULL(`%s`, 0) + `%s`", column_name.ptr(), column_name.ptr())) < 0) { ret = OB_SIZE_OVERFLOW; - LOG_WARN("fail to construct increment expr string", K(ret), K(total_len)); + LOG_WARN("fail to construct increment expr string", K(ret), K(total_len), K(delta)); } else { - ObString expr_str(actual_len, buf); - if (OB_FAIL(expr_strs_.push_back(expr_str))) { - LOG_WARN("fail to push back expr str", K(ret)); - } + ObString generated_expr_str(actual_len, buf); + assign.column_item_->generated_expr_str_ = generated_expr_str; + assign.is_inc_or_append_ = true; } } } } + return ret; } +/* + classify scan expr for get/delete/update/scan operation +*/ int ObTableCtx::classify_scan_exprs() { int ret = OB_SUCCESS; - const ObIArray *exprs = is_for_update_ ? &old_row_exprs_ : &all_exprs_.get_expr_array(); - int64_t exprs_cnt = exprs->count(); + const ObIArray &exprs = all_exprs_.get_expr_array(); - if (0 == exprs_cnt) { + if (0 == exprs.count()) { ret = OB_ERR_UNEXPECTED; LOG_WARN("exprs is empty", K(ret)); + } else if (column_items_.count() > exprs.count()) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unecpect column_items_ count", K(ret), K(column_items_), K(exprs.count())); } else if (!select_exprs_.empty()) { // had classify, do nothing } else { - for (int64_t i = 0; OB_SUCC(ret) && i < exprs_cnt; i++) { - if (exprs->at(i)->is_column_ref_expr()) { - ObColumnRefRawExpr *expr = static_cast(exprs->at(i)); - if (expr->is_rowkey_column() && OB_FAIL(rowkey_exprs_.push_back(expr))) { - LOG_WARN("fail to push back rowkey expr", K(ret)); - } else if (has_exist_in_array(select_col_ids_, expr->get_column_id()) - && OB_FAIL(select_exprs_.push_back(expr))) { - LOG_WARN("fail to push back select expr", K(ret)); - } else if (is_index_scan_ - && has_exist_in_array(index_col_ids_, expr->get_column_id()) - && OB_FAIL(index_exprs_.push_back(expr))) { - LOG_WARN("fail to push back index column expr", K(ret)); - } + for (int64_t i = 0; OB_SUCC(ret) && i < column_items_.count(); i++) { + const ObTableColumnItem &tmp_item = column_items_.at(i); + if (tmp_item.expr_->is_rowkey_column() && OB_FAIL(rowkey_exprs_.push_back(exprs.at(i)))) { + LOG_WARN("fail to push back rowkey expr", K(ret)); + } else if (has_exist_in_array(select_col_ids_, tmp_item.column_id_) + && OB_FAIL(select_exprs_.push_back(exprs.at(i)))) { + LOG_WARN("fail to push back select expr", K(ret)); + } else if (is_index_scan_ + && has_exist_in_array(index_col_ids_, tmp_item.column_id_) + && OB_FAIL(index_exprs_.push_back(exprs.at(i)))) { + LOG_WARN("fail to push back index column expr", K(ret)); } } } @@ -1084,7 +1367,8 @@ int ObTableCtx::init_exec_ctx() return ret; } -// 初始化 das context 中的 table_loc 和 tablet_loc + +// get primary tablet location and all index tablet location, add them to das context. int ObTableCtx::init_das_context(ObDASCtx &das_ctx) { int ret = OB_SUCCESS; @@ -1230,7 +1514,21 @@ int ObTableCtx::init_dml_related_tid() ret = OB_SCHEMA_ERROR; LOG_WARN("null index schema", K(ret)); } else if (index_schema->is_index_local_storage()) { - if (OB_FAIL(related_index_ids_.push_back(index_schema->get_table_id()))) { + if (ObTableOperationType::Type::UPDATE == operation_type_) { // check index column is updated or not + bool found = false; + for (int64_t j = 0; OB_SUCC(ret) && j < assigns_.count() && !found; j++) { + const ObTableAssignment &assign = assigns_.at(j); + if (OB_ISNULL(assign.column_item_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("assign column item is null", K(ret), K(assign)); + } else if (OB_NOT_NULL(index_schema->get_column_schema(assign.column_item_->column_id_))) { + found = true; + } + } + if (found && OB_FAIL(related_index_ids_.push_back(index_schema->get_table_id()))) { + LOG_WARN("fail to add related index ids", K(ret), K(index_schema->get_table_id())); + } + } else if (OB_FAIL(related_index_ids_.push_back(index_schema->get_table_id()))) { LOG_WARN("fail to add related index ids", K(ret), K(index_schema->get_table_id())); } } @@ -1273,57 +1571,59 @@ int ObTableCtx::add_aggregate_proj(int64_t cell_idx, return ret; } -int ObTableCtx::add_auto_inc_param(ObPhysicalPlanCtx &phy_plan_ctx) +/* + add auto increment parameters + - each auto increment column contains a param + - only support one auto increment column in mysql mode +*/ +int ObTableCtx::add_auto_inc_param(const ObColumnSchemaV2 &column_schema) { int ret = OB_SUCCESS; - ObIArray &auto_params = phy_plan_ctx.get_autoinc_params(); - for (ObTableSchema::const_column_iterator iter = table_schema_->column_begin(); - OB_SUCC(ret) && iter != table_schema_->column_end() && !has_auto_inc_; ++iter) { - const ObColumnSchemaV2 *col_schema = *iter; - if (OB_ISNULL(col_schema)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("column schema is NULL", K(ret)); - } else if (col_schema->is_autoincrement()) { + ObIArray &auto_params = exec_ctx_.get_physical_plan_ctx()->get_autoinc_params(); + int64_t auto_increment_cache_size = -1; + + if (!auto_params.empty()) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected auto params count, should be empty", K(ret)); + } else if (OB_FAIL(get_session_info().get_auto_increment_cache_size(auto_increment_cache_size))) { + LOG_WARN("fail to get increment factor", K(ret)); + } else { + AutoincParam param; + param.tenant_id_ = tenant_id_; + param.autoinc_table_id_ = table_schema_->get_table_id(); + param.autoinc_first_part_num_ = table_schema_->get_first_part_num(); + param.autoinc_table_part_num_ = table_schema_->get_all_part_num(); + param.autoinc_col_id_ = column_schema.get_column_id(); + param.auto_increment_cache_size_ = auto_increment_cache_size; + param.part_level_ = table_schema_->get_part_level(); + ObObjType column_type = column_schema.get_data_type(); + param.autoinc_col_type_ = column_type; + param.autoinc_desired_count_ = 0; + param.autoinc_mode_is_order_ = table_schema_->is_order_auto_increment_mode(); + param.autoinc_version_ = table_schema_->get_truncate_version(); + param.total_value_count_ = 1; + param.autoinc_increment_ = 1; + param.autoinc_offset_ = 1; + param.part_value_no_order_ = true; + if (column_schema.is_tbl_part_key_column()) { + // don't keep intra-partition value asc order when partkey column is auto inc + param.part_value_no_order_ = true; + } + if (OB_FAIL(auto_params.prepare_allocate(1))) { // only one auto inc in a table + LOG_WARN("fail to init auto params", K(ret)); + } else { + auto_params.at(0) = param; has_auto_inc_ = true; - int64_t auto_increment_cache_size = -1; - if (OB_FAIL(get_session_info().get_auto_increment_cache_size(auto_increment_cache_size))) { - LOG_WARN("fail to get increment factor", K(ret)); - } else { - AutoincParam ¶m = get_auto_inc_param(); - param.tenant_id_ = tenant_id_; - param.autoinc_table_id_ = ref_table_id_; - param.autoinc_first_part_num_ = table_schema_->get_first_part_num(); - param.autoinc_table_part_num_ = table_schema_->get_all_part_num(); - param.autoinc_col_id_ = col_schema->get_column_id(); - param.auto_increment_cache_size_ = auto_increment_cache_size; - param.part_level_ = table_schema_->get_part_level(); - ObObjType column_type = col_schema->get_data_type(); - param.autoinc_col_type_ = column_type; - param.autoinc_desired_count_ = 0; - param.autoinc_mode_is_order_ = table_schema_->is_order_auto_increment_mode(); - param.autoinc_version_ = table_schema_->get_truncate_version(); - param.total_value_count_ = 1; - param.autoinc_increment_ = 1; - param.autoinc_offset_ = 1; - param.part_value_no_order_ = true; - // for generate column id when use auto inc - set_auto_inc_column_id(col_schema->get_column_id()); - set_auto_inc_column_name(col_schema->get_column_name_str()); - if (col_schema->is_tbl_part_key_column()) { - // don't keep intra-partition value asc order when partkey column is auto inc - param.part_value_no_order_ = true; - } - if (OB_FAIL(auto_params.prepare_allocate(1))) { // only one auto inc in a table - LOG_WARN("fail to init auto params", K(ret)); - } else { - auto_params.at(0) = param; - } - } } } + return ret; } +/* + update auto increment local and gobal value. + - we need to update local and gobal value after user set specific value. +*/ int ObTableCtx::update_auto_inc_value() { int ret = OB_SUCCESS; @@ -1339,7 +1639,7 @@ int ObTableCtx::update_auto_inc_value() return ret; } -// 获取索引表的tablet_id +// get index table's tablet id int ObTableCtx::get_related_tablet_id(const share::schema::ObTableSchema &index_schema, ObTabletID &related_tablet_id) { diff --git a/src/observer/table/ob_table_context.h b/src/observer/table/ob_table_context.h index f0f35f5493..2196c2d18e 100644 --- a/src/observer/table/ob_table_context.h +++ b/src/observer/table/ob_table_context.h @@ -17,6 +17,7 @@ #include "sql/resolver/expr/ob_raw_expr_util.h" #include "sql/engine/dml/ob_dml_ctx_define.h" #include "sql/das/ob_das_scan_op.h" // for ObDASScanRtDef +#include "sql/resolver/dml/ob_dml_stmt.h" #include "share/table/ob_table.h" #include "ob_table_session_pool.h" @@ -24,23 +25,64 @@ namespace oceanbase { namespace table { - -// 用于存放ctx下自增列的信息 -struct ObTableAutoInc +struct ObTableColumnItem : public sql::ColumnItem { -public: - ObTableAutoInc() - : param_(), - auto_inc_column_id_(OB_INVALID_ID), - auto_inc_column_name_() - { - } - TO_STRING_KV(K_(param), - K_(auto_inc_column_id), - K_(auto_inc_column_name)); - AutoincParam param_; - uint64_t auto_inc_column_id_; - ObString auto_inc_column_name_; + ObTableColumnItem() + : sql::ColumnItem(), + raw_expr_(nullptr), + is_generated_column_(false), + is_stored_generated_column_(false), + is_virtual_generated_column_(false), + is_auto_increment_(false) + {} + TO_STRING_KV("ColumnItem", static_cast(*this), + KPC_(raw_expr), + K_(is_generated_column), + K_(is_stored_generated_column), + K_(is_virtual_generated_column), + K_(cascaded_column_ids), + K_(generated_expr_str), + K_(dependant_exprs), + K_(is_auto_increment)); + sql::ObRawExpr *raw_expr_; // column ref expr or calculate expr + bool is_generated_column_; + bool is_stored_generated_column_; + bool is_virtual_generated_column_; + common::ObSEArray cascaded_column_ids_; + // default equal item.default_value_.get_string() + // specific value in append and increment operation + common::ObString generated_expr_str_; + common::ObSEArray dependant_exprs_; + bool is_auto_increment_; +}; + +struct ObTableAssignment : public sql::ObAssignment +{ + ObTableAssignment() + : sql::ObAssignment(), + column_item_(nullptr), + is_inc_or_append_(false), + delta_expr_(nullptr), + is_assigned_(false) + {} + ObTableAssignment(ObTableColumnItem *item) + : sql::ObAssignment(), + column_item_(item), + is_inc_or_append_(false), + delta_expr_(nullptr), + is_assigned_(false) + {} + TO_STRING_KV("ObAssignment", static_cast(*this), + KPC_(column_item), + K_(is_inc_or_append), + KPC_(delta_expr), + K_(assign_value), + K_(is_assigned)); + ObTableColumnItem *column_item_; + bool is_inc_or_append_; // for append/increment + sql::ObColumnRefRawExpr *delta_expr_; // for append/increment + common::ObObj assign_value_; + bool is_assigned_; // did user assign specific value or not }; enum ObTableExecutorType @@ -62,19 +104,6 @@ enum ObTableExecutorType // 2.在try_process()中进行初始化 class ObTableCtx { -public: - struct ObAssignId { - ObAssignId() - : idx_(OB_INVALID_ID), - column_id_(OB_INVALID_ID) - {} - TO_STRING_KV("index", idx_, - "column_id", column_id_); - uint64_t idx_; - uint64_t column_id_; - }; - typedef common::ObFixedArray ObAssignIds; - typedef std::pair> ObGenDenpendantsPair; public: explicit ObTableCtx(common::ObIAllocator &allocator) : allocator_(allocator), @@ -84,11 +113,8 @@ public: expr_factory_(allocator_), all_exprs_(false), loc_meta_(allocator_), - assign_ids_(allocator_), agg_cell_proj_(allocator_), - auto_inc_param_(), - has_auto_inc_(false), - all_column_ref_exprs_() + has_auto_inc_(false) { // common is_init_ = false; @@ -134,6 +160,8 @@ public: K_(index_tablet_id), K_(ls_id), K_(tenant_schema_version), + K_(column_items), + K_(assigns), // scan to string K_(is_scan), K_(is_index_scan), @@ -172,6 +200,9 @@ public: OB_INLINE sql::ObExecContext& get_exec_ctx() { return exec_ctx_; } OB_INLINE sql::ObRawExprFactory& get_expr_factory() { return expr_factory_; } OB_INLINE sql::ObRawExprUniqueSet& get_all_exprs() { return all_exprs_; } + OB_INLINE ObIArray& get_all_exprs_array() { + return const_cast &>(all_exprs_.get_expr_array()); + } OB_INLINE sql::ObSQLSessionInfo& get_session_info() { return sess_guard_.get_sess_info();} OB_INLINE const sql::ObSQLSessionInfo& get_session_info() const @@ -179,6 +210,10 @@ public: OB_INLINE int64_t get_tenant_schema_version() const { return tenant_schema_version_; } OB_INLINE ObTableOperationType::Type get_opertion_type() const { return operation_type_; } OB_INLINE bool is_init() const { return is_init_; } + OB_INLINE const ObIArray& get_column_items() const { return column_items_; } + OB_INLINE ObIArray& get_column_items() { return column_items_; } + OB_INLINE const ObIArray& get_assignments() const { return assigns_; } + OB_INLINE ObIArray& get_assignments() { return assigns_; } // for scan OB_INLINE bool is_scan() const { return is_scan_; } OB_INLINE bool is_index_scan() const { return is_index_scan_; } @@ -202,16 +237,15 @@ public: OB_INLINE const common::ObIArray& get_query_col_names() const { return query_col_names_; } // for update OB_INLINE bool is_for_update() const { return is_for_update_; } - OB_INLINE const common::ObIArray& get_expr_strs() const { return expr_strs_; } OB_INLINE bool is_inc_or_append() const { return ObTableOperationType::Type::APPEND == operation_type_ || ObTableOperationType::Type::INCREMENT == operation_type_; } - OB_INLINE ObIArray& get_old_row_exprs() { return old_row_exprs_; } - OB_INLINE ObIArray& get_full_assign_exprs() { return full_assign_exprs_; } - OB_INLINE ObIArray& get_delta_exprs() { return delta_exprs_; } - OB_INLINE const ObAssignIds& get_assign_ids() const { return assign_ids_; } + OB_INLINE bool is_dml() const + { + return ObTableOperationType::Type::GET != operation_type_ && !is_scan_; + } // for dml OB_INLINE const ObIArray& get_related_index_ids() const { return related_index_ids_; } OB_INLINE bool is_for_insertup() const { return is_for_insertup_; } @@ -228,24 +262,11 @@ public: OB_INLINE bool return_affected_entity() const { return return_affected_entity_;} OB_INLINE bool return_rowkey() const { return return_rowkey_;} OB_INLINE uint64_t get_cur_cluster_version() const { return cur_cluster_version_;} - OB_INLINE common::ObIArray& get_gen_dependants_pairs() - { - return gen_dependants_pairs_; - } - OB_INLINE const common::ObIArray& get_gen_dependants_pairs() const - { - return gen_dependants_pairs_; - } OB_INLINE bool has_generated_column() const { return table_schema_->has_generated_column(); } // for aggregate OB_INLINE const common::ObIArray &get_agg_projs() const { return agg_cell_proj_; } - // for auto inc - OB_INLINE uint64_t get_auto_inc_column_id() { return auto_inc_param_.auto_inc_column_id_; } - OB_INLINE ObString get_auto_inc_column_name() { return auto_inc_param_.auto_inc_column_name_; } OB_INLINE ObPhysicalPlanCtx *get_physical_plan_ctx() { return exec_ctx_.get_physical_plan_ctx(); } OB_INLINE bool has_auto_inc() { return has_auto_inc_; } - // for rowkey constraint info - OB_INLINE common::ObIArray &get_all_column_ref_exprs() { return all_column_ref_exprs_; } //////////////////////////////////////// setter //////////////////////////////////////////////// // for common OB_INLINE void set_init_flag(bool is_init) { is_init_ = is_init; } @@ -261,8 +282,6 @@ public: // for htable OB_INLINE void set_batch_operation(const ObTableBatchOperation *batch_op) { batch_op_ = batch_op; } // for auto inc - OB_INLINE void set_auto_inc_column_id(const uint64_t &auto_inc_column_id) { auto_inc_param_.auto_inc_column_id_ = auto_inc_column_id; } - OB_INLINE void set_auto_inc_column_name(const ObString &auto_inc_column_name) { auto_inc_param_.auto_inc_column_name_ = auto_inc_column_name; } OB_INLINE bool need_auto_inc_expr() { // delete/update/get/scan操作只需要生成列引用表达式 @@ -311,14 +330,19 @@ public: int init_trans(transaction::ObTxDesc *trans_desc, const transaction::ObTxReadSnapshot &tx_snapshot); int init_das_context(ObDASCtx &das_ctx); + int init_physical_plan_ctx(int64_t timeout_ts, int64_t tenant_schema_version); // 更新全局自增值 int update_auto_inc_value(); // init table context for ttl operation bool is_ttl_table() const { return is_ttl_table_; } void set_is_ttl_table(bool is_ttl_table) { is_ttl_table_ = is_ttl_table; } - int init_phy_plan_ctx(); int init_ttl_delete(ObRowkey &start_key); + int get_column_item_by_column_id(uint64_t column_id, const ObTableColumnItem *&item) const; + int get_column_item_by_expr(sql::ObRawExpr *raw_expr, const ObTableColumnItem *&item) const; + int get_column_item_by_expr(sql::ObColumnRefRawExpr *expr, const ObTableColumnItem *&item) const; + int get_expr_from_column_items(const common::ObString &col_name, sql::ObRawExpr *&expr) const; + int get_expr_from_assignments(const common::ObString &col_name, sql::ObRawExpr *&expr) const; public: // convert lob的allocator需要保证obj写入表达式后才能析构 static int convert_lob(common::ObIAllocator &allocator, ObObj &obj); @@ -336,8 +360,8 @@ private: // for dml int init_dml_related_tid(); // for update - int init_assign_ids(ObAssignIds &assign_ids, - const ObTableEntity &entity); + int init_assignments(const ObTableEntity &entity); + int add_stored_generated_column_assignment(const ObTableAssignment &assign); // Init size of aggregation project array. // // @param [in] size The agg size @@ -350,17 +374,12 @@ private: // @return Returns OB_SUCCESS on success, error code otherwise. int add_aggregate_proj(int64_t cell_idx, const common::ObString &column_name, const ObIArray &aggregations); - AutoincParam &get_auto_inc_param() { return auto_inc_param_.param_; } - - // Add auto inc param to phy_plan_ctx. - // - // @param [in] phy_plan_ctx The phy_plan_ctx. - // @return Returns OB_SUCCESS on success, error code otherwise. - int add_auto_inc_param(ObPhysicalPlanCtx &phy_plan_ctx); + int add_auto_inc_param(const share::schema::ObColumnSchemaV2 &column_schema); private: + int construct_column_items(); int cons_column_type(const share::schema::ObColumnSchemaV2 &column_schema, - sql::ObExprResType &column_type); + sql::ObExprResType &column_type); int adjust_column_type(const ObExprResType &column_type, ObObj &obj); int adjust_column(const ObColumnSchemaV2 &col_schema, ObObj &obj); int adjust_rowkey(); @@ -401,6 +420,8 @@ private: ObTableApiSessGuard sess_guard_; sql::ObDASTableLocMeta loc_meta_; int64_t tenant_schema_version_; + common::ObSEArray column_items_; + common::ObSEArray assigns_; // for scan bool is_scan_; bool is_index_scan_; @@ -409,38 +430,30 @@ private: bool is_get_; bool read_latest_; // default true, false in single get and multi get common::ObQueryFlag::ScanOrder scan_order_; - common::ObArray select_exprs_; - common::ObArray rowkey_exprs_; - common::ObArray index_exprs_; - common::ObArray filter_exprs_; - common::ObArray select_col_ids_; // 基于schema序的select column id - common::ObArray query_col_ids_; // 用户查询的select column id - common::ObArray query_col_names_; // 用户查询的select column name,引用的是schema上的列名 - common::ObArray index_col_ids_; + common::ObSEArray select_exprs_; + common::ObSEArray rowkey_exprs_; + common::ObSEArray index_exprs_; + common::ObSEArray filter_exprs_; + common::ObSEArray select_col_ids_; // 基于schema序的select column id + common::ObSEArray query_col_ids_; // 用户查询的select column id + common::ObSEArray query_col_names_; // 用户查询的select column name,引用的是schema上的列名 + common::ObSEArray index_col_ids_; const share::schema::ObTableSchema *index_schema_; int64_t offset_; int64_t limit_; common::ObSEArray key_ranges_; - // for generate column - common::ObArray gen_dependants_pairs_; // 生成列及其依赖列数组 // for update bool is_for_update_; ObTableOperationType::Type operation_type_; - common::ObArray old_row_exprs_; - common::ObArray full_assign_exprs_; - ObAssignIds assign_ids_; // agg cell index in schema common::ObFixedArray agg_cell_proj_; // for auto inc - ObTableAutoInc auto_inc_param_; bool has_auto_inc_; // for increment/append - common::ObSEArray expr_strs_; - common::ObArray delta_exprs_; // for increment/append bool return_affected_entity_; bool return_rowkey_; // for dml - common::ObSEArray related_index_ids_; + common::ObSEArray related_index_ids_; bool is_for_insertup_; ObTableEntityType entity_type_; const ObITableEntity *entity_; @@ -448,8 +461,6 @@ private: const ObTableBatchOperation *batch_op_; // for lob adapt uint64_t cur_cluster_version_; - // for rowkey constraint info - common::ObSEArray all_column_ref_exprs_; bool is_ttl_table_; private: DISALLOW_COPY_AND_ASSIGN(ObTableCtx); @@ -563,8 +574,7 @@ public: ObTableUpdCtDef(common::ObIAllocator &alloc) : ObTableDmlBaseCtDef(alloc), full_row_(alloc), - full_assign_row_(alloc), - delta_exprs_(alloc), + delta_row_(alloc), das_ctdef_(alloc), assign_columns_(alloc), related_ctdefs_(alloc), @@ -576,14 +586,12 @@ public: { } TO_STRING_KV(K_(full_row), - K_(full_assign_row), - K_(delta_exprs), + K_(delta_row), K_(das_ctdef), K_(assign_columns), K_(related_ctdefs)); ExprFixedArray full_row_; - ExprFixedArray full_assign_row_; - ExprFixedArray delta_exprs_; // for increment/append + ExprFixedArray delta_row_; ObDASUpdCtDef das_ctdef_; ColContentFixedArray assign_columns_; DASUpdCtDefArray related_ctdefs_; diff --git a/src/observer/table/ob_table_execute_processor.cpp b/src/observer/table/ob_table_execute_processor.cpp index bd74682b27..d9f0d509d3 100644 --- a/src/observer/table/ob_table_execute_processor.cpp +++ b/src/observer/table/ob_table_execute_processor.cpp @@ -371,8 +371,6 @@ int ObTableApiExecuteP::process_get() ObNewRow *row = nullptr; if (OB_FAIL(check_arg2())) { LOG_WARN("fail to check arg", K(ret)); - } else if (OB_FAIL(init_tb_ctx())) { - LOG_WARN("fail to init table ctx", K(ret)); } else if (OB_FAIL(init_read_trans(arg_.consistency_level_, tb_ctx_.get_ls_id(), tb_ctx_.get_timeout_ts()))) { diff --git a/src/observer/table/ob_table_executor.cpp b/src/observer/table/ob_table_executor.cpp index ed308b7801..ddea72352f 100644 --- a/src/observer/table/ob_table_executor.cpp +++ b/src/observer/table/ob_table_executor.cpp @@ -72,18 +72,9 @@ void ObTableApiExecutor::clear_evaluated_flag() ObExprFrameInfo *expr_info = const_cast(tb_ctx_.get_expr_frame_info()); if (OB_NOT_NULL(expr_info)) { for (int64_t i = 0; i < expr_info->rt_exprs_.count(); i++) { - if (!tb_ctx_.has_auto_inc()) { // 如果是inc/append场景下进行了自增操作,则不应该清自增列转换的flag,特判 + const ObExpr &expr = expr_info->rt_exprs_.at(i); + if (expr.type_ != T_FUN_SYS_AUTOINC_NEXTVAL) { expr_info->rt_exprs_.at(i).clear_evaluated_flag(eval_ctx_); - } else { - if (expr_info->rt_exprs_.at(i).type_ == T_FUN_COLUMN_CONV) { - if (expr_info->rt_exprs_.at(i).args_[4]->type_ == T_FUN_SYS_AUTOINC_NEXTVAL) { - // do nothing - } else { - expr_info->rt_exprs_.at(i).clear_evaluated_flag(eval_ctx_); - } - } else { - expr_info->rt_exprs_.at(i).clear_evaluated_flag(eval_ctx_); - } } } } diff --git a/src/observer/table/ob_table_insert_up_executor.cpp b/src/observer/table/ob_table_insert_up_executor.cpp index 16ffe80c7e..2164d62282 100644 --- a/src/observer/table/ob_table_insert_up_executor.cpp +++ b/src/observer/table/ob_table_insert_up_executor.cpp @@ -87,13 +87,12 @@ int ObTableApiInsertUpExecutor::refresh_exprs_frame(const ObTableEntity *entity) const ObTableInsCtDef &ins_ctdef = insert_up_spec_.get_ctdef().ins_ctdef_; const ObTableUpdCtDef &upd_ctdef = insert_up_spec_.get_ctdef().upd_ctdef_; - clear_evaluated_flag(); if (OB_ISNULL(entity)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("entity is null", K(ret)); } else if (OB_FAIL(ObTableExprCgService::refresh_insert_up_exprs_frame(tb_ctx_, ins_ctdef.new_row_, - upd_ctdef.delta_exprs_, + upd_ctdef.delta_row_, *entity))) { LOG_WARN("fail to refresh insert up exprs frame", K(ret), K(*entity)); } @@ -108,8 +107,11 @@ int ObTableApiInsertUpExecutor::get_next_row_from_child() if (cur_idx_ >= 1) { ret = OB_ITER_END; - } else if (OB_FAIL(refresh_exprs_frame(entity))) { - LOG_WARN("fail to refresh exprs frame", K(ret)); + } else { + clear_evaluated_flag(); + if (OB_FAIL(refresh_exprs_frame(entity))) { + LOG_WARN("fail to refresh exprs frame", K(ret)); + } } return ret; @@ -158,6 +160,21 @@ int ObTableApiInsertUpExecutor::try_update_row() return ret; } +int ObTableApiInsertUpExecutor::cache_insert_row() +{ + int ret = OB_SUCCESS; + const ObExprPtrIArray &new_row_exprs = get_primary_table_new_row(); + + if (OB_FAIL(ObChunkDatumStore::StoredRow::build(insert_row_, new_row_exprs, eval_ctx_, allocator_))) { + LOG_WARN("fail to build stored row", K(ret), K(new_row_exprs)); + } else if (OB_ISNULL(insert_row_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("cache insert row is null", K(ret)); + } + + return ret; +} + // 通过主键在conflict_checker_中找到冲突旧行,执行更新 // 注意,这里更新后还可能出现二级索引冲突,eg: // create table t (C1 int, C2 varchar(10), primary key(C1), UNIQUE KEY idx_c2 (C2)); @@ -170,45 +187,32 @@ int ObTableApiInsertUpExecutor::do_insert_up_cache() { int ret = OB_SUCCESS; ObSEArray constraint_values; - bool is_skipped = false; - ObChunkDatumStore::StoredRow *insert_row = NULL; ObTableUpdRtDef &upd_rtdef = insert_up_rtdef_.upd_rtdef_; - const ObTableEntity *entity = static_cast(tb_ctx_.get_entity()); - const ObExprPtrIArray &new_row_exprs = get_primary_table_insert_row(); - // new_row_exprs因为冲突已经被conflict_checker_刷为冲突行,因此需要重新刷一遍 - if (OB_FAIL(refresh_exprs_frame(entity))) { - LOG_WARN("fail to refresh exprs frame", K(ret)); - } else if (OB_FAIL(ObChunkDatumStore::StoredRow::build(insert_row, new_row_exprs, eval_ctx_, allocator_))) { - LOG_WARN("fail to build stored row", K(ret), K(new_row_exprs)); + if (OB_ISNULL(insert_row_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("insert row is NULL", K(ret)); + } else if (OB_FAIL(conflict_checker_.check_duplicate_rowkey(insert_row_, constraint_values, true))) { + LOG_WARN("fail to check duplicated key", K(ret), KPC_(insert_row)); } else { - if (OB_ISNULL(insert_row)) { + upd_rtdef.found_rows_++; + const ObChunkDatumStore::StoredRow *upd_new_row = insert_row_; + const ObChunkDatumStore::StoredRow *upd_old_row = constraint_values.at(0).current_datum_row_; + if (OB_ISNULL(upd_old_row)) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("insert row is NULL", K(ret)); - } else if (OB_FAIL(conflict_checker_.check_duplicate_rowkey(insert_row, - constraint_values, - true))) { - LOG_WARN("fail to check duplicated key", K(ret), KPC(insert_row)); - } else { - upd_rtdef.found_rows_++; - const ObChunkDatumStore::StoredRow *upd_new_row = insert_row; - const ObChunkDatumStore::StoredRow *upd_old_row = constraint_values.at(0).current_datum_row_; - if (OB_ISNULL(upd_old_row)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("upd_old_row is NULL", K(ret)); - } else if (OB_FAIL(check_whether_row_change(*upd_old_row, - *upd_new_row, - insert_up_spec_.get_ctdef().upd_ctdef_, - is_row_changed_))) { - LOG_WARN("fail to check whether row change", K(ret)); - } else if (is_row_changed_) { - // do update - clear_evaluated_flag(); - if (OB_FAIL(conflict_checker_.update_row(upd_new_row, upd_old_row))) { - LOG_WARN("fail to update row in conflict_checker", K(ret), KPC(upd_new_row), KPC(upd_old_row)); - } else { - upd_changed_rows_++; - } + LOG_WARN("upd_old_row is NULL", K(ret)); + } else if (OB_FAIL(check_whether_row_change(*upd_old_row, + *upd_new_row, + insert_up_spec_.get_ctdef().upd_ctdef_, + is_row_changed_))) { + LOG_WARN("fail to check whether row change", K(ret)); + } else if (is_row_changed_) { + // do update + clear_evaluated_flag(); + if (OB_FAIL(conflict_checker_.update_row(upd_new_row, upd_old_row))) { + LOG_WARN("fail to update row in conflict_checker", K(ret), KPC(upd_new_row), KPC(upd_old_row)); + } else { + upd_changed_rows_++; } } } @@ -258,7 +262,6 @@ int ObTableApiInsertUpExecutor::do_update(const ObRowkey &constraint_rowkey, insert_up_rtdef_.upd_rtdef_, upd_rtctx_)); OZ(to_expr_skip_old(*constraint_value.current_datum_row_, - constraint_rowkey, insert_up_spec_.get_ctdef().upd_ctdef_)); clear_evaluated_flag(); OZ(insert_upd_new_row_to_das(insert_up_spec_.get_ctdef().upd_ctdef_, @@ -267,7 +270,6 @@ int ObTableApiInsertUpExecutor::do_update(const ObRowkey &constraint_rowkey, } else if (NULL == constraint_value.baseline_datum_row_ && NULL != constraint_value.current_datum_row_) { // 单单是唯一索引冲突的时候,会走这个分支 OZ(to_expr_skip_old(*constraint_value.current_datum_row_, - constraint_rowkey, insert_up_spec_.get_ctdef().upd_ctdef_)); OZ(insert_upd_new_row_to_das(insert_up_spec_.get_ctdef().upd_ctdef_, insert_up_rtdef_.upd_rtdef_, @@ -295,6 +297,8 @@ int ObTableApiInsertUpExecutor::get_next_row() } else if (!is_duplicated()) { insert_rows_ = 1; LOG_TRACE("try insert is not duplicated", K(ret), K(insert_rows_)); + } else if (OB_FAIL(cache_insert_row())) { + LOG_WARN("fail to cache insert row", K(ret)); } else if (OB_FAIL(fetch_conflict_rowkey(conflict_checker_))) { LOG_WARN("fail to fetch conflict row", K(ret)); } else if (OB_FAIL(reset_das_env(insert_up_rtdef_.ins_rtdef_))) { diff --git a/src/observer/table/ob_table_insert_up_executor.h b/src/observer/table/ob_table_insert_up_executor.h index d4d0865d05..50196d536d 100644 --- a/src/observer/table/ob_table_insert_up_executor.h +++ b/src/observer/table/ob_table_insert_up_executor.h @@ -25,8 +25,7 @@ public: ObTableApiInsertUpSpec(common::ObIAllocator &alloc, const ObTableExecutorType type) : ObTableApiModifySpec(alloc, type), insert_up_ctdef_(alloc), - conflict_checker_ctdef_(alloc), - all_saved_exprs_(alloc) + conflict_checker_ctdef_(alloc) { } public: @@ -34,12 +33,9 @@ public: OB_INLINE ObTableInsUpdCtDef& get_ctdef() { return insert_up_ctdef_; } OB_INLINE const sql::ObConflictCheckerCtdef& get_conflict_checker_ctdef() const { return conflict_checker_ctdef_; } OB_INLINE sql::ObConflictCheckerCtdef& get_conflict_checker_ctdef() { return conflict_checker_ctdef_; } - OB_INLINE const common::ObIArray& get_all_saved_exprs() const { return all_saved_exprs_; } - OB_INLINE common::ObIArray& get_all_saved_exprs() { return all_saved_exprs_; } private: ObTableInsUpdCtDef insert_up_ctdef_; sql::ObConflictCheckerCtdef conflict_checker_ctdef_; - sql::ExprFixedArray all_saved_exprs_; private: DISALLOW_COPY_AND_ASSIGN(ObTableApiInsertUpSpec); }; @@ -52,6 +48,7 @@ public: allocator_(ObModIds::TABLE_PROC, OB_MALLOC_NORMAL_BLOCK_SIZE, MTL_ID()), insert_up_spec_(spec), insert_up_rtdef_(), + insert_row_(nullptr), insert_rows_(0), upd_changed_rows_(0), upd_rtctx_(eval_ctx_, exec_ctx_, get_fake_modify_op()), @@ -110,6 +107,7 @@ private: int try_insert_row(); int try_update_row(); int do_insert_up_cache(); + int cache_insert_row(); int prepare_final_insert_up_task(); int do_update(const ObRowkey &constraint_rowkey, const sql::ObConflictValue &constraint_value); @@ -119,6 +117,7 @@ private: common::ObArenaAllocator allocator_; const ObTableApiInsertUpSpec &insert_up_spec_; ObTableInsUpdRtDef insert_up_rtdef_; + ObChunkDatumStore::StoredRow *insert_row_; int64_t insert_rows_; int64_t upd_changed_rows_; sql::ObDMLRtCtx upd_rtctx_; diff --git a/src/observer/table/ob_table_modify_executor.cpp b/src/observer/table/ob_table_modify_executor.cpp index 4359e9ed0e..1a55101c75 100644 --- a/src/observer/table/ob_table_modify_executor.cpp +++ b/src/observer/table/ob_table_modify_executor.cpp @@ -410,7 +410,6 @@ int ObTableApiModifyExecutor::check_whether_row_change(const ObChunkDatumStore:: } int ObTableApiModifyExecutor::to_expr_skip_old(const ObChunkDatumStore::StoredRow &store_row, - const ObRowkey &constraint_rowkey, const ObTableUpdCtDef &upd_ctdef) { int ret = OB_SUCCESS; @@ -430,37 +429,35 @@ int ObTableApiModifyExecutor::to_expr_skip_old(const ObChunkDatumStore::StoredRo } // 2. refresh assign column expr datum - const ObTableCtx::ObAssignIds &assign_ids = tb_ctx_.get_assign_ids(); - const int64_t N = assign_ids.count(); - for (uint64_t i = 0; OB_SUCC(ret) && i < N; ++i) { - uint64_t assign_id = assign_ids.at(i).idx_; - const ObColumnSchemaV2 *col_schema = nullptr; - if (OB_ISNULL(col_schema = table_schema->get_column_schema_by_idx(assign_id))) { - ret = OB_SCHEMA_ERROR; - LOG_WARN("fail to get column schema", K(ret), K(assign_id), K(*table_schema)); - } else if (assign_id >= store_row.cnt_) { - ret = OB_ERROR_OUT_OF_RANGE; - LOG_WARN("assign idx out of range", K(ret), K(assign_id), K(store_row.cnt_)); - } else if (assign_id >= new_row.count()) { - ret = OB_ERROR_OUT_OF_RANGE; - LOG_WARN("assign idx out of range", K(ret), K(assign_id), K(new_row.count())); - } else if (col_schema->is_virtual_generated_column()) { + const ObIArray &assigns = tb_ctx_.get_assignments(); + for (int64_t i = 0; OB_SUCC(ret) && i < assigns.count(); i++) { + const ObTableAssignment &assign = assigns.at(i); + if (OB_ISNULL(assign.column_item_)) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("should not have virtual generated expr", K(ret)); - } else if (col_schema->is_stored_generated_column()) { - ObTableCtx &ctx = const_cast(tb_ctx_); - if (OB_FAIL(ObTableExprCgService::refresh_generated_column_related_frame(ctx, - upd_ctdef.old_row_, - upd_ctdef.full_assign_row_, - assign_ids, - *col_schema))) { - LOG_WARN("fail to refresh generated column related frame", K(ret), K(ctx), K(*col_schema)); - } + LOG_WARN("assign column item is null", K(ret), K(assign)); + } else if (new_row.count() < assign.column_item_->col_idx_) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected assign projector_index_", K(ret), K(new_row), K(assign.column_item_)); + } else if (assign.column_item_->is_virtual_generated_column_) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("virtual generated column not support to update", K(ret), K(assign)); } else { - const ObExpr *expr = new_row.at(assign_id); - expr->locate_expr_datum(eval_ctx_) = store_row.cells()[assign_id]; - expr->get_eval_info(eval_ctx_).evaluated_ = true; - expr->get_eval_info(eval_ctx_).projected_ = true; + ObExpr *expr = new_row.at(assign.column_item_->col_idx_); + if (OB_ISNULL(expr)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("expr is null", K(ret)); + } else if (assign.column_item_->is_stored_generated_column_) { + // do nothing, stored generated column not need to fill + } else if (assign.column_item_->auto_filled_timestamp_ && !assign.is_assigned_) { + ObDatum *tmp_datum = nullptr; + if (OB_FAIL(expr->eval(eval_ctx_, tmp_datum))) { + LOG_WARN("fail to eval current timestamp expr", K(ret)); + } + } else { + expr->locate_expr_datum(eval_ctx_) = store_row.cells()[assign.column_item_->col_idx_]; + expr->get_eval_info(eval_ctx_).evaluated_ = true; + expr->get_eval_info(eval_ctx_).projected_ = true; + } } } } diff --git a/src/observer/table/ob_table_modify_executor.h b/src/observer/table/ob_table_modify_executor.h index 1d4de7542f..df92faa077 100644 --- a/src/observer/table/ob_table_modify_executor.h +++ b/src/observer/table/ob_table_modify_executor.h @@ -108,7 +108,6 @@ protected: const ObTableUpdCtDef &upd_ctdef, bool &is_row_changed); int to_expr_skip_old(const ObChunkDatumStore::StoredRow &store_row, - const ObRowkey &constraint_rowkey, const ObTableUpdCtDef &upd_ctdef); int generate_del_rtdef_for_update(const ObTableUpdCtDef &upd_ctdef, ObTableUpdRtDef &upd_rtdef); diff --git a/src/observer/table/ob_table_op_wrapper.cpp b/src/observer/table/ob_table_op_wrapper.cpp index 35cc3c55fc..ac5c88e812 100644 --- a/src/observer/table/ob_table_op_wrapper.cpp +++ b/src/observer/table/ob_table_op_wrapper.cpp @@ -81,47 +81,49 @@ int ObTableOpWrapper::process_affected_entity(ObTableCtx &tb_ctx, } else if (OB_FAIL(op_result.get_entity(result_entity))) { LOG_WARN("fail to get result entity", K(ret), K(result_entity)); } else { - ObIAllocator &allocator = tb_ctx.get_allocator(); - const ObIArray *full_assign_exprs = nullptr; const ObIArray *ins_exprs = nullptr; + const ObIArray *upd_exprs = nullptr; bool use_insert_expr = false; if (TABLE_API_EXEC_INSERT_UP == spec.get_type()) { const ObTableApiInsertUpSpec &ins_up_spec = static_cast(spec); - full_assign_exprs = &ins_up_spec.get_ctdef().upd_ctdef_.full_assign_row_; ins_exprs = &ins_up_spec.get_ctdef().ins_ctdef_.new_row_; + upd_exprs = &ins_up_spec.get_ctdef().upd_ctdef_.new_row_; use_insert_expr = !static_cast(executor).is_insert_duplicated(); } else { ObTableApiTTLExecutor &ttl_executor = static_cast(executor); const ObTableApiTTLSpec &ttl_spec = static_cast(spec); - full_assign_exprs = &ttl_spec.get_ctdef().upd_ctdef_.full_assign_row_; ins_exprs = &ttl_spec.get_ctdef().ins_ctdef_.new_row_; + upd_exprs = &ttl_spec.get_ctdef().upd_ctdef_.new_row_; use_insert_expr = !ttl_executor.is_insert_duplicated() || ttl_executor.is_expired(); } - const ObTableCtx::ObAssignIds &assign_ids = tb_ctx.get_assign_ids(); - const int64_t N = assign_ids.count(); - ObObj *obj_array = static_cast(allocator.alloc(sizeof(ObObj) * N)); + + ObIArray &assigns = tb_ctx.get_assignments(); + ObIAllocator &allocator = tb_ctx.get_allocator(); + ObObj *obj_array = static_cast(allocator.alloc(sizeof(ObObj) * assigns.count())); if (OB_ISNULL(obj_array)) { ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("faild to alloc memory for objs", K(ret)); - } else if (OB_ISNULL(full_assign_exprs)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("full assign exprs is null", K(ret)); + LOG_WARN("faild to alloc memory for objs", K(ret), K(assigns.count())); } else if (OB_ISNULL(ins_exprs)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("insert exprs is null", K(ret)); } - for (int64_t i = 0; OB_SUCC(ret) && i < N; i++) { - uint64_t idx = assign_ids.at(i).idx_; - uint64_t column_id = assign_ids.at(i).column_id_; - const ObColumnSchemaV2 *column_schema = nullptr; - if (OB_ISNULL(column_schema = tb_ctx.get_table_schema()->get_column_schema(column_id))) { - ret = OB_ERR_COLUMN_NOT_FOUND; - LOG_WARN("column not exist", K(ret), K(column_id)); + for (int64_t i = 0; OB_SUCC(ret) && i < assigns.count(); i++) { + ObTableAssignment &assign = assigns.at(i); + uint64_t project_idx = OB_INVALID_ID; + if (OB_ISNULL(assign.column_item_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("assign column item is nullptr", K(ret), K(assign)); + } else if (FALSE_IT(project_idx = assign.column_item_->col_idx_)) { + } else if (use_insert_expr && ins_exprs->count() <= project_idx) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected insert index", K(ret), K(ins_exprs), K(assign)); + } else if (!use_insert_expr && upd_exprs->count() <= project_idx) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected assign index", K(ret), K(upd_exprs), K(assign)); } else { ObObj &obj = obj_array[i]; - ObExpr *rt_expr = use_insert_expr ? ins_exprs->at(idx) : full_assign_exprs->at(idx); + ObExpr *rt_expr = use_insert_expr ? ins_exprs->at(project_idx) : upd_exprs->at(project_idx); ObDatum *datum = nullptr; - const ObString &column_name = column_schema->get_column_name_str(); if (OB_FAIL(rt_expr->eval(executor.get_eval_ctx(), datum))) { LOG_WARN("fail to eval datum", K(ret), K(*rt_expr)); } else if (OB_FAIL(datum->to_obj(obj, rt_expr->obj_meta_))) { @@ -129,8 +131,8 @@ int ObTableOpWrapper::process_affected_entity(ObTableCtx &tb_ctx, } else if (is_lob_storage(obj.get_type()) && OB_FAIL(ObTableCtx::read_real_lob(allocator, obj))) { LOG_WARN("fail to read lob", K(ret), K(obj)); - } else if (OB_FAIL(result_entity->set_property(column_name, obj))) { - LOG_WARN("fail to set property", K(ret), K(column_name), K(obj)); + } else if (OB_FAIL(result_entity->set_property(assign.column_item_->column_name_, obj))) { + LOG_WARN("fail to set property", K(ret), K(assign), K(obj)); } } } diff --git a/src/observer/table/ob_table_query_common.cpp b/src/observer/table/ob_table_query_common.cpp index b51e2e2bb7..4137029f86 100644 --- a/src/observer/table/ob_table_query_common.cpp +++ b/src/observer/table/ob_table_query_common.cpp @@ -25,7 +25,7 @@ int ObTableQueryUtils::check_htable_query_args(const ObTableQuery &query, int ret = OB_SUCCESS; const ObIArray &select_columns = tb_ctx.get_query_col_names(); int64_t N = select_columns.count(); - if (N != 4) { + if (N != 4 && N != 5) { // htable maybe has prefix generated column ret = OB_INVALID_ARGUMENT; LOG_WARN("TableQuery with htable_filter should select 4 columns", K(ret), K(N)); } diff --git a/src/observer/table/ob_table_replace_executor.cpp b/src/observer/table/ob_table_replace_executor.cpp index 3d230952ba..5aa29d2132 100644 --- a/src/observer/table/ob_table_replace_executor.cpp +++ b/src/observer/table/ob_table_replace_executor.cpp @@ -208,18 +208,11 @@ int ObTableApiReplaceExecutor::do_insert() const ObTableEntity *entity = static_cast(tb_ctx_.get_entity()); const ObTableReplaceCtDef &ctdef = replace_spec_.get_ctdef(); - if (OB_FAIL(refresh_exprs_frame(entity))) { - LOG_WARN("fail to refresh expr frame", K(ret)); - } else if (tb_ctx_.has_auto_inc()) { - for (int64_t i = 0; i < ctdef.ins_ctdef_.new_row_.count(); i++) { // 在自增的场景下,由于自增列的列引用表达式被用户输入的值覆盖 - if (ctdef.ins_ctdef_.new_row_.at(i)->type_ == T_FUN_COLUMN_CONV) { // 故需要手动清空eval的flag - ctdef.ins_ctdef_.new_row_.at(i)->get_eval_info(eval_ctx_).evaluated_ = false; - } - } - } - - if (OB_FAIL(ret)) { - // do nothing + if (OB_ISNULL(insert_row_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("insert row is null", K(ret)); + } else if (OB_FAIL(insert_row_->to_expr(get_primary_table_new_row(), eval_ctx_))) { + LOG_WARN("stored row to expr faild", K(ret)); } else if (OB_FAIL(insert_row_to_das(ctdef.ins_ctdef_, replace_rtdef_.ins_rtdef_))) { LOG_WARN("shuffle insert row failed", K(ret)); } else { @@ -229,6 +222,21 @@ int ObTableApiReplaceExecutor::do_insert() return ret; } +int ObTableApiReplaceExecutor::cache_insert_row() +{ + int ret = OB_SUCCESS; + const ObExprPtrIArray &new_row_exprs = get_primary_table_new_row(); + + if (OB_FAIL(ObChunkDatumStore::StoredRow::build(insert_row_, new_row_exprs, eval_ctx_, allocator_))) { + LOG_WARN("fail to build stored row", K(ret), K(new_row_exprs)); + } else if (OB_ISNULL(insert_row_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("cache insert row is null", K(ret)); + } + + return ret; +} + int ObTableApiReplaceExecutor::prepare_final_replace_task() { int ret = OB_SUCCESS; @@ -278,6 +286,8 @@ int ObTableApiReplaceExecutor::get_next_row() LOG_WARN("fail to post all das task", K(ret)); } else if (!is_duplicated()) { LOG_DEBUG("try insert is not duplicated", K(ret)); + } else if (OB_FAIL(cache_insert_row())) { + LOG_WARN("fail to cache insert row", K(ret)); } else if (OB_FAIL(fetch_conflict_rowkey(conflict_checker_))) { LOG_WARN("fail to fetch conflict row", K(ret)); } else if (OB_FAIL(reset_das_env(replace_rtdef_.ins_rtdef_))) { diff --git a/src/observer/table/ob_table_replace_executor.h b/src/observer/table/ob_table_replace_executor.h index d3244ac47b..d5140581c4 100644 --- a/src/observer/table/ob_table_replace_executor.h +++ b/src/observer/table/ob_table_replace_executor.h @@ -48,6 +48,7 @@ public: : ObTableApiModifyExecutor(ctx), allocator_(ObModIds::TABLE_PROC, OB_MALLOC_NORMAL_BLOCK_SIZE, MTL_ID()), replace_spec_(replace_spec), + insert_row_(NULL), insert_rows_(0), delete_rows_(0), conflict_checker_(allocator_, eval_ctx_, replace_spec_.get_conflict_checker_ctdef()), @@ -93,6 +94,7 @@ private: const ObChunkDatumStore::StoredRow *replace_row, const ObChunkDatumStore::StoredRow *delete_row); int prepare_final_replace_task(); + int cache_insert_row(); int do_delete(ObConflictRowMap *primary_map); int do_insert(); int reuse(); @@ -100,6 +102,7 @@ private: common::ObArenaAllocator allocator_; const ObTableApiReplaceSpec &replace_spec_; ObTableReplaceRtDef replace_rtdef_; + ObChunkDatumStore::StoredRow *insert_row_; int64_t insert_rows_; int64_t delete_rows_; sql::ObConflictChecker conflict_checker_; diff --git a/src/observer/table/ob_table_update_executor.cpp b/src/observer/table/ob_table_update_executor.cpp index fff876ed46..a2dadb59b7 100644 --- a/src/observer/table/ob_table_update_executor.cpp +++ b/src/observer/table/ob_table_update_executor.cpp @@ -21,8 +21,7 @@ namespace oceanbase { namespace table { -int ObTableApiUpdateExecutor::process_single_operation(const ObTableEntity *entity, - const ObTableCtx::ObAssignIds &assign_ids) +int ObTableApiUpdateExecutor::process_single_operation(const ObTableEntity *entity) { int ret = OB_SUCCESS; common::ObIArray &key_ranges = tb_ctx_.get_key_ranges(); @@ -49,10 +48,7 @@ int ObTableApiUpdateExecutor::process_single_operation(const ObTableEntity *enti LOG_WARN("fail to get next row", K(ret)); } } else if (OB_FAIL(ObTableExprCgService::refresh_update_exprs_frame(tb_ctx_, - upd_ctdef->old_row_, upd_ctdef->new_row_, - upd_ctdef->full_assign_row_, - assign_ids, *entity))) { LOG_WARN("fail to refresh update exprs frame", K(ret), K(*entity), K(cur_idx_)); } @@ -69,7 +65,7 @@ int ObTableApiUpdateExecutor::get_next_row_from_child() if (cur_idx_ >= 1) { ret = OB_ITER_END; - } else if (OB_FAIL(process_single_operation(entity, tb_ctx_.get_assign_ids()))) { + } else if (OB_FAIL(process_single_operation(entity))) { if (OB_ITER_END != ret) { LOG_WARN("fail to process single update operation", K(ret)); } diff --git a/src/observer/table/ob_table_update_executor.h b/src/observer/table/ob_table_update_executor.h index 47a0784b4b..862b3389b1 100644 --- a/src/observer/table/ob_table_update_executor.h +++ b/src/observer/table/ob_table_update_executor.h @@ -53,8 +53,7 @@ private: int get_next_row_from_child(); int update_row_to_das(); int upd_rows_post_proc(); - int process_single_operation(const ObTableEntity *entity, - const ObTableCtx::ObAssignIds &assign_ids); + int process_single_operation(const ObTableEntity *entity); private: const ObTableApiUpdateSpec &upd_spec_; ObTableUpdRtDef upd_rtdef_; diff --git a/src/observer/table/ttl/ob_table_ttl_executor.cpp b/src/observer/table/ttl/ob_table_ttl_executor.cpp index 5aeb9f2766..7bdc697f09 100644 --- a/src/observer/table/ttl/ob_table_ttl_executor.cpp +++ b/src/observer/table/ttl/ob_table_ttl_executor.cpp @@ -93,7 +93,7 @@ int ObTableApiTTLExecutor::refresh_exprs_frame(const ObTableEntity *entity) LOG_WARN("entity is null", K(ret)); } else if (OB_FAIL(ObTableExprCgService::refresh_ttl_exprs_frame(tb_ctx_, ins_ctdef.new_row_, - upd_ctdef.delta_exprs_, + upd_ctdef.delta_row_, *entity))) { LOG_WARN("fail to refresh ttl exprs frame", K(ret), K(*entity)); } @@ -277,7 +277,6 @@ int ObTableApiTTLExecutor::update_row_to_das() ttl_rtdef_.upd_rtdef_, upd_rtctx_)); OZ(to_expr_skip_old(*constraint_value.current_datum_row_, - constraint_rowkey, ttl_spec_.get_ctdef().upd_ctdef_)); clear_evaluated_flag(); OZ(insert_upd_new_row_to_das(ttl_spec_.get_ctdef().upd_ctdef_, @@ -286,7 +285,6 @@ int ObTableApiTTLExecutor::update_row_to_das() } else if (NULL == constraint_value.baseline_datum_row_ && NULL != constraint_value.current_datum_row_) { // 单单是唯一索引冲突的时候,会走这个分支 OZ(to_expr_skip_old(*constraint_value.current_datum_row_, - constraint_rowkey, ttl_spec_.get_ctdef().upd_ctdef_)); OZ(insert_upd_new_row_to_das(ttl_spec_.get_ctdef().upd_ctdef_, ttl_rtdef_.upd_rtdef_, diff --git a/unittest/observer/table/test_create_executor.cpp b/unittest/observer/table/test_create_executor.cpp index 2594815c70..cc5686ca03 100644 --- a/unittest/observer/table/test_create_executor.cpp +++ b/unittest/observer/table/test_create_executor.cpp @@ -166,7 +166,8 @@ void TestCreateExecutor::fake_ctx_init_common(ObTableCtx &fake_ctx, ObTableSchem g_sess_node_val.is_inited_ = true; g_sess_node_val.sess_info_.test_init(0, 0, 0, NULL); g_sess_node_val.sess_info_.load_all_sys_vars(schema_guard_); - fake_ctx.init_phy_plan_ctx(); + fake_ctx.init_physical_plan_ctx(0, 1); + ASSERT_EQ(OB_SUCCESS, fake_ctx.construct_column_items()); } TEST_F(TestCreateExecutor, scan) @@ -296,7 +297,7 @@ TEST_F(TestCreateExecutor, update) ASSERT_EQ(OB_SUCCESS, ObTableExprCgService::generate_exprs(fake_ctx, allocator_, fake_expr_info)); fake_ctx.set_expr_info(&fake_expr_info); - ASSERT_EQ(6, fake_ctx.get_all_exprs().get_expr_array().count()); + ASSERT_EQ(4, fake_ctx.get_all_exprs().get_expr_array().count()); ObTableApiSpec *root_spec = nullptr; ObTableApiExecutor *executor = nullptr; // generate update spec tree @@ -343,7 +344,7 @@ TEST_F(TestCreateExecutor, insertup) ASSERT_EQ(OB_SUCCESS, fake_ctx.init_insert_up()); ASSERT_EQ(OB_SUCCESS, ObTableExprCgService::generate_exprs(fake_ctx, allocator_, fake_expr_info)); fake_ctx.set_expr_info(&fake_expr_info); - ASSERT_EQ(6, fake_ctx.get_all_exprs().get_expr_array().count()); + ASSERT_EQ(4, fake_ctx.get_all_exprs().get_expr_array().count()); ObTableApiSpec *root_spec = nullptr; ObTableApiExecutor *executor = nullptr;