Fix config comparison

This commit is contained in:
Pavel Kruglov 2021-04-02 13:17:28 +03:00
parent dfbe042bf1
commit dff7834af0
3 changed files with 53 additions and 42 deletions

View File

@ -32,60 +32,60 @@ bool isSameConfiguration(const Poco::Util::AbstractConfiguration & left, const P
return isSameConfiguration(left, key, right, key);
}
bool isSameConfigurationWithMultipleKeys(const Poco::Util::AbstractConfiguration & left, const Poco::Util::AbstractConfiguration & right, const String & root, const String & name)
{
if (&left == &right)
return true;
auto left_multiple_keys = getMultipleKeysFromConfig(left, root, name);
auto right_multiple_keys = getMultipleKeysFromConfig(right, root, name);
if (left_multiple_keys.size() != right_multiple_keys.size())
return false;
for (auto & key : left_multiple_keys)
if (!isSameConfiguration(left, right, concatKeyAndSubKey(root, key)))
return false;
return true;
}
bool isSameConfiguration(const Poco::Util::AbstractConfiguration & left, const String & left_key,
const Poco::Util::AbstractConfiguration & right, const String & right_key)
{
if (&left == &right && left_key == right_key)
return true;
/// Config may have multiple keys with one name. For example:
/// <yandex>
/// <some_key>...</some_key>
/// <some_key>...</some_key>
/// </yandex>
/// In this case we need to compare all of them.
auto left_multiple_keys = getMultipleKeysFromConfig(left, "", left_key);
auto right_multiple_keys = getMultipleKeysFromConfig(right, "", right_key);
if (left_multiple_keys.size() != right_multiple_keys.size())
bool has_property = left.hasProperty(left_key);
if (has_property != right.hasProperty(right_key))
return false;
for (size_t i = 0; i != left_multiple_keys.size(); ++i)
if (has_property)
{
if (left_multiple_keys[i] != right_multiple_keys[i])
/// The left and right configurations contains values so we can compare them.
if (left.getRawString(left_key) != right.getRawString(right_key))
return false;
}
bool has_property = left.hasProperty(left_multiple_keys[i]);
if (has_property != right.hasProperty(right_multiple_keys[i]))
/// Get the subkeys of the left and right configurations.
Poco::Util::AbstractConfiguration::Keys subkeys;
left.keys(left_key, subkeys);
{
/// Check that the right configuration has the same set of subkeys as the left configuration.
Poco::Util::AbstractConfiguration::Keys right_subkeys;
right.keys(right_key, right_subkeys);
std::unordered_set<StringRef> left_subkeys{subkeys.begin(), subkeys.end()};
if ((left_subkeys.size() != right_subkeys.size()) || (left_subkeys.size() != subkeys.size()))
return false;
if (has_property)
{
/// The left and right configurations contains values so we can compare them.
if (left.getRawString(left_multiple_keys[i]) != right.getRawString(right_multiple_keys[i]))
return false;
}
/// Get the subkeys of the left and right configurations.
Poco::Util::AbstractConfiguration::Keys subkeys;
left.keys(left_multiple_keys[i], subkeys);
{
/// Check that the right configuration has the same set of subkeys as the left configuration.
Poco::Util::AbstractConfiguration::Keys right_subkeys;
right.keys(right_multiple_keys[i], right_subkeys);
std::unordered_set<StringRef> left_subkeys{subkeys.begin(), subkeys.end()};
if ((left_subkeys.size() != right_subkeys.size()) || (left_subkeys.size() != subkeys.size()))
return false;
for (const auto & right_subkey : right_subkeys)
if (!left_subkeys.count(right_subkey))
return false;
}
/// Go through all the subkeys and compare corresponding parts of the configurations.
for (const auto & subkey : subkeys)
if (!isSameConfiguration(left, concatKeyAndSubKey(left_multiple_keys[i], subkey), right, concatKeyAndSubKey(right_multiple_keys[i], subkey)))
for (const auto & right_subkey : right_subkeys)
if (!left_subkeys.count(right_subkey))
return false;
}
/// Go through all the subkeys and compare corresponding parts of the configurations.
for (const auto & subkey : subkeys)
if (!isSameConfiguration(left, concatKeyAndSubKey(left_key, subkey), right, concatKeyAndSubKey(right_key, subkey)))
return false;
return true;
}

View File

@ -13,6 +13,17 @@ namespace DB
bool isSameConfiguration(const Poco::Util::AbstractConfiguration & left,
const Poco::Util::AbstractConfiguration & right);
/// Config may have multiple keys with one name. For example:
/// <root>
/// <some_key>...</some_key>
/// <some_key>...</some_key>
/// </root>
/// Returns true if the specified subview of the two configurations contains
/// the same keys and values for each key with the given name.
bool isSameConfigurationWithMultipleKeys(const Poco::Util::AbstractConfiguration & left,
const Poco::Util::AbstractConfiguration & right,
const String & root, const String & name);
/// Returns true if the specified subview of the two configurations contains the same keys and values.
bool isSameConfiguration(const Poco::Util::AbstractConfiguration & left,
const Poco::Util::AbstractConfiguration & right,

View File

@ -1374,11 +1374,11 @@ void Context::setExternalModelsConfig(const ConfigurationPtr & config, const std
{
std::lock_guard lock(shared->external_models_mutex);
if (shared->external_models_config && isSameConfiguration(*config, *shared->external_models_config, config_name))
if (shared->external_models_config && isSameConfigurationWithMultipleKeys(*config, *shared->external_models_config, "", config_name))
return;
shared->external_models_config = config;
shared->models_repository_guard.reset();
shared->models_repository_guard .reset();
shared->models_repository_guard = getExternalModelsLoaderUnlocked().addConfigRepository(
std::make_unique<ExternalLoaderXMLConfigRepository>(*config, config_name));
}