[CP] Fix bug for last_insert_id()
This commit is contained in:
parent
435d6eb508
commit
90c2c33118
@ -62,15 +62,16 @@ int ObExprLastInsertID::eval_last_insert_id(
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObPhysicalPlanCtx *plan_ctx = ctx.exec_ctx_.get_physical_plan_ctx();
|
||||
ObSQLSessionInfo *session = ctx.exec_ctx_.get_my_session();
|
||||
ObDatum *arg = NULL;
|
||||
if (NULL == plan_ctx) {
|
||||
if (NULL == plan_ctx || NULL == session) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("phy plan context is NULL", K(ret));
|
||||
LOG_WARN("phy plan context or session is NULL", K(ret), K(plan_ctx), K(session));
|
||||
} else if (OB_FAIL(expr.eval_param_value(ctx, arg))) {
|
||||
LOG_WARN("evaluate parameter failed", K(ret));
|
||||
} else {
|
||||
if (0 == expr.arg_cnt_) {
|
||||
expr_datum.set_uint(plan_ctx->get_last_insert_id_session());
|
||||
expr_datum.set_uint(session->get_local_last_insert_id());
|
||||
} else if (1 == expr.arg_cnt_) {
|
||||
plan_ctx->set_last_insert_id_with_expr(true);
|
||||
plan_ctx->set_last_insert_id_changed(true);
|
||||
|
@ -745,7 +745,7 @@ int ObRawExpr::is_const_inherit_expr(bool &is_const_inherit,
|
||||
|| T_FUN_NORMAL_UDF == type_
|
||||
|| T_FUN_SYS_REMOVE_CONST == type_
|
||||
|| T_FUN_SYS_WRAPPER_INNER == type_
|
||||
|| T_FUN_SYS_LAST_INSERT_ID == type_
|
||||
|| (T_FUN_SYS_LAST_INSERT_ID == type_ && get_param_count() > 0)
|
||||
|| T_FUN_SYS_TO_BLOB == type_
|
||||
|| (T_FUN_SYS_SYSDATE == type_ && lib::is_mysql_mode())
|
||||
|| (param_need_replace ? is_not_calculable_expr() : cnt_not_calculable_expr())
|
||||
|
@ -470,7 +470,7 @@ int ObRawExprInfoExtractor::visit(ObSysFunRawExpr &expr)
|
||||
if (T_FUN_SYS_AUTOINC_NEXTVAL == expr.get_expr_type()
|
||||
|| T_FUN_SYS_TABLET_AUTOINC_NEXTVAL == expr.get_expr_type()
|
||||
|| T_FUN_SYS_SLEEP == expr.get_expr_type()
|
||||
|| T_FUN_SYS_LAST_INSERT_ID == expr.get_expr_type()
|
||||
|| (T_FUN_SYS_LAST_INSERT_ID == expr.get_expr_type() && expr.get_param_count() > 0)
|
||||
|| T_FUN_SYS_PART_ID == expr.get_expr_type()
|
||||
|| T_OP_GET_PACKAGE_VAR == expr.get_expr_type()
|
||||
|| T_OP_GET_SUBPROGRAM_VAR == expr.get_expr_type()
|
||||
|
@ -265,48 +265,17 @@ int ObPredicateDeduce::check_index_part_cond(ObTransformerCtx &ctx,
|
||||
int ret = OB_SUCCESS;
|
||||
is_valid = false;
|
||||
ObRawExpr *check_expr = NULL;
|
||||
ObSQLSessionInfo *session_info = ctx.session_info_;
|
||||
if (OB_ISNULL(left_expr) || OB_ISNULL(right_expr)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("invalid index", K(ret), K(left_expr), K(right_expr));
|
||||
} else if (OB_ISNULL(session_info)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("session_info is null", K(ret));
|
||||
}else if (left_expr->is_column_ref_expr() && right_expr->is_const_expr()) {
|
||||
} else if (left_expr->is_column_ref_expr() && right_expr->is_const_expr()) {
|
||||
check_expr = left_expr;
|
||||
} else if (right_expr->is_column_ref_expr() && left_expr->is_const_expr()) {
|
||||
check_expr = right_expr;
|
||||
}
|
||||
if (OB_SUCC(ret) && NULL != check_expr) {
|
||||
ObColumnRefRawExpr *col = static_cast<ObColumnRefRawExpr *>(check_expr);
|
||||
const share::schema::ObColumnSchemaV2 *column_schema = NULL;
|
||||
TableItem *table = stmt_.get_table_item_by_id(col->get_table_id());
|
||||
if (OB_ISNULL(table)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("table is null", K(ret), K(*col));
|
||||
} else if (!table->is_basic_table()) {
|
||||
|
||||
} else if (OB_FAIL(ctx.schema_checker_->get_column_schema(session_info->get_effective_tenant_id(),
|
||||
table->ref_id_,
|
||||
col->get_column_id(),
|
||||
column_schema,
|
||||
true))) {
|
||||
LOG_WARN("failed to get column schema", K(ret), K(table->ref_id_), K(col->get_column_id()), K(col->get_table_id()), K(table), K(col), K(lbt()));
|
||||
} else if (OB_ISNULL(column_schema)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("column schema is null", K(ret));
|
||||
} else if (column_schema->is_rowkey_column()) {
|
||||
is_valid = true;
|
||||
} else if (OB_FAIL(ctx.schema_checker_->check_column_has_index(column_schema->get_tenant_id(),
|
||||
table->ref_id_,
|
||||
col->get_column_id(),
|
||||
is_valid))) {
|
||||
LOG_WARN("failed to check column is a key", K(ret));
|
||||
} else if (is_valid) {
|
||||
// do nothing
|
||||
} else if (ctx.schema_checker_->check_if_partition_key(session_info->get_effective_tenant_id(),
|
||||
table->ref_id_, col->get_column_id(), is_valid)) {
|
||||
LOG_WARN("failed to check if partition key", K(ret));
|
||||
if (OB_FAIL(ObTransformUtils::check_is_index_part_key(ctx, stmt_, check_expr, is_valid))) {
|
||||
LOG_WARN("fail to check if check_expr is index or part key", K(ret));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
|
@ -238,6 +238,14 @@ int ObTransformPreProcess::transform_one_stmt(common::ObIArray<ObParentDMLStmt>
|
||||
LOG_TRACE("succeed to transform rollup exprs", K(is_happened));
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
if (OB_FAIL(transform_for_last_insert_id(stmt, is_happened))) {
|
||||
LOG_WARN("failed to transform for last_insert_id.", K(ret));
|
||||
} else {
|
||||
trans_happened |= is_happened;
|
||||
LOG_TRACE("succeed to transform for last_insert_id.",K(is_happened), K(ret));
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
LOG_DEBUG("transform pre process succ", K(*stmt));
|
||||
if (OB_FAIL(stmt->formalize_stmt(ctx_->session_info_))) {
|
||||
@ -9206,5 +9214,201 @@ int ObTransformPreProcess::check_pre_aggregate(const ObSelectStmt &select_stmt,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObTransformPreProcess::transform_for_last_insert_id(ObDMLStmt *stmt, bool &trans_happened) {
|
||||
int ret = OB_SUCCESS;
|
||||
trans_happened = false;
|
||||
if (OB_ISNULL(stmt)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected null", K(ret), K(stmt));
|
||||
} else if (stmt->is_select_stmt()) {
|
||||
ObSelectStmt *sel_stmt = static_cast<ObSelectStmt*>(stmt);
|
||||
bool is_happened = false;
|
||||
if (OB_FAIL(expand_for_last_insert_id(*stmt, sel_stmt->get_having_exprs(), is_happened))) {
|
||||
LOG_WARN("fail to expand having exprs",K(ret));
|
||||
} else {
|
||||
trans_happened |= is_happened;
|
||||
}
|
||||
if (OB_FAIL(ret)) {
|
||||
} else if (OB_FAIL(expand_for_last_insert_id(*stmt, sel_stmt->get_condition_exprs(), is_happened))) {
|
||||
LOG_WARN("fail to expand condition exprs",K(ret));
|
||||
} else {
|
||||
trans_happened |= is_happened;
|
||||
}
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < sel_stmt->get_joined_tables().count(); ++i) {
|
||||
if (OB_FAIL(expand_last_insert_id_for_join(*stmt, sel_stmt->get_joined_tables().at(i), is_happened))) {
|
||||
LOG_WARN("failed to expand join conditions", K(ret));
|
||||
} else {
|
||||
trans_happened |= is_happened;
|
||||
}
|
||||
}
|
||||
} else if (stmt->is_delete_stmt() || stmt->is_update_stmt()) {
|
||||
bool is_happened = false;
|
||||
if (OB_FAIL(expand_for_last_insert_id(*stmt, stmt->get_condition_exprs(), is_happened))) {
|
||||
LOG_WARN("fail to expand having exprs",K(ret));
|
||||
} else {
|
||||
trans_happened |= is_happened;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObTransformPreProcess::expand_last_insert_id_for_join(ObDMLStmt &stmt, JoinedTable *join_table, bool &has_happened) {
|
||||
int ret = OB_SUCCESS;
|
||||
bool is_happened = false;
|
||||
has_happened = false;
|
||||
if (OB_ISNULL(join_table) || OB_ISNULL(join_table->left_table_) || OB_ISNULL(join_table->right_table_)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected null", K(ret), K(join_table));
|
||||
} else if (OB_FAIL(expand_for_last_insert_id(stmt, join_table->join_conditions_, has_happened))) {
|
||||
LOG_WARN("failed to expand join conditions", K(ret));
|
||||
} else if (join_table->left_table_->is_joined_table() &&
|
||||
OB_FAIL(expand_last_insert_id_for_join(stmt, static_cast<JoinedTable*>(join_table->left_table_), is_happened))) {
|
||||
LOG_WARN("fail to expand last_insert_id in left join table", K(ret));
|
||||
} else if (FALSE_IT(has_happened |= is_happened)) {
|
||||
} else if (join_table->right_table_->is_joined_table() &&
|
||||
OB_FAIL(expand_last_insert_id_for_join(stmt, static_cast<JoinedTable*>(join_table->right_table_), is_happened))) {
|
||||
LOG_WARN("fail to expand last_insert_id in right join table", K(ret));
|
||||
} else {
|
||||
has_happened |= is_happened;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObTransformPreProcess::expand_for_last_insert_id(ObDMLStmt &stmt, ObIArray<ObRawExpr*> &exprs, bool &is_happended) {
|
||||
int ret = OB_SUCCESS;
|
||||
ObSEArray<ObRawExpr *, 4> new_exprs;
|
||||
is_happended = false;
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < exprs.count(); ++i) {
|
||||
ObRawExpr *expr = exprs.at(i);
|
||||
if (OB_ISNULL(expr)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected null", K(ret), K(expr), K(i));
|
||||
} else if (expr->has_flag(CNT_LAST_INSERT_ID) &&
|
||||
(IS_RANGE_CMP_OP(expr->get_expr_type()) || T_OP_EQ == expr->get_expr_type()) &&
|
||||
!expr->has_flag(CNT_RAND_FUNC) &&
|
||||
!expr->has_flag(CNT_SUB_QUERY) &&
|
||||
!expr->has_flag(CNT_ROWNUM) &&
|
||||
!expr->has_flag(CNT_SEQ_EXPR) &&
|
||||
!expr->has_flag(CNT_USER_VARIABLE)) {
|
||||
bool removable = false;
|
||||
ObRawExpr *left = expr->get_param_expr(0);
|
||||
ObRawExpr *right = expr->get_param_expr(1);
|
||||
ObRawExpr *check_expr = NULL;
|
||||
if (OB_ISNULL(left) || OB_ISNULL(right)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected null", K(ret), K(left), K(right));
|
||||
} else if (left->has_flag(CNT_LAST_INSERT_ID) && !left->has_flag(CNT_COLUMN) && right->has_flag(CNT_COLUMN)) {
|
||||
check_expr = right;
|
||||
} else if (right->has_flag(CNT_LAST_INSERT_ID) && !right->has_flag(CNT_COLUMN) && left->has_flag(CNT_COLUMN)) {
|
||||
check_expr = left;
|
||||
}
|
||||
if (OB_FAIL(ret) || NULL == check_expr) {
|
||||
//do nothing
|
||||
} else if (OB_FAIL(ObTransformUtils::check_is_index_part_key(*ctx_, stmt, check_expr, removable))) {
|
||||
LOG_WARN("fail to check if it's a index/part condition", K(ret));
|
||||
} else if (!removable) {
|
||||
//do nothing if the param which does not contain last_insert_id is not a index key with lossless cast or a index key.
|
||||
} else if (OB_FAIL(check_last_insert_id_removable(expr, removable))) {
|
||||
LOG_WARN("fail to check whether last_insert_id can be removed", K(ret));
|
||||
} else if (removable) {
|
||||
ObRawExpr *param_expr = check_expr == left ? right : left;
|
||||
ObRawExpr *new_expr = NULL;
|
||||
if (OB_FAIL(ObRawExprCopier::copy_expr(
|
||||
*ctx_->expr_factory_,
|
||||
param_expr,
|
||||
param_expr))) {
|
||||
LOG_WARN("failed to copy expr", K(ret));
|
||||
} else if (OB_ISNULL(param_expr)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("new param is invalid", K(ret));
|
||||
} else if (OB_FAIL(remove_last_insert_id(param_expr))) {
|
||||
LOG_WARN("failed to remove last insert id exprs", K(ret));
|
||||
} else if (OB_FAIL(param_expr->formalize(ctx_->session_info_))) {
|
||||
LOG_WARN("failed to formalize expr", K(ret));
|
||||
} else if (!param_expr->is_const_expr()) {
|
||||
//do nothing
|
||||
} else if (OB_FAIL(ObRawExprCopier::copy_expr_node(*ctx_->expr_factory_,
|
||||
expr,
|
||||
new_expr))) {
|
||||
LOG_WARN("failed to copy expr", K(ret));
|
||||
} else if (OB_ISNULL(new_expr)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("failed to build new expr", K(ret));
|
||||
} else if (new_expr->get_param_expr(0) == check_expr) {
|
||||
new_expr->get_param_expr(1) = param_expr;
|
||||
} else {
|
||||
new_expr->get_param_expr(0) = param_expr;
|
||||
}
|
||||
if (OB_SUCC(ret) && NULL != new_expr) {
|
||||
if (OB_FAIL(new_expr->formalize(ctx_->session_info_))) {
|
||||
LOG_WARN("failed to formalize expr", K(ret));
|
||||
} else if (OB_FAIL(exprs.push_back(new_expr))) {
|
||||
LOG_WARN("failed to push back new pred", K(ret));
|
||||
} else {
|
||||
is_happended = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObTransformPreProcess::check_last_insert_id_removable(const ObRawExpr *expr, bool &is_removable) {
|
||||
int ret = OB_SUCCESS;
|
||||
is_removable = true;
|
||||
if (OB_ISNULL(expr)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected null", K(ret), K(expr));
|
||||
} else if (expr->has_flag(IS_LAST_INSERT_ID)) {
|
||||
if (1 != expr->get_param_count()) {
|
||||
is_removable = false;
|
||||
} else {
|
||||
const ObRawExpr *param = expr->get_param_expr(0);
|
||||
if (OB_ISNULL(param)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected null", K(ret), K(param));
|
||||
} else if (!param->has_flag(IS_CONST) && !param->has_flag(IS_CONST_EXPR)) {
|
||||
is_removable = false;
|
||||
}
|
||||
}
|
||||
} else if (expr->has_flag(CNT_LAST_INSERT_ID)) {
|
||||
bool flag = true;
|
||||
for (int64_t i = 0; OB_SUCC(ret) && is_removable && i < expr->get_param_count(); ++i) {
|
||||
if (OB_FAIL(check_last_insert_id_removable(expr->get_param_expr(i), flag))) {
|
||||
LOG_WARN("fail to check whether last insert id expr is removable", K(ret));
|
||||
} else {
|
||||
is_removable = is_removable & flag;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObTransformPreProcess::remove_last_insert_id(ObRawExpr *&expr) {
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_ISNULL(expr)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected null", K(ret));
|
||||
} else if (expr->has_flag(IS_LAST_INSERT_ID)) {
|
||||
if (1 == expr->get_param_count()) {
|
||||
ObRawExpr *new_expr = expr->get_param_expr(0);
|
||||
if (OB_ISNULL(new_expr)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected null", K(ret), K(new_expr));
|
||||
} else if (new_expr->has_flag(IS_CONST) || new_expr->has_flag(IS_CONST_EXPR)) {
|
||||
expr = new_expr;
|
||||
}
|
||||
}
|
||||
} else if (expr->has_flag(CNT_LAST_INSERT_ID)) {
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < expr->get_param_count(); ++i) {
|
||||
if (OB_FAIL(remove_last_insert_id(expr->get_param_expr(i)))) {
|
||||
LOG_WARN("fail to check whether last insert id expr is removable", K(ret));
|
||||
}
|
||||
}
|
||||
} else {}
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // end namespace sql
|
||||
} // end namespace oceanbase
|
||||
|
@ -594,6 +594,12 @@ struct DistinctObjMeta
|
||||
int add_column_conv_to_multiset(ObQueryRefRawExpr *multiset_expr,
|
||||
const pl::ObPLDataType &elem_type,
|
||||
bool& trans_happened);
|
||||
|
||||
int transform_for_last_insert_id(ObDMLStmt *stmt, bool &trans_happened);
|
||||
int expand_for_last_insert_id(ObDMLStmt &stmt, ObIArray<ObRawExpr*> &exprs, bool &is_happended);
|
||||
int expand_last_insert_id_for_join(ObDMLStmt &stmt, JoinedTable *join_table, bool &is_happened);
|
||||
int remove_last_insert_id(ObRawExpr *&expr);
|
||||
int check_last_insert_id_removable(const ObRawExpr *expr, bool &is_removable);
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(ObTransformPreProcess);
|
||||
};
|
||||
|
@ -13211,5 +13211,58 @@ int ObTransformUtils::create_udt_hidden_columns(ObTransformerCtx *ctx,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObTransformUtils::check_is_index_part_key(ObTransformerCtx &ctx,
|
||||
ObDMLStmt &stmt,
|
||||
ObRawExpr *check_expr,
|
||||
bool &is_valid)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
is_valid = false;
|
||||
ObSQLSessionInfo *session_info = ctx.session_info_;
|
||||
if (OB_ISNULL(check_expr)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("invalid index", K(ret), K(check_expr));
|
||||
} else if (OB_ISNULL(session_info)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("session_info is null", K(ret));
|
||||
} else if (OB_FAIL(ObOptimizerUtil::get_expr_without_lossless_cast(check_expr, check_expr))) {
|
||||
LOG_WARN("failed to get expr without lossless cast", K(ret));
|
||||
} else if (!check_expr->is_column_ref_expr()) {
|
||||
// do nothing
|
||||
} else {
|
||||
ObColumnRefRawExpr *col = static_cast<ObColumnRefRawExpr *>(check_expr);
|
||||
const share::schema::ObColumnSchemaV2 *column_schema = NULL;
|
||||
TableItem *table = stmt.get_table_item_by_id(col->get_table_id());
|
||||
if (OB_ISNULL(table)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("table is null", K(ret), K(*col));
|
||||
} else if (!table->is_basic_table()) {
|
||||
|
||||
} else if (OB_FAIL(ctx.schema_checker_->get_column_schema(session_info->get_effective_tenant_id(),
|
||||
table->ref_id_,
|
||||
col->get_column_id(),
|
||||
column_schema,
|
||||
true))) {
|
||||
LOG_WARN("failed to get column schema", K(ret), K(table->ref_id_), K(col->get_column_id()), K(col->get_table_id()), K(table), K(col), K(lbt()));
|
||||
} else if (OB_ISNULL(column_schema)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("column schema is null", K(ret));
|
||||
} else if (column_schema->is_rowkey_column()) {
|
||||
is_valid = true;
|
||||
} else if (OB_FAIL(ctx.schema_checker_->check_column_has_index(column_schema->get_tenant_id(),
|
||||
table->ref_id_,
|
||||
col->get_column_id(),
|
||||
is_valid))) {
|
||||
LOG_WARN("failed to check column is a key", K(ret));
|
||||
} else if (is_valid) {
|
||||
// do nothing
|
||||
} else if (ctx.schema_checker_->check_if_partition_key(session_info->get_effective_tenant_id(),
|
||||
table->ref_id_, col->get_column_id(), is_valid)) {
|
||||
LOG_WARN("failed to check if partition key", K(ret));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace sql
|
||||
} // namespace oceanbase
|
||||
|
@ -1772,6 +1772,7 @@ public:
|
||||
static int extract_shared_exprs(ObDMLStmt *parent,
|
||||
ObIArray<ObRawExpr *> &relation_exprs,
|
||||
ObIArray<ObRawExpr *> &common_exprs);
|
||||
static int check_is_index_part_key(ObTransformerCtx &ctx, ObDMLStmt &stmt, ObRawExpr *check_expr, bool &is_valid);
|
||||
private:
|
||||
static int inner_get_lazy_left_join(ObDMLStmt *stmt,
|
||||
TableItem *table,
|
||||
|
@ -4569,7 +4569,7 @@ last_insert_id()
|
||||
1
|
||||
select bug15728()|
|
||||
bug15728()
|
||||
0
|
||||
1
|
||||
drop function bug15728|
|
||||
drop table t3|
|
||||
drop procedure if exists bug18787|
|
||||
|
Loading…
x
Reference in New Issue
Block a user