1#pragma once
2
3#include <Parsers/IAST.h>
4#include <DataTypes/IDataType.h>
5#include <memory>
6#include <unordered_map>
7#include <DataTypes/DataTypeLowCardinality.h>
8
9namespace DB
10{
11
12struct PreparedSetKey
13{
14 /// Prepared sets for tuple literals are indexed by the hash of the tree contents and by the desired
15 /// data types of set elements (two different Sets can be required for two tuples with the same contents
16 /// if left hand sides of the IN operators have different types).
17 static PreparedSetKey forLiteral(const IAST & ast, DataTypes types_)
18 {
19 /// Remove LowCardinality types from type list because Set doesn't support LowCardinality keys now,
20 /// just converts LowCardinality to ordinary types.
21 for (auto & type : types_)
22 type = recursiveRemoveLowCardinality(type);
23
24 PreparedSetKey key;
25 key.ast_hash = ast.getTreeHash();
26 key.types = std::move(types_);
27 return key;
28 }
29
30 /// Prepared sets for subqueries are indexed only by the AST contents because the type of the resulting
31 /// set is fully determined by the subquery.
32 static PreparedSetKey forSubquery(const IAST & ast)
33 {
34 PreparedSetKey key;
35 key.ast_hash = ast.getTreeHash();
36 return key;
37 }
38
39 IAST::Hash ast_hash;
40 DataTypes types; /// Empty for subqueries.
41
42 bool operator==(const PreparedSetKey & other) const
43 {
44 if (ast_hash != other.ast_hash)
45 return false;
46
47 if (types.size() != other.types.size())
48 return false;
49
50 for (size_t i = 0; i < types.size(); ++i)
51 {
52 if (!types[i]->equals(*other.types[i]))
53 return false;
54 }
55
56 return true;
57 }
58
59 struct Hash
60 {
61 UInt64 operator()(const PreparedSetKey & key) const { return key.ast_hash.first; }
62 };
63};
64
65class Set;
66using SetPtr = std::shared_ptr<Set>;
67
68using PreparedSets = std::unordered_map<PreparedSetKey, SetPtr, PreparedSetKey::Hash>;
69
70}
71