[CP] Fix bug for last_insert_id()
This commit is contained in:
@ -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
|
||||
|
||||
Reference in New Issue
Block a user