bugfix: fix object privilege is lost after create or replace a view which was existed

This commit is contained in:
obdev
2022-11-07 07:08:06 +00:00
committed by wangzelin.wzl
parent 1a8e6bf6ae
commit b1b4631c04
2 changed files with 121 additions and 86 deletions

View File

@ -1653,6 +1653,33 @@ int ObDDLService::print_view_expanded_definition(
return ret; return ret;
} }
int ObDDLService::get_obj_privs_ora(const uint64_t tenant_id,
const uint64_t obj_id,
const uint64_t obj_type,
ObSchemaGetterGuard &schema_guard,
ObIArray<ObObjPriv> &obj_privs) {
int ret = OB_SUCCESS;
ObArray<const ObObjPriv*> obj_privs_pointer;
if (OB_FAIL(schema_guard.get_obj_priv_with_obj_id(tenant_id,
obj_id,
obj_type,
obj_privs_pointer,
true))) {
LOG_WARN("fail to get_obj_priv_with_obj_id", KR(ret), K(tenant_id), K(obj_id), K(obj_type));
} else {
for (int64_t i = 0; OB_SUCC(ret) && i < obj_privs_pointer.count(); ++i) {
if (OB_ISNULL(obj_privs_pointer.at(i))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("obj_privs_pointer contains NULL", KR(ret), K(i));
} else if(OB_FAIL(obj_privs.push_back(*(obj_privs_pointer.at(i))))) {
LOG_WARN("obj_privs fail to push back", KR(ret), K(i));
}
}
}
return ret;
}
int ObDDLService::create_tables_in_trans(const bool if_not_exist, int ObDDLService::create_tables_in_trans(const bool if_not_exist,
const ObString &ddl_stmt_str, const ObString &ddl_stmt_str,
const ObErrorInfo &error_info, const ObErrorInfo &error_info,
@ -1684,6 +1711,9 @@ int ObDDLService::create_tables_in_trans(const bool if_not_exist,
ObSchemaGetterGuard schema_guard; ObSchemaGetterGuard schema_guard;
uint64_t tenant_id = table_schemas.at(0).get_tenant_id(); uint64_t tenant_id = table_schemas.at(0).get_tenant_id();
share::schema::ObTableSchema &first_table = table_schemas.at(0); share::schema::ObTableSchema &first_table = table_schemas.at(0);
ObArray<ObObjPriv> orig_obj_privs_ora;
const ObTableSchema *old_view_schema = NULL;
bool is_oracle_mode = false;
int64_t refreshed_schema_version = 0; int64_t refreshed_schema_version = 0;
if (OB_FAIL(get_tenant_schema_guard_with_version_in_inner_table(tenant_id, schema_guard))) { if (OB_FAIL(get_tenant_schema_guard_with_version_in_inner_table(tenant_id, schema_guard))) {
LOG_WARN("fail to get schema guard with version in inner table", K(ret), K(tenant_id)); LOG_WARN("fail to get schema guard with version in inner table", K(ret), K(tenant_id));
@ -1692,6 +1722,8 @@ int ObDDLService::create_tables_in_trans(const bool if_not_exist,
} else if (OB_FAIL(trans.start(sql_proxy_, tenant_id, refreshed_schema_version))) { } else if (OB_FAIL(trans.start(sql_proxy_, tenant_id, refreshed_schema_version))) {
LOG_WARN("failed to start trans", KR(ret), K(tenant_id), LOG_WARN("failed to start trans", KR(ret), K(tenant_id),
K(tenant_id), K(refreshed_schema_version)); K(tenant_id), K(refreshed_schema_version));
} else if (OB_FAIL(first_table.check_if_oracle_compat_mode(is_oracle_mode))) {
LOG_WARN("fail to check is oracle mode", KR(ret), K(first_table));
} else { } else {
} }
if (OB_SUCC(ret)) { if (OB_SUCC(ret)) {
@ -1712,7 +1744,6 @@ int ObDDLService::create_tables_in_trans(const bool if_not_exist,
if (OB_FAIL(ret)) { if (OB_FAIL(ret)) {
} else if (table_schema.is_view_table() && if_not_exist) { } else if (table_schema.is_view_table() && if_not_exist) {
const ObString &view_name = table_schema.get_table_name(); const ObString &view_name = table_schema.get_table_name();
const ObTableSchema *old_view_schema = NULL;
if (OB_FAIL(schema_guard.get_table_schema(table_schema.get_tenant_id(), if (OB_FAIL(schema_guard.get_table_schema(table_schema.get_tenant_id(),
table_schema.get_database_id(), table_schema.get_database_id(),
view_name, view_name,
@ -1721,12 +1752,26 @@ int ObDDLService::create_tables_in_trans(const bool if_not_exist,
LOG_WARN("failed to get table schema", K(view_name), K(ret)); LOG_WARN("failed to get table schema", K(view_name), K(ret));
} else if (OB_ISNULL(old_view_schema)) { } else if (OB_ISNULL(old_view_schema)) {
ret = OB_SUCCESS; ret = OB_SUCCESS;
} else if (OB_FAIL(drop_trigger_in_drop_table(trans, ddl_operator, schema_guard, } else {
*old_view_schema, false))) { if (!is_oracle_mode) {
// 兼容oracle,create or replace view时drop trigger,且不进回收站 // no need to store obj privs
LOG_WARN("failed to drop trigger", K(old_view_schema->get_table_id()), K(ret)); } else if (OB_FAIL(get_obj_privs_ora(table_schema.get_tenant_id(),
} else if (OB_FAIL(ddl_operator.drop_table(*old_view_schema, trans))) { old_view_schema->get_table_id(),
LOG_WARN("failed to drop old view schema", K(ret)); static_cast<uint64_t>(ObObjectType::TABLE),
schema_guard,
orig_obj_privs_ora))) {
LOG_WARN("fial to get obj privs ora", KR(ret), K(table_schema.get_tenant_id()),
K(old_view_schema->get_table_id()));
}
if (OB_FAIL(ret)) {
} else if (OB_FAIL(drop_trigger_in_drop_table(trans, ddl_operator, schema_guard,
*old_view_schema, false))) {
// 兼容oracle,create or replace view时drop trigger,且不进回收站
LOG_WARN("failed to drop trigger", KR(ret), K(old_view_schema->get_table_id()));
} else if (OB_FAIL(ddl_operator.drop_table(*old_view_schema, trans))) {
LOG_WARN("failed to drop old view schema", KR(ret));
}
} }
} }
} }
@ -1761,15 +1806,32 @@ int ObDDLService::create_tables_in_trans(const bool if_not_exist,
} }
} }
} }
if (OB_SUCC(ret) && (0 == i) && table_schema.is_view_table() &&
OB_NOT_NULL(old_view_schema) && is_oracle_mode) {
const uint64_t db_id = table_schema.get_database_id();
const ObSimpleDatabaseSchema *db_schema = NULL;
if (OB_FAIL(schema_guard.get_database_schema(tenant_id, db_id, db_schema))) {
LOG_WARN("failed to get database schema", KR(ret), K(db_id));
} else if (OB_ISNULL(db_schema)) {
ret = OB_ERR_BAD_DATABASE;
LOG_WARN("db schema is NULL", KR(ret), K(tenant_id), K(db_id));
} else if (OB_FAIL(restore_obj_privs_for_table(table_schema.get_table_id(),
db_schema->get_database_name_str(),
table_schema.get_table_name_str(),
ddl_operator,
trans,
orig_obj_privs_ora))) {
LOG_WARN("restore_obj_privs_for_table failed", KR(ret), K(table_schema.get_table_id()),
K(db_schema->get_database_name_str()), K(table_schema.get_table_name_str()));
}
}
} }
// add error info for create force view // add error info for create force view
if (OB_SUCC(ret) && 1 == table_schemas.count() && first_table.is_user_view()) { if (OB_SUCC(ret) && 1 == table_schemas.count() && first_table.is_user_view()) {
bool is_oracle_mode = false;
if (OB_LIKELY(ERROR_STATUS_HAS_ERROR != error_info.get_error_status())) { if (OB_LIKELY(ERROR_STATUS_HAS_ERROR != error_info.get_error_status())) {
/* do nothing */ /* do nothing */
} else if (OB_FAIL(first_table.check_if_oracle_compat_mode(is_oracle_mode))) {
LOG_WARN("fail to check if tenant mode is oracle mode", K(ret));
} else if (OB_UNLIKELY(!is_oracle_mode)) { } else if (OB_UNLIKELY(!is_oracle_mode)) {
ret = OB_ERR_UNEXPECTED; ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected compat mode add create view error info", K(ret), K(is_oracle_mode)); LOG_WARN("unexpected compat mode add create view error info", K(ret), K(is_oracle_mode));
@ -12338,7 +12400,6 @@ int ObDDLService::truncate_table_in_trans(const obrpc::ObTruncateTableArg &arg,
ObArenaAllocator allocator(ObModIds::OB_RS_PARTITION_TABLE_TEMP); ObArenaAllocator allocator(ObModIds::OB_RS_PARTITION_TABLE_TEMP);
const uint64_t tenant_id = orig_table_schema.get_tenant_id(); const uint64_t tenant_id = orig_table_schema.get_tenant_id();
ObSArray<ObSAuditSchema> audit_schemas; ObSArray<ObSAuditSchema> audit_schemas;
ObArray<const ObObjPriv *> orig_obj_privs_pointer_ora;
ObArray<ObObjPriv> orig_obj_privs_ora; ObArray<ObObjPriv> orig_obj_privs_ora;
const bool to_recyclebin = false; const bool to_recyclebin = false;
if (table_schemas.count() < 1) { if (table_schemas.count() < 1) {
@ -12370,24 +12431,12 @@ int ObDDLService::truncate_table_in_trans(const obrpc::ObTruncateTableArg &arg,
} }
} }
// Save Oracle obj privs on table for later restore // Save Oracle obj privs on table for later restore
if (OB_SUCC(ret)) { if (OB_SUCC(ret) && OB_FAIL(get_obj_privs_ora(tenant_id,
if (OB_FAIL(schema_guard.get_obj_priv_with_obj_id(tenant_id, orig_table_schema.get_table_id(),
orig_table_schema.get_table_id(), static_cast<uint64_t>(ObObjectType::TABLE),
static_cast<uint64_t>(ObObjectType::TABLE), schema_guard,
orig_obj_privs_pointer_ora, orig_obj_privs_ora))) {
true /* reset flag */))) { LOG_WARN("fail to get obj privs ora", KR(ret), K(tenant_id), K(orig_table_schema.get_table_id()));
LOG_WARN("get_obj_priv_with_obj_id failed", K(ret),
K(tenant_id), K(orig_table_schema.get_table_id()));
} else {
for (int i = 0; OB_SUCC(ret) && i < orig_obj_privs_pointer_ora.count(); ++i) {
if (OB_ISNULL(orig_obj_privs_pointer_ora.at(i))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("orig_obj_privs_pointer_ora contains NULL", K(ret), K(i));
} else {
OZ (orig_obj_privs_ora.push_back(*(orig_obj_privs_pointer_ora.at(i))));
}
}
}
} }
if (OB_SUCC(ret) && OB_FAIL(drop_aux_table_in_truncate( if (OB_SUCC(ret) && OB_FAIL(drop_aux_table_in_truncate(
orig_table_schema, schema_guard, trans, ddl_operator, orig_table_schema, schema_guard, trans, ddl_operator,
@ -12592,17 +12641,16 @@ int ObDDLService::truncate_table_in_trans(const obrpc::ObTruncateTableArg &arg,
} }
if (OB_SUCC(ret) && (0 == i)) { if (OB_SUCC(ret) && (0 == i)) {
// truncate table needs to rebuild the audit rules for the newly created table // truncate table needs to rebuild the audit rules for the newly created table
if (OB_FAIL(restore_obj_priv_after_truncation( if (OB_FAIL(restore_obj_privs_for_table(tmp_schema.get_table_id(),
ddl_operator, database_name,
trans, tmp_schema.get_table_name_str(),
orig_obj_privs_ora, ddl_operator,
tmp_schema.get_table_id(), trans,
database_name, orig_obj_privs_ora))) {
tmp_schema.get_table_name_str()))) { LOG_WARN("restore_obj_privs_for_table failed", KR(ret),
LOG_WARN("restore_obj_priv_after_truncation failed", K(ret), K(tmp_schema.get_table_id()),
K(tmp_schema.get_table_id()), K(database_name),
K(database_name), K(tmp_schema.get_table_name_str()));
K(tmp_schema.get_table_name_str()));
} }
} }
} }
@ -12705,14 +12753,12 @@ int ObDDLService::truncate_table_in_trans(const obrpc::ObTruncateTableArg &arg,
return ret; return ret;
} }
int ObDDLService::restore_obj_priv_after_truncation( int ObDDLService::restore_obj_privs_for_table(const uint64_t new_table_id,
ObDDLOperator &ddl_operator, const ObString &database_name,
ObMySQLTransaction &trans, const ObString &table_name,
ObIArray<ObObjPriv> &orig_obj_privs_ora, ObDDLOperator &ddl_operator,
uint64_t new_table_id, ObMySQLTransaction &trans,
const ObString &database_name, ObIArray<ObObjPriv> &orig_obj_privs_ora) {
const ObString &table_name)
{
int ret = OB_SUCCESS; int ret = OB_SUCCESS;
for (int i = 0; OB_SUCC(ret) && i < orig_obj_privs_ora.count(); ++i) { for (int i = 0; OB_SUCC(ret) && i < orig_obj_privs_ora.count(); ++i) {
ObObjPriv &obj_priv = orig_obj_privs_ora.at(i); ObObjPriv &obj_priv = orig_obj_privs_ora.at(i);
@ -13103,39 +13149,24 @@ int ObDDLService::rebuild_hidden_table_priv(const ObTableSchema &orig_table_sche
ObMySQLTransaction &trans) ObMySQLTransaction &trans)
{ {
int ret = OB_SUCCESS; int ret = OB_SUCCESS;
ObArray<const ObObjPriv *> orig_obj_privs_pointer_ora;
ObArray<ObObjPriv> orig_obj_privs_ora; ObArray<ObObjPriv> orig_obj_privs_ora;
if (OB_FAIL(schema_guard.get_obj_priv_with_obj_id( if (OB_FAIL(get_obj_privs_ora(orig_table_schema.get_tenant_id(),
orig_table_schema.get_tenant_id(), orig_table_schema.get_table_id(),
orig_table_schema.get_table_id(), static_cast<uint64_t>(ObObjectType::TABLE),
static_cast<uint64_t>(ObObjectType::TABLE), schema_guard,
orig_obj_privs_pointer_ora, orig_obj_privs_ora))) {
true /* reset flag */))) { LOG_WARN("fail to get obj privs ora", KR(ret), K(orig_table_schema.get_tenant_id()),
LOG_WARN("get_obj_priv_with_obj_id failed", K(ret), K(orig_table_schema.get_table_id()));
K(orig_table_schema.get_table_id())); } else if (OB_FAIL(restore_obj_privs_for_table(hidden_table_schema.get_table_id(),
} else { hidden_table_schema.get_link_database_name(),
for (int i = 0; OB_SUCC(ret) && i < orig_obj_privs_pointer_ora.count(); ++i) { hidden_table_schema.get_table_name_str(),
if (OB_ISNULL(orig_obj_privs_pointer_ora.at(i))) { ddl_operator,
ret = OB_ERR_UNEXPECTED; trans,
LOG_WARN("orig_obj_privs_pointer_ora contains NULL", K(ret), K(i)); orig_obj_privs_ora))) {
} else {
OZ (orig_obj_privs_ora.push_back(*(orig_obj_privs_pointer_ora.at(i))));
}
}
}
if (OB_SUCC(ret)) {
// need to rebuild permissions for the newly created table // need to rebuild permissions for the newly created table
if (OB_FAIL(restore_obj_priv_after_truncation( LOG_WARN("restore_obj_privs_for_table failed", KR(ret),
ddl_operator, K(hidden_table_schema.get_table_id()),
trans, K(hidden_table_schema.get_table_name_str()));
orig_obj_privs_ora,
hidden_table_schema.get_table_id(),
hidden_table_schema.get_link_database_name(),
hidden_table_schema.get_table_name_str()))) {
LOG_WARN("restore_obj_priv_after_truncation failed", K(ret),
K(hidden_table_schema.get_table_id()),
K(hidden_table_schema.get_table_name_str()));
}
} }
return ret; return ret;
} }

View File

@ -1435,13 +1435,6 @@ private:
ObMySQLTransaction &trans, ObMySQLTransaction &trans,
const common::ObString *ddl_stmt_str, const common::ObString *ddl_stmt_str,
const common::ObString &db_name); const common::ObString &db_name);
int restore_obj_priv_after_truncation(
ObDDLOperator &ddl_operator,
ObMySQLTransaction &trans,
common::ObIArray<share::schema::ObObjPriv> &orig_obj_privs_ora,
uint64_t new_table_id,
const common::ObString &database_name,
const common::ObString &table_name);
int drop_aux_table_in_truncate( int drop_aux_table_in_truncate(
const share::schema::ObTableSchema &orig_table_schema, const share::schema::ObTableSchema &orig_table_schema,
share::schema::ObSchemaGetterGuard &schema_guard, share::schema::ObSchemaGetterGuard &schema_guard,
@ -2167,6 +2160,17 @@ private:
int alter_system_table_column_( int alter_system_table_column_(
share::schema::ObSchemaGetterGuard &schema_guard, share::schema::ObSchemaGetterGuard &schema_guard,
const share::schema::ObTableSchema &hard_code_schema); const share::schema::ObTableSchema &hard_code_schema);
int get_obj_privs_ora(const uint64_t tenant_id,
const uint64_t obj_id,
const uint64_t obj_type,
ObSchemaGetterGuard &schema_guard,
ObIArray<ObObjPriv> &obj_privs);
int restore_obj_privs_for_table(const uint64_t new_table_id,
const common::ObString &database_name,
const common::ObString &table_name,
ObDDLOperator &ddl_operator,
ObMySQLTransaction &trans,
common::ObIArray<share::schema::ObObjPriv> &orig_obj_privs_ora);
private: private:
bool inited_; bool inited_;
volatile bool stopped_; volatile bool stopped_;