Register GROUP BY keys in scope.nullable_group_by_keys in every shape in which an expression * equal to a key can arrive at the lookup in resolveExpressionNode, so that the lookup can use * exact comparison (including types): * - the original form, for keys resolved from scratch; * - the form with every maximal proper sub-key already converted to Nullable and the types of * the nodes a
| 3837 | * All shapes are mapped to the original key node. |
| 3838 | */ |
| 3839 | void registerNullableGroupByKeys(const QueryTreeNodes & group_by_keys, IdentifierResolveScope & scope) |
| 3840 | { |
| 3841 | for (const auto & key : group_by_keys) |
| 3842 | scope.nullable_group_by_keys.emplace(key, key); |
| 3843 | |
| 3844 | for (const auto & key : group_by_keys) |
| 3845 | { |
| 3846 | if (key->as<FunctionNode>()) |
| 3847 | { |
| 3848 | auto key_with_converted_sub_keys = key->clone(); |
| 3849 | bool converted = false; |
| 3850 | |
| 3851 | for (auto & child : key_with_converted_sub_keys->getChildren()) |
| 3852 | { |
| 3853 | if (child && convertNestedGroupByKeysToNullable(child, scope.nullable_group_by_keys, scope.context)) |
| 3854 | converted = true; |
| 3855 | } |
| 3856 | |
| 3857 | if (converted) |
| 3858 | { |
| 3859 | rerunFunctionResolve(key_with_converted_sub_keys->as<FunctionNode>(), scope.context); |
| 3860 | scope.nullable_group_by_keys.emplace(std::move(key_with_converted_sub_keys), key); |
| 3861 | } |
| 3862 | } |
| 3863 | |
| 3864 | if (nodeSupportsConvertToNullable(key)) |
| 3865 | { |
| 3866 | auto converted_key = key->clone(); |
| 3867 | converted_key->convertToNullable(); |
| 3868 | scope.nullable_group_by_keys.emplace(std::move(converted_key), key); |
| 3869 | } |
| 3870 | } |
| 3871 | } |
| 3872 | |
| 3873 | } |
| 3874 |
no test coverage detected