diff --git a/src/Access/AccessBackup.cpp b/src/Access/AccessBackup.cpp index 5c0b4b92f05..577ae00bcc3 100644 --- a/src/Access/AccessBackup.cpp +++ b/src/Access/AccessBackup.cpp @@ -452,20 +452,20 @@ void AccessRestorerFromBackup::generateRandomIDsAndResolveDependencies(const Acc } else { - if (entity_info.is_dependency && !entity_info.restore && !skip_unresolved_dependencies) - { - throw Exception(ErrorCodes::ACCESS_ENTITY_NOT_FOUND, "Cannot resolve {} while restoring from backup", - AccessEntityTypeInfo::get(type).formatEntityNameWithType(name)); - } if (entity_info.restore) { entity_info.new_id = UUIDHelpers::generateV4(); LOG_TRACE(log, "{}: Generated new UUID {}", AccessEntityTypeInfo::get(type).formatEntityNameWithType(name), *entity_info.new_id); } - else + else if (skip_unresolved_dependencies) { LOG_TRACE(log, "{}: Not found, ignoring", AccessEntityTypeInfo::get(type).formatEntityNameWithType(name)); } + else + { + throw Exception(ErrorCodes::ACCESS_ENTITY_NOT_FOUND, "Cannot resolve {} while restoring from backup", + AccessEntityTypeInfo::get(type).formatEntityNameWithType(name)); + } } } diff --git a/src/Backups/RestoreSettings.h b/src/Backups/RestoreSettings.h index 1cab081b20d..2b44951ccff 100644 --- a/src/Backups/RestoreSettings.h +++ b/src/Backups/RestoreSettings.h @@ -100,7 +100,7 @@ struct RestoreSettings /// How the RESTORE command will handle if an user (or role or profile) which it's going to restore already exists. RestoreAccessCreationMode create_access = RestoreAccessCreationMode::kCreateIfNotExists; - /// Ignore dependencies of access entities which can't be resolved. + /// Ignore dependencies or dependents (with update_access_entities_dependents=true) of access entities in the case if they can't be resolved. /// For example: if a backup contains a profile assigned to a user: `CREATE PROFILE p1; CREATE USER u1 SETTINGS PROFILE p1` /// and now we're restoring only user `u1` and profile `p1` doesn't exists, then /// this flag is whether RESTORE should continue with restoring user `u1` without assigning profile `p1`. diff --git a/tests/queries/0_stateless/03231_restore_user_with_existing_role.sh b/tests/queries/0_stateless/03231_restore_user_with_existing_role.sh index 4a079ef1613..0db57f2dd7c 100755 --- a/tests/queries/0_stateless/03231_restore_user_with_existing_role.sh +++ b/tests/queries/0_stateless/03231_restore_user_with_existing_role.sh @@ -75,7 +75,8 @@ do_check echo "Everything dropped, restore system.roles, then system.users" ${CLICKHOUSE_CLIENT} --query "DROP USER ${user_a}" ${CLICKHOUSE_CLIENT} --query "DROP ROLE ${role_b}" -${CLICKHOUSE_CLIENT} --query "RESTORE TABLE system.roles FROM ${backup_name} FORMAT Null" +# Here "allow_unresolved_access_dependencies=true" because users don't exist yet and restored roles can't be granted to non-existent users. +${CLICKHOUSE_CLIENT} --query "RESTORE TABLE system.roles FROM ${backup_name} SETTINGS allow_unresolved_access_dependencies=true FORMAT Null" ${CLICKHOUSE_CLIENT} --query "SELECT 'user_a', count() FROM system.users WHERE name = '${user_a}'" ${CLICKHOUSE_CLIENT} --query "SELECT 'role_b', count() FROM system.roles WHERE name = '${role_b}'" ${CLICKHOUSE_CLIENT} --query "RESTORE TABLE system.users FROM ${backup_name} FORMAT Null" @@ -84,6 +85,7 @@ do_check echo "Everything dropped, restore system.users, then system.roles" ${CLICKHOUSE_CLIENT} --query "DROP USER ${user_a}" ${CLICKHOUSE_CLIENT} --query "DROP ROLE ${role_b}" +# Here "allow_unresolved_access_dependencies=true" because roles don't exist yet and can't be granted to restored users. ${CLICKHOUSE_CLIENT} --query "RESTORE TABLE system.users FROM ${backup_name} SETTINGS allow_unresolved_access_dependencies=true FORMAT Null" ${CLICKHOUSE_CLIENT} --query "SELECT 'user_a', count() FROM system.users WHERE name = '${user_a}'" ${CLICKHOUSE_CLIENT} --query "SELECT 'role_b', count() FROM system.roles WHERE name = '${role_b}'"