-
Notifications
You must be signed in to change notification settings - Fork 2.3k
/
Expand.scala
133 lines (120 loc) · 5.52 KB
/
Expand.scala
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
/*
* Copyright (c) 2002-2018 "Neo Technology,"
* Network Engine for Objects in Lund AB [http://neotechnology.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.neo4j.cypher.internal.v3_4.logical.plans
import org.neo4j.cypher.internal.ir.v3_4.{CardinalityEstimation, PlannerQuery, VarPatternLength}
import org.neo4j.cypher.internal.util.v3_4.attribution.IdGen
import org.neo4j.cypher.internal.v3_4.expressions._
/**
* For every source row, traverse all the relationships of 'from' which fulfill the
* provided constraints. Produce one row per traversed relationships, and add the
* relationship and end node as values on the produced rows.
*/
case class Expand(source: LogicalPlan,
from: String,
dir: SemanticDirection,
types: Seq[RelTypeName],
to: String,
relName: String,
mode: ExpansionMode = ExpandAll)
(val solved: PlannerQuery with CardinalityEstimation)
(implicit idGen: IdGen)
extends LogicalPlan(idGen) with LazyLogicalPlan {
override val lhs = Some(source)
override def rhs = None
override val availableSymbols: Set[String] = source.availableSymbols + relName + to
}
/**
* This works exactly like Expand, but if no matching relationships are found, a single
* row is produced instead populated by the argument, and the 'relName' and 'to' variables
* are set to NO_VALUE.
*/
case class OptionalExpand(source: LogicalPlan,
from: String,
dir: SemanticDirection,
types: Seq[RelTypeName],
to: String,
relName: String,
mode: ExpansionMode = ExpandAll,
predicates: Seq[Expression] = Seq.empty)
(val solved: PlannerQuery with CardinalityEstimation)
(implicit idGen: IdGen)
extends LogicalPlan(idGen) with LazyLogicalPlan {
override val lhs = Some(source)
override def rhs = None
override val availableSymbols: Set[String] = source.availableSymbols + relName + to
}
/**
* For every source row, explore all homogeneous paths starting in 'from', that fulfill the provided
* criteria. Paths are homogeneous in that all relationships have to fulfill the same relationship
* predicate, and all nodes except 'from' have to fulfill the same node predicate. For each explored
* path that is longer or equal to length.min, and shorter than length.max, a row is produced.
*
* The relationships and end node of the corresponding path are added to the produced row.
*/
case class VarExpand(source: LogicalPlan,
from: String,
dir: SemanticDirection,
projectedDir: SemanticDirection,
types: Seq[RelTypeName],
to: String,
relName: String,
length: VarPatternLength,
mode: ExpansionMode = ExpandAll,
tempNode: String,
tempEdge: String,
nodePredicate: Expression,
edgePredicate: Expression,
legacyPredicates: Seq[(LogicalVariable, Expression)])
(val solved: PlannerQuery with CardinalityEstimation)
(implicit idGen: IdGen) extends LogicalPlan(idGen) with LazyLogicalPlan {
override val lhs = Some(source)
override def rhs = None
override val availableSymbols: Set[String] = source.availableSymbols + relName + to
}
/**
* In essence a VarExpand, where some paths are not explored if they could not produce an unseen
* end node. Used to serve DISTINCT VarExpands where the individual paths are not of interest. This
* operator does not guarantee unique end nodes, but it will produce less of them than the regular
* VarExpand.
*
* Only the end node is added to produced rows.
*/
case class PruningVarExpand(source: LogicalPlan,
from: String,
dir: SemanticDirection,
types: Seq[RelTypeName],
to: String,
minLength: Int,
maxLength: Int,
predicates: Seq[(LogicalVariable, Expression)] = Seq.empty)
(val solved: PlannerQuery with CardinalityEstimation)(implicit idGen: IdGen) extends LogicalPlan(idGen) with LazyLogicalPlan {
override val lhs = Some(source)
override def rhs = None
override val availableSymbols: Set[String] = source.availableSymbols + to
}
sealed trait ExpansionMode
/**
* Expand relationships (a)-[r]-(b) for a given a, and populate r and b
*/
case object ExpandAll extends ExpansionMode
/**
* Expand relationships (a)-[r]-(b) for a given a and b, and populate r
*/
case object ExpandInto extends ExpansionMode