Rewrite Set lookup to make it more readable

This commit is contained in:
Nicolae Vartolomei 2020-07-01 15:05:54 +01:00
parent f8ceca6942
commit 3854ce6d84
3 changed files with 22 additions and 21 deletions

View File

@ -441,9 +441,14 @@ void Set::checkColumnsNumber(size_t num_key_columns) const
}
}
bool Set::areTypesEqual(size_t set_type_idx, const DataTypePtr & other_type) const
{
return removeNullable(recursiveRemoveLowCardinality(data_types[set_type_idx]))->equals(*removeNullable(recursiveRemoveLowCardinality(other_type)));
}
void Set::checkTypesEqual(size_t set_type_idx, const DataTypePtr & other_type) const
{
if (!removeNullable(recursiveRemoveLowCardinality(data_types[set_type_idx]))->equals(*removeNullable(recursiveRemoveLowCardinality(other_type))))
if (!this->areTypesEqual(set_type_idx, other_type))
throw Exception("Types of column " + toString(set_type_idx + 1) + " in section IN don't match: "
+ other_type->getName() + " on the left, "
+ data_types[set_type_idx]->getName() + " on the right", ErrorCodes::TYPE_MISMATCH);

View File

@ -74,6 +74,7 @@ public:
Columns getSetElements() const { return { set_elements.begin(), set_elements.end() }; }
void checkColumnsNumber(size_t num_key_columns) const;
bool areTypesEqual(size_t set_type_idx, const DataTypePtr & other_type) const;
void checkTypesEqual(size_t set_type_idx, const DataTypePtr & other_type) const;
private:

View File

@ -617,13 +617,10 @@ bool KeyCondition::tryPrepareSetIndex(
const ASTPtr & right_arg = args[1];
PreparedSetKey set_key;
SetPtr prepared_set;
if (right_arg->as<ASTSubquery>() || right_arg->as<ASTIdentifier>())
{
set_key = PreparedSetKey::forSubquery(*right_arg);
auto set_it = prepared_sets.find(set_key);
auto set_it = prepared_sets.find(PreparedSetKey::forSubquery(*right_arg));
if (set_it == prepared_sets.end())
return false;
@ -631,25 +628,23 @@ bool KeyCondition::tryPrepareSetIndex(
}
else
{
/// We have `PreparedSetKey::forLiteral` but it is useless here as we don't have enough information
/// about types in left argument of the IN operator. Instead, we manually iterate through all the sets
/// and find the one for the right arg based on the AST structure (getTreeHash), after that we check
/// that the types it was prepared with are compatible with the types of the primary key.
auto set_ast_hash = right_arg->getTreeHash();
auto set_it = std::find_if(
prepared_sets.begin(),
prepared_sets.end(),
[&](const auto &e)
prepared_sets.begin(), prepared_sets.end(),
[&](const auto & candidate_entry)
{
if (e.first.ast_hash == right_arg->getTreeHash())
{
for (size_t i = 0; i < data_types.size(); i++)
{
if (!recursiveRemoveLowCardinality(data_types[i])->equals(*e.first.types[indexes_mapping[i].tuple_index]))
{
return false;
}
}
if (candidate_entry.first.ast_hash != set_ast_hash)
return false;
return true;
}
for (size_t i = 0; i < indexes_mapping.size(); ++i)
if (!candidate_entry.second->areTypesEqual(indexes_mapping[i].tuple_index, data_types[i]))
return false;
return false;
return true;
});
if (set_it == prepared_sets.end())
return false;
@ -663,7 +658,7 @@ bool KeyCondition::tryPrepareSetIndex(
prepared_set->checkColumnsNumber(left_args_count);
for (size_t i = 0; i < indexes_mapping.size(); ++i)
prepared_set->checkTypesEqual(indexes_mapping[i].tuple_index, removeLowCardinality(data_types[i]));
prepared_set->checkTypesEqual(indexes_mapping[i].tuple_index, data_types[i]);
out.set_index = std::make_shared<MergeTreeSetIndex>(prepared_set->getSetElements(), std::move(indexes_mapping));