support truncate fk parent table while foreign_key_checks is off

This commit is contained in:
obdev
2022-11-08 02:06:00 +00:00
committed by wangzelin.wzl
parent 1ae305f255
commit bc9a954129
6 changed files with 36 additions and 18 deletions

View File

@ -12540,14 +12540,21 @@ int ObDDLService::truncate_table_in_trans(const obrpc::ObTruncateTableArg &arg,
for (int64_t i = 0; OB_SUCC(ret) && i < foreign_key_infos.count(); i++) {
ObForeignKeyInfo &foreign_key_info = foreign_key_infos.at(i);
foreign_key_info.foreign_key_id_ = OB_INVALID_ID;
if (OB_FAIL(schema_service->fetch_new_constraint_id(tmp_schema.get_tenant_id(), foreign_key_info.foreign_key_id_))) {
if (OB_FAIL(schema_service->fetch_new_constraint_id(
tmp_schema.get_tenant_id(), foreign_key_info.foreign_key_id_))) {
LOG_WARN("failed to fetch new foreign key id", K(ret), K(tmp_schema.get_tenant_id()));
} else if (foreign_key_info.child_table_id_ == foreign_key_info.parent_table_id_) {
} else if (orig_table_schema.get_table_id() == foreign_key_info.child_table_id_) {
if (foreign_key_info.child_table_id_ == foreign_key_info.parent_table_id_) {
// When it depends on itself, the parent table ID also needs to be updated
foreign_key_info.parent_table_id_ = tmp_schema.get_table_id();
}
if (OB_SUCC(ret)) {
foreign_key_info.child_table_id_ = tmp_schema.get_table_id();
} else if (orig_table_schema.get_table_id() == foreign_key_info.parent_table_id_) {
foreign_key_info.parent_table_id_ = tmp_schema.get_table_id();
} else {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("orig table id is not equal to orig parent_table_id_ or orig child_table_id_ of foreign_key_info ",
K(ret), K(orig_table_schema.get_table_id()), K(foreign_key_info));
}
}
}
@ -15577,7 +15584,7 @@ int ObDDLService::truncate_table(const ObTruncateTableArg &arg,
ret = OB_NOT_SUPPORTED;
LOG_WARN("not support trunate table has materialized view", K(ret));
}
if (OB_SUCC(ret)) {
if (OB_SUCC(ret) && arg.foreign_key_checks_) {
// When truncate table, check whether the table being truncate is the parent table
// of the foreign key constraint
// if it is parent table, not allow truncate

View File

@ -1779,7 +1779,8 @@ OB_SERIALIZE_MEMBER((ObTruncateTableArg, ObDDLArg),
table_name_,
session_id_,
is_add_to_scheduler_,
compat_mode_);
compat_mode_,
foreign_key_checks_);
DEF_TO_STRING(ObTruncateTableArg)
{
@ -1790,7 +1791,8 @@ DEF_TO_STRING(ObTruncateTableArg)
K_(table_name),
K_(session_id),
K_(is_add_to_scheduler),
K_(compat_mode));
K_(compat_mode),
K_(foreign_key_checks));
J_OBJ_END();
return pos;
}

View File

@ -1461,7 +1461,8 @@ public:
database_name_(),
table_name_(),
is_add_to_scheduler_(false),
compat_mode_(lib::Worker::CompatMode::INVALID)
compat_mode_(lib::Worker::CompatMode::INVALID),
foreign_key_checks_(false)
{}
ObTruncateTableArg &operator=(const ObTruncateTableArg &other) = delete;
@ -1475,6 +1476,7 @@ public:
common::ObString table_name_;
bool is_add_to_scheduler_;
lib::Worker::CompatMode compat_mode_;
bool foreign_key_checks_;
};
struct ObRenameTableItem

View File

@ -694,7 +694,7 @@ int ObTableSqlService::drop_table(const ObTableSchema &table_schema,
if (OB_SUCC(ret)) {
// For oracle compatibility, foreign key should be dropped while drop table.
if (OB_FAIL(delete_foreign_key(sql_client, table_schema, new_schema_version))) {
if (OB_FAIL(delete_foreign_key(sql_client, table_schema, new_schema_version, is_truncate_table))) {
LOG_WARN("failed to delete foreign key", K(ret));
}
}
@ -1883,7 +1883,7 @@ int ObTableSqlService::update_table_options(ObISQLClient &sql_client,
|| (OB_DDL_TRUNCATE_DROP_TABLE_TO_RECYCLEBIN == operation_type)) {
// 1. For oracle compatibility, drop foreign key while drop table.
// 2. Foreign key will be rebuilded while truncate table.
if (OB_FAIL(delete_foreign_key(sql_client, new_table_schema, new_table_schema.get_schema_version()))) {
if (OB_FAIL(delete_foreign_key(sql_client, new_table_schema, new_table_schema.get_schema_version(), OB_DDL_TRUNCATE_DROP_TABLE_TO_RECYCLEBIN == operation_type))) {
LOG_WARN("failed to delete foreign key", K(ret));
}
}
@ -4226,7 +4226,9 @@ int ObTableSqlService::delete_from_all_foreign_key_column(ObISQLClient &sql_clie
}
// drop fk child table or drop fk child table into recyclebin will come here
int ObTableSqlService::delete_foreign_key(common::ObISQLClient &sql_client, const ObTableSchema &table_schema, const int64_t new_schema_version)
int ObTableSqlService::delete_foreign_key(
common::ObISQLClient &sql_client, const ObTableSchema &table_schema,
const int64_t new_schema_version, const bool is_truncate_table)
{
int ret = OB_SUCCESS;
const ObIArray<ObForeignKeyInfo> &foreign_key_infos = table_schema.get_foreign_key_infos();
@ -4236,8 +4238,9 @@ int ObTableSqlService::delete_foreign_key(common::ObISQLClient &sql_client, cons
}
for (int64_t i = 0; OB_SUCC(ret) && i < foreign_key_infos.count(); i++) {
const ObForeignKeyInfo &foreign_key_info = foreign_key_infos.at(i);
if (table_schema.get_table_id() == foreign_key_info.child_table_id_
|| table_schema.is_offline_ddl_table()) { // offline ddl table will swap and drop parent table
if (is_truncate_table // truncate table will drop parent table and create it again
|| table_schema.is_offline_ddl_table() // offline ddl table will swap and drop parent table
|| table_schema.get_table_id() == foreign_key_info.child_table_id_) {
uint64_t foreign_key_id = foreign_key_info.foreign_key_id_;
if (OB_FAIL(delete_from_all_foreign_key(sql_client, tenant_id, new_schema_version, foreign_key_info))) {
LOG_WARN("failed to delete __all_foreign_key_history", K(table_schema), K(ret));
@ -4450,8 +4453,8 @@ int ObTableSqlService::add_foreign_key(
} else if (!foreign_key_info.is_parent_table_mock_) {
// If parent table is mock, it may not exist. And we will deal with mock fk parent table after add_foreign_key.
if (OB_FAIL(update_data_table_schema_version(sql_client, tenant_id,
foreign_key_info.parent_table_id_, table.get_in_offline_ddl_white_list()))) {
LOG_WARN("failed to update parent table schema version", K(ret));
table.get_table_id() == foreign_key_info.child_table_id_ ? foreign_key_info.parent_table_id_ : foreign_key_info.child_table_id_, table.get_in_offline_ddl_white_list()))) {
LOG_WARN("failed to update parent table schema version", K(ret), K(foreign_key_info));
}
}
if (OB_FAIL(ret)) {

View File

@ -311,7 +311,8 @@ private:
int add_table_part_info(common::ObISQLClient &sql_client, const ObTableSchema &table);
int delete_foreign_key(common::ObISQLClient &sql_client,
const ObTableSchema &table_schema,
const int64_t new_schema_version);
const int64_t new_schema_version,
const bool is_truncate_table);
int delete_from_all_foreign_key(common::ObISQLClient &sql_client,
const uint64_t tenant_id,
const int64_t new_schema_version,

View File

@ -1818,6 +1818,9 @@ int ObTruncateTableExecutor::execute(ObExecContext &ctx, ObTruncateTableStmt &st
&& FALSE_IT(const_cast<obrpc::ObTruncateTableArg&>(truncate_table_arg).session_id_ = my_session->get_sessid_for_table())) {
//impossible
} else if (!stmt.is_truncate_oracle_temp_table()) {
int64_t foreign_key_checks = 0;
my_session->get_foreign_key_checks(foreign_key_checks);
const_cast<obrpc::ObTruncateTableArg&>(truncate_table_arg).foreign_key_checks_ = is_oracle_mode() || (is_mysql_mode() && foreign_key_checks);
const_cast<obrpc::ObTruncateTableArg&>(truncate_table_arg).compat_mode_ = ORACLE_MODE == my_session->get_compatibility_mode()
? lib::Worker::CompatMode::ORACLE : lib::Worker::CompatMode::MYSQL;
int64_t affected_rows = 0;