This repository was archived by the owner on Oct 10, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 467
Expand file tree
/
Copy pathquery_graph.h
More file actions
171 lines (137 loc) · 6.56 KB
/
query_graph.h
File metadata and controls
171 lines (137 loc) · 6.56 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
#pragma once
#include <bitset>
#include <unordered_map>
#include "binder/expression/rel_expression.h"
namespace kuzu {
namespace binder {
constexpr static uint8_t MAX_NUM_QUERY_VARIABLES = 64;
class QueryGraph;
struct SubqueryGraph;
struct SubqueryGraphHasher;
using subquery_graph_set_t = std::unordered_set<SubqueryGraph, SubqueryGraphHasher>;
template<typename T>
using subquery_graph_V_map_t = std::unordered_map<SubqueryGraph, T, SubqueryGraphHasher>;
// hash on node bitset if subgraph has no rel
struct SubqueryGraphHasher {
std::size_t operator()(const SubqueryGraph& key) const;
};
struct SubqueryGraph {
const QueryGraph& queryGraph;
std::bitset<MAX_NUM_QUERY_VARIABLES> queryNodesSelector;
std::bitset<MAX_NUM_QUERY_VARIABLES> queryRelsSelector;
explicit SubqueryGraph(const QueryGraph& queryGraph) : queryGraph{queryGraph} {}
void addQueryNode(uint32_t nodePos) { queryNodesSelector[nodePos] = true; }
void addQueryRel(uint32_t relPos) { queryRelsSelector[relPos] = true; }
void addSubqueryGraph(const SubqueryGraph& other) {
queryRelsSelector |= other.queryRelsSelector;
queryNodesSelector |= other.queryNodesSelector;
}
common::idx_t getNumQueryNodes() const { return queryNodesSelector.count(); }
common::idx_t getNumQueryRels() const { return queryRelsSelector.count(); }
common::idx_t getTotalNumVariables() const {
return queryNodesSelector.count() + queryRelsSelector.count();
}
bool isSingleRel() const {
return queryRelsSelector.count() == 1 && queryNodesSelector.count() == 0;
}
std::unordered_map<common::idx_t, std::vector<common::idx_t>> getWCOJRelCandidates() const;
bool containAllVariables(std::unordered_set<std::string>& variables) const;
std::unordered_set<uint32_t> getNodeNbrPositions() const;
std::unordered_set<uint32_t> getRelNbrPositions() const;
subquery_graph_set_t getNbrSubgraphs(uint32_t size) const;
std::vector<uint32_t> getConnectedNodePos(const SubqueryGraph& nbr) const;
// E.g. query graph (a)-[e1]->(b) and subgraph (a)-[e1], although (b) is not in subgraph, we
// return both (a) and (b) regardless of node selector. See needPruneJoin() in
// join_order_enumerator.cpp for its use case.
std::unordered_set<uint32_t> getNodePositionsIgnoringNodeSelector() const;
bool operator==(const SubqueryGraph& other) const {
return queryRelsSelector == other.queryRelsSelector &&
queryNodesSelector == other.queryNodesSelector;
}
private:
subquery_graph_set_t getBaseNbrSubgraph() const;
subquery_graph_set_t getNextNbrSubgraphs(const SubqueryGraph& prevNbr) const;
};
// QueryGraph represents a connected pattern specified in MATCH clause.
class QueryGraph {
public:
QueryGraph() = default;
QueryGraph(const QueryGraph& other)
: queryNodeNameToPosMap{other.queryNodeNameToPosMap},
queryRelNameToPosMap{other.queryRelNameToPosMap}, queryNodes{other.queryNodes},
queryRels{other.queryRels} {}
bool isEmpty() const;
std::vector<std::shared_ptr<NodeOrRelExpression>> getAllPatterns() const;
common::idx_t getNumQueryNodes() const { return queryNodes.size(); }
bool containsQueryNode(const std::string& queryNodeName) const {
return queryNodeNameToPosMap.contains(queryNodeName);
}
std::vector<std::shared_ptr<NodeExpression>> getQueryNodes() const { return queryNodes; }
std::shared_ptr<NodeExpression> getQueryNode(const std::string& queryNodeName) const {
return queryNodes[getQueryNodePos(queryNodeName)];
}
std::shared_ptr<NodeExpression> getQueryNode(common::idx_t nodePos) const {
return queryNodes[nodePos];
}
std::vector<std::shared_ptr<NodeExpression>> getQueryNodes(
const std::vector<common::idx_t>& nodePoses) const;
common::idx_t getQueryNodePos(NodeExpression& node) const {
return getQueryNodePos(node.getUniqueName());
}
uint32_t getQueryNodePos(const std::string& queryNodeName) const {
return queryNodeNameToPosMap.at(queryNodeName);
}
void addQueryNode(std::shared_ptr<NodeExpression> queryNode);
uint32_t getNumQueryRels() const { return queryRels.size(); }
bool containsQueryRel(const std::string& queryRelName) const {
return queryRelNameToPosMap.contains(queryRelName);
}
std::vector<std::shared_ptr<RelExpression>> getQueryRels() const { return queryRels; }
std::shared_ptr<RelExpression> getQueryRel(const std::string& queryRelName) const {
return queryRels.at(queryRelNameToPosMap.at(queryRelName));
}
std::shared_ptr<RelExpression> getQueryRel(common::idx_t relPos) const {
return queryRels[relPos];
}
std::vector<std::shared_ptr<RelExpression>> getQueryRels(
const std::vector<common::idx_t>& indices) const;
common::idx_t getQueryRelPos(const std::string& queryRelName) const {
return queryRelNameToPosMap.at(queryRelName);
}
void addQueryRel(std::shared_ptr<RelExpression> queryRel);
bool canProjectExpression(const std::shared_ptr<Expression>& expression) const;
bool isConnected(const QueryGraph& other);
void merge(const QueryGraph& other);
std::unique_ptr<QueryGraph> copy() const { return std::make_unique<QueryGraph>(*this); }
private:
std::unordered_map<std::string, uint32_t> queryNodeNameToPosMap;
std::unordered_map<std::string, uint32_t> queryRelNameToPosMap;
std::vector<std::shared_ptr<NodeExpression>> queryNodes;
std::vector<std::shared_ptr<RelExpression>> queryRels;
};
// QueryGraphCollection represents a pattern (a set of connected components) specified in MATCH
// clause.
class QueryGraphCollection {
public:
QueryGraphCollection() = default;
DELETE_COPY_DEFAULT_MOVE(QueryGraphCollection);
void addAndMergeQueryGraphIfConnected(QueryGraph queryGraphToAdd);
void finalize();
common::idx_t getNumQueryGraphs() const { return queryGraphs.size(); }
QueryGraph* getQueryGraphUnsafe(common::idx_t idx) { return &queryGraphs[idx]; }
const QueryGraph* getQueryGraph(common::idx_t idx) const { return &queryGraphs[idx]; }
std::vector<std::shared_ptr<NodeExpression>> getQueryNodes() const;
std::vector<std::shared_ptr<RelExpression>> getQueryRels() const;
private:
std::vector<QueryGraph> mergeGraphs(common::idx_t baseGraphIdx);
private:
std::vector<QueryGraph> queryGraphs;
};
struct BoundGraphPattern {
QueryGraphCollection queryGraphCollection;
std::shared_ptr<Expression> where;
BoundGraphPattern() = default;
DELETE_COPY_DEFAULT_MOVE(BoundGraphPattern);
};
} // namespace binder
} // namespace kuzu