[to #53767952]fix bug trigger not use das

This commit is contained in:
seuwebber 2024-02-07 20:43:16 +00:00 committed by ob-robot
parent c5aec9185b
commit 028d69f378
7 changed files with 91 additions and 78 deletions

View File

@ -895,16 +895,11 @@ int ObDelUpdResolver::set_base_table_for_updatable_view(TableItem &table_item,
}
} else if (new_table_item->is_generated_table() || new_table_item->is_temp_table()) {
const bool inner_log_error = false;
if (new_table_item->is_view_table_ && is_oracle_mode()
&& stmt_->is_support_instead_of_trigger_stmt()) {
bool has_tg = false;
OZ (has_need_fired_trigger_on_view(new_table_item, has_tg));
OX ((static_cast<ObDelUpdStmt*>(stmt_))
->set_has_instead_of_trigger(has_tg));
}
if (OB_FAIL(SMART_CALL(set_base_table_for_updatable_view(*new_table_item,
*new_col_ref,
inner_log_error)))) {
if (OB_FAIL(check_need_fired_trigger(new_table_item))) {
LOG_WARN("check has need fired trigger failed", K(ret));
} else if (OB_FAIL(SMART_CALL(set_base_table_for_updatable_view(*new_table_item,
*new_col_ref,
inner_log_error)))) {
LOG_WARN("find base table for updatable view failed", K(ret));
}
} else if (new_table_item->is_fake_cte_table()) {
@ -2146,63 +2141,86 @@ int ObDelUpdResolver::uv_check_key_preserved(const TableItem &table_item, bool &
return ret;
}
//检查user_view上是否有对应dml事件触发且状态为enabled的instead of trigger
int ObDelUpdResolver::has_need_fired_trigger_on_view(const TableItem* view_item, bool &has)
int ObDelUpdResolver::check_need_fired_trigger(const TableItem* table_item)
{
int ret = OB_SUCCESS;
has = false;
const ObTableSchema *view_schema = NULL;
bool has = false;
const ObTableSchema *table_schema = NULL;
ObSchemaGetterGuard *schema_guard = NULL;
uint64_t view_id = OB_INVALID_ID;
CK (OB_NOT_NULL(view_item));
CK (OB_NOT_NULL(schema_checker_));
CK (OB_NOT_NULL(schema_guard = schema_checker_->get_schema_guard()));
OX (view_id = view_item->ref_id_);
if (OB_SUCC(ret) && !view_item->alias_name_.empty()) {
uint64_t tenant_id = session_info_->get_effective_tenant_id();
uint64_t table_id = OB_INVALID_ID;
CK (OB_NOT_NULL(table_item));
if (OB_SUCC(ret)
&& !session_info_->get_ddl_info().is_ddl()
&& !table_item->is_index_table_
&& (table_item->is_basic_table() || table_item->is_view_table_)) {
CK (OB_NOT_NULL(schema_checker_));
CK (OB_NOT_NULL(schema_guard = schema_checker_->get_schema_guard()))
OZ (schema_guard->get_table_id(tenant_id, view_item->database_name_,
view_item->table_name_, false /*is_index*/,
ObSchemaGetterGuard::ALL_NON_HIDDEN_TYPES, view_id));
}
OZ (schema_checker_->get_table_schema(session_info_->get_effective_tenant_id(), view_id, view_schema), view_id);
CK (OB_NOT_NULL(view_schema));
if (OB_SUCC(ret) && view_schema->is_user_view()) {
const uint64_t tenant_id = view_schema->get_tenant_id();
const ObIArray<uint64_t> &tg_list = view_schema->get_trigger_list();
const ObTriggerInfo *tg_info = NULL;
uint64_t tg_id = OB_INVALID_ID;
uint64_t dml_event = 0;
switch (stmt_->get_stmt_type())
{
case stmt::T_INSERT:
dml_event = ObTriggerEvents::get_insert_event();
break;
case stmt::T_UPDATE:
dml_event = ObTriggerEvents::get_update_event();
break;
case stmt::T_DELETE:
dml_event = ObTriggerEvents::get_delete_event();
break;
default:
ret = OB_ERR_UNEXPECTED;
LOG_WARN("stmt type is error", K(stmt_->get_stmt_type()), K(ret));
break;
CK (OB_NOT_NULL(schema_guard = schema_checker_->get_schema_guard()));
OX (table_id = table_item->ref_id_);
if (OB_SUCC(ret)) {
if (stmt::T_INSERT == stmt_->get_stmt_type() || stmt::T_INSERT_ALL == stmt_->get_stmt_type()) {
table_id = (!OB_ISNULL(table_item->ref_query_) && table_item->ref_query_->is_view_stmt())
? table_item->ref_query_->get_view_ref_id()
: table_item->get_base_table_item().ref_id_;
} else if (!table_item->alias_name_.empty() && table_item->is_view_table_) {
uint64_t tenant_id = session_info_->get_effective_tenant_id();
CK (OB_NOT_NULL(schema_checker_));
CK (OB_NOT_NULL(schema_guard = schema_checker_->get_schema_guard()))
OZ (schema_guard->get_table_id(tenant_id, table_item->database_name_,
table_item->table_name_, false /*is_index*/,
ObSchemaGetterGuard::ALL_NON_HIDDEN_TYPES, table_id));
}
}
for (int64_t i = 0; OB_SUCC(ret) && !has && i < tg_list.count(); i++) {
OX (tg_id = tg_list.at(i));
OZ (schema_guard->get_trigger_info(tenant_id, tg_id, tg_info));
OV (OB_NOT_NULL(tg_info));
OX (has = (tg_info->is_enable() && tg_info->has_event(dml_event)));
}
if (OB_SUCC(ret) && has) {
CK (stmt_->is_support_instead_of_trigger_stmt());
if (OB_SUCC(ret)) {
ObDelUpdStmt *del_upd_stmt = static_cast<ObDelUpdStmt *>(stmt_);
if (del_upd_stmt->is_returning()) {
ret = OB_ERR_RETURNING_CLAUSE;
LOG_WARN("RETURNING clause is currently not supported for INSTEAD OF Triggers", K(ret));
OZ (schema_checker_->get_table_schema(session_info_->get_effective_tenant_id(), table_id, table_schema), table_id);
CK (OB_NOT_NULL(table_schema));
if (OB_SUCC(ret)) {
const uint64_t tenant_id = table_schema->get_tenant_id();
const ObIArray<uint64_t> &tg_list = table_schema->get_trigger_list();
const ObTriggerInfo *tg_info = NULL;
uint64_t tg_id = OB_INVALID_ID;
uint64_t dml_event = 0;
switch (stmt_->get_stmt_type())
{
case stmt::T_INSERT:
case stmt::T_INSERT_ALL:
dml_event = ObTriggerEvents::get_insert_event();
break;
case stmt::T_UPDATE:
dml_event = ObTriggerEvents::get_update_event();
break;
case stmt::T_DELETE:
dml_event = ObTriggerEvents::get_delete_event();
break;
case stmt::T_MERGE:
dml_event = ObTriggerEvents::get_all_event();
break;
case stmt::T_REPLACE:
dml_event = ObTriggerEvents::get_insert_event() + ObTriggerEvents::get_update_event();
break;
default:
ret = OB_ERR_UNEXPECTED;
LOG_WARN("stmt type is error", K(stmt_->get_stmt_type()), K(ret));
break;
}
for (int64_t i = 0; OB_SUCC(ret) && !has && i < tg_list.count(); i++) {
OX (tg_id = tg_list.at(i));
OZ (schema_guard->get_trigger_info(tenant_id, tg_id, tg_info));
OV (OB_NOT_NULL(tg_info));
OX (has = (tg_info->is_enable() && tg_info->has_event(dml_event)));
}
OX (stmt_->get_query_ctx()->disable_udf_parallel_ |= has);
if (OB_SUCC(ret) && has && table_schema->is_user_view()) {
if (!stmt_->is_support_instead_of_trigger_stmt()) {
ret = OB_NOT_SUPPORTED;
LOG_WARN("only insert/update/delete stmt support instead of trigger", K(ret), K(stmt_->get_stmt_type()));
LOG_USER_ERROR(OB_NOT_SUPPORTED, "except for insert/update/delete statement, instead of trigger is");
} else {
ObDelUpdStmt *del_upd_stmt = static_cast<ObDelUpdStmt *>(stmt_);
if (del_upd_stmt->is_returning()) {
ret = OB_ERR_RETURNING_CLAUSE;
LOG_WARN("RETURNING clause is currently not supported for INSTEAD OF Triggers", K(ret));
} else {
del_upd_stmt->set_has_instead_of_trigger(true);
}
}
}
}

View File

@ -149,7 +149,7 @@ protected:
// check the update view is key preserved
int uv_check_key_preserved(const TableItem &table_item, bool &key_preserved);
int has_need_fired_trigger_on_view(const TableItem* view_item, bool &has);
int check_need_fired_trigger(const TableItem* table_item);
int view_pullup_special_column_exprs();
int view_pullup_part_exprs();

View File

@ -263,10 +263,7 @@ int ObDeleteResolver::resolve_table_list(const ParseNode &table_list, bool &is_m
//single table delete, delete list is same with from list
CK(delete_stmt->get_table_size() == 1);
OZ(delete_tables_.push_back(delete_stmt->get_table_item(0)));
if (OB_SUCC(ret) && delete_stmt->get_table_item(0)->is_view_table_ && is_oracle_mode()) {
OZ(has_need_fired_trigger_on_view(delete_stmt->get_table_item(0), has_tg));
}
OX(delete_stmt->set_has_instead_of_trigger(has_tg));
OZ (check_need_fired_trigger(table_item));
} else {
//multi table delete
is_multi_table_delete = true;
@ -289,6 +286,8 @@ int ObDeleteResolver::resolve_table_list(const ParseNode &table_list, bool &is_m
ret = OB_ERR_NONUNIQ_TABLE;
LOG_USER_ERROR(OB_ERR_NONUNIQ_TABLE, table_item->table_name_.length(),
table_item->table_name_.ptr());
} else if (OB_FAIL(check_need_fired_trigger(table_item))) {
LOG_WARN("failed to check need fired trigger", K(ret));
} else if (OB_FAIL(delete_tables_.push_back(table_item))) {
LOG_WARN("failed to push back table item", K(ret));
}

View File

@ -429,12 +429,7 @@ int ObInsertResolver::resolve_insert_field(const ParseNode &insert_into, TableIt
? table_item->ref_query_->get_view_ref_id()
: table_item->get_base_table_item().ref_id_;
OZ(schema_checker_->get_table_schema(session_info_->get_effective_tenant_id(), ref_id, table_schema, table_item->is_link_table()));
if (OB_SUCC(ret) && table_item->is_view_table_ && is_oracle_mode()) {
bool has_tg = false;
OZ (has_need_fired_trigger_on_view(table_item, has_tg));
OX (insert_stmt->set_has_instead_of_trigger(has_tg));
}
OZ (check_need_fired_trigger(table_item));
if (OB_SUCC(ret)) {
if (table_schema->is_oracle_tmp_table()) {

View File

@ -232,6 +232,8 @@ int ObMergeResolver::resolve_target_relation(const ParseNode *target_node)
LOG_WARN("failed to resolve foreign key constraint", K(ret), K(table_item->ref_id_));
} else if (OB_FAIL(column_namespace_checker_.add_reference_table(table_item))) {
LOG_WARN("add reference table to column namespace checker failed", K(ret));
} else if (OB_FAIL(check_need_fired_trigger(table_item))) {
LOG_WARN("check has need fired trigger failed");
} else if (table_item->is_generated_table()) {
ObSelectStmt *ref_stmt = NULL;
if (OB_ISNULL(ref_stmt = table_item->ref_query_)) {

View File

@ -364,6 +364,8 @@ int ObMultiTableInsertResolver::resolve_insert_table_node(const ParseNode &inser
LOG_WARN("failed to resolve basic table");
} else if (OB_FAIL(resolve_foreign_key_constraint(table_item))) {
LOG_WARN("failed to resolve foreign key constraint", K(ret), K(table_item->ref_id_));
} else if (OB_FAIL(check_need_fired_trigger(table_item))) {
LOG_WARN("failed to check has need fired trigger", K(ret), K(table_item->ref_id_));
} else {
//提前设置好解析参数,对于多表插入会出现相同的表的场景,因此检查时需要提前设置好参数
if (OB_FAIL(generate_insert_all_table_info(*table_item, when_conds_idx, table_info))) {

View File

@ -451,12 +451,9 @@ int ObUpdateResolver::resolve_table_list(const ParseNode &parse_tree)
LOG_WARN("add reference table to namespace checker failed", K(ret));
} else if (OB_FAIL(update_stmt->add_from_item(table_item->table_id_, table_item->is_joined_table()))) {
LOG_WARN("failed to add from item", K(ret));
} else if (check_need_fired_trigger(table_item)) {
LOG_WARN("failed to check need fired trigger", K(ret));
} else {
if (is_oracle_mode() && table_item->is_view_table_) {
bool has_tg = false;
OZ (has_need_fired_trigger_on_view(table_item, has_tg));
OX (update_stmt->set_has_instead_of_trigger(has_tg));
}
/*
In order to share the same logic with 'select' to generate access path costly, we
add the table in the udpate stmt in the from_item list as well.