Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
小 白蛋
Neo4jsource
Commits
76c0f0cb
Commit
76c0f0cb
authored
7 years ago
by
Pontus Melke
Browse files
Options
Download
Plain Diff
Merge remote-tracking branch 'upstream/3.1' into 3.2
parents
49f927df
6c0459e7
4.4
3.2
3.3
3.3-report-costs
3.4
3.5
3.5-compiled-expression
3.5-no-more-longarray-hashing
4.0
4.1
4.2
4.2-pipelined
4.3
5.0
5.1
5.2
akollegger-patch-1
issue-management-update
revert-12892-feature/upd
testwin/3.3-ref-from-slot-name
testwin/3.4-failing-windows
5.2.0
5.1.0
5.0.0
4.4.14
4.4.13
4.4.12
4.4.11
4.4.10
4.4.9
4.4.8
4.4.7
4.4.6
4.4.5
4.4.4
4.4.3
4.4.2
4.4.1
4.4.0
4.4.0-alpha01
4.3.21
4.3.20
4.3.19
4.3.18
4.3.17
4.3.16
4.3.15
4.3.14
4.3.13
4.3.12
4.3.11
4.3.10
4.3.9
4.3.8
4.3.7
4.3.6
4.3.5
4.3.4
4.3.3
4.3.2
4.3.1
4.3.0
4.2.19
4.2.18
4.2.17
4.2.16
4.2.15
4.2.14
4.2.13
4.2.12
4.2.11
4.2.10
4.2.9
4.2.8
4.2.7
4.2.6
4.2.5
4.2.4
4.2.3
4.2.2
4.2.1
4.2.0
4.1.12
4.1.11
4.1.10
4.1.9
4.1.8
4.1.7
4.1.6
4.1.5
4.1.4
4.1.3
4.1.2
4.1.1
4.1.0
4.1.0-alpha01
4.0.12
4.0.11
4.0.10
4.0.9
4.0.8
4.0.7
4.0.6
4.0.5
4.0.4
4.0.3
4.0.2
4.0.1
4.0.0
4.0.0-rc01
4.0.0-beta03mr03
4.0.0-beta02
4.0.0-beta01
4.0.0-alpha10
4.0.0-alpha09mr02
4.0.0-alpha08
4.0.0-alpha07mr01
4.0.0-alpha06
4.0.0-alpha05
4.0.0-alpha04
4.0.0-alpha03
4.0.0-alpha02
4.0.0-alpha01
3.5.35
3.5.34
3.5.33
3.5.32
3.5.31
3.5.30
3.5.29
3.5.28
3.5.27
3.5.26
3.5.25
3.5.24
3.5.23
3.5.22
3.5.21
3.5.20
3.5.19
3.5.18
3.5.17
3.5.16
3.5.15
3.5.14
3.5.13
3.5.12
3.5.11
3.5.9
3.5.8
3.5.7
3.5.6
3.5.5
3.5.4
3.5.3
3.5.2
3.5.1
3.5.0
3.5.0-rc01
3.5.0-beta03
3.5.0-beta02
3.5.0-beta01
3.5.0-alpha09
3.5.0-alpha08
3.5.0-alpha07
3.5.0-alpha06
3.5.0-alpha05
3.5.0-alpha04
3.5.0-alpha02
3.5.0-alpha01
3.4.18
3.4.17
3.4.16
3.4.15
3.4.14
3.4.13
3.4.12
3.4.11
3.4.10
3.4.9
3.4.8
3.4.7
3.4.6
3.4.5
3.4.4
3.4.2
3.4.1
3.4.0
3.4.0-rc02
3.4.0-rc01
3.4.0-beta02
3.4.0-beta01
3.4.0-alpha10
3.4.0-alpha09
3.4.0-alpha08
3.4.0-alpha07
3.4.0-alpha06
3.4.0-alpha05
3.4.0-alpha04
3.4.0-alpha03
3.4.0-alpha02
3.4.0-alpha01
3.3.9
3.3.8
3.3.7
3.3.6
3.3.5
3.3.4
3.3.3
3.3.2
3.3.1
3.2.14
3.2.13
3.2.12
3.2.11
3.2.10
3.2.9
3.2.8
3.2.7
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
community/cypher/acceptance-spec-suite/src/test/scala/org/neo4j/internal/cypher/acceptance/ShortestPathEdgeCasesAcceptanceTest.scala
+145
-0
...pher/acceptance/ShortestPathEdgeCasesAcceptanceTest.scala
community/cypher/cypher-compiler-3.2/src/main/scala/org/neo4j/cypher/internal/compiler/v3_2/planner/logical/steps/planShortestPaths.scala
+7
-1
...mpiler/v3_2/planner/logical/steps/planShortestPaths.scala
with
152 additions
and
1 deletion
+152
-1
community/cypher/acceptance-spec-suite/src/test/scala/org/neo4j/internal/cypher/acceptance/ShortestPathEdgeCasesAcceptanceTest.scala
0 → 100644
+
145
-
0
View file @
76c0f0cb
/*
* Copyright (c) 2002-2017 "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.internal.cypher.acceptance
import
org.neo4j.cypher.internal.RewindableExecutionResult
import
org.neo4j.cypher.internal.compatibility.ClosingExecutionResult
import
org.neo4j.cypher.
{
ExecutionEngineFunSuite
,
NewPlannerTestSupport
}
import
org.neo4j.graphdb.Node
class
ShortestPathEdgeCasesAcceptanceTest
extends
ExecutionEngineFunSuite
with
NewPlannerTestSupport
{
test
(
"GH #5803 query should work with shortest path"
)
{
def
createTestGraph
()
=
{
// First create some background graph to get the stats right
(
0
to
16
).
map
(
_
=>
createNode
()).
sliding
(
2
).
foreach
{
case
Seq
(
n1
,
n2
)
=>
relate
(
n1
,
n2
)
}
// Now create the specific subgraph used for the test
graph
.
createIndex
(
"WP"
,
"id"
)
val
query
=
"""create (_31801:`WP` {`id`:1})
|create (_31802:`WP` {`id`:2})
|create (_31803:`WP` {`id`:3})
|create (_31804:`WP` {`id`:4})
|create (_31805:`WP` {`id`:5})
|create (_31806:`WP` {`id`:11})
|create (_31807:`WP` {`id`:12})
|create (_31808:`WP` {`id`:13})
|create (_31809:`WP` {`id`:22})
|create (_31810:`WP` {`id`:23})
|create (_31811:`WP` {`id`:21})
|create (_31812:`WP` {`id`:14})
|create (_31813:`WP` {`id`:29})
|create (_31814:`WP` {`id`:15})
|create (_31815:`WP` {`id`:24})
|create (_31816:`WP` {`id`:25})
|create (_31817:`WP` {`id`:26})
|create (_31818:`WP` {`id`:27})
|create (_31819:`WP` {`id`:28})
|create (_31820:`WP` {`id`:30})
|create (_31801)-[:`SE`]->(_31806)
|create (_31801)-[:`SE`]->(_31802)
|create (_31802)-[:`SE`]->(_31807)
|create (_31802)-[:`SE`]->(_31803)
|create (_31803)-[:`SE`]->(_31808)
|create (_31803)-[:`SE`]->(_31804)
|create (_31804)-[:`SE`]->(_31812)
|create (_31804)-[:`SE`]->(_31805)
|create (_31805)-[:`SE`]->(_31814)
|create (_31805)-[:`SE`]->(_31801)
|create (_31806)-[:`SE`]->(_31809)
|create (_31806)-[:`SE`]->(_31811)
|create (_31806)-[:`SE`]->(_31807)
|create (_31807)-[:`SE`]->(_31815)
|create (_31807)-[:`SE`]->(_31810)
|create (_31807)-[:`SE`]->(_31808)
|create (_31808)-[:`SE`]->(_31817)
|create (_31808)-[:`SE`]->(_31816)
|create (_31808)-[:`SE`]->(_31812)
|create (_31809)-[:`SE`]->(_31811)
|create (_31810)-[:`SE`]->(_31809)
|create (_31811)-[:`SE`]->(_31820)
|create (_31812)-[:`SE`]->(_31819)
|create (_31812)-[:`SE`]->(_31818)
|create (_31812)-[:`SE`]->(_31814)
|create (_31813)-[:`SE`]->(_31819)
|create (_31814)-[:`SE`]->(_31820)
|create (_31814)-[:`SE`]->(_31813)
|create (_31814)-[:`SE`]->(_31806)
|create (_31815)-[:`SE`]->(_31810)
|create (_31816)-[:`SE`]->(_31815)
|create (_31817)-[:`SE`]->(_31816)
|create (_31818)-[:`SE`]->(_31817)
|create (_31819)-[:`SE`]->(_31818)
|create (_31820)-[:`SE`]->(_31813)"""
.
stripMargin
graph
.
execute
(
query
)
}
createTestGraph
()
val
query
=
"""WITH [1,3,26,14] as wps
|UNWIND wps AS wpstartid
|UNWIND wps AS wpendid
|WITH wpstartid, wpendid, wps
|WHERE wpstartid<wpendid
|MATCH (wpstart {id:wpstartid})
|MATCH (wpend {id:wpendid})
|MATCH p=shortestPath((wpstart)-[*..10]-(wpend))
|WHERE ALL(id IN wps WHERE id IN EXTRACT(n IN nodes(p) | n.id))
|WITH p, size(nodes(p)) as length order by length limit 1
|RETURN EXTRACT(n IN nodes(p) | n.id) as nodes"""
.
stripMargin
val
results
=
executeWithCostPlannerOnly
(
query
)
results
.
toList
should
equal
(
List
(
Map
(
"nodes"
->
List
(
1
,
2
,
3
,
4
,
14
,
13
,
26
))))
}
test
(
"Predicate should associate with correct shortestPath in complex query"
)
{
// Given query with two shortestPath expressions and a predicate that depends on both paths
val
query
=
"""
|MATCH (r1:Road) WHERE r1.latitude = 51.357397146246264 AND r1.longitude = -0.20153965352074504
|MATCH (r2:Road) WHERE r2.latitude = 51.36272835382321 AND r2.longitude = -0.16836400394638354
|MATCH path = shortestpath((r1)-[:CONNECTS*]-(r2))
|WITH r1, r2, path
|MATCH returnPath = shortestpath((r2)-[:CONNECTS*]-(r1))
|WHERE none(rel in relationships(returnPath) where rel in relationships(path))
|RETURN returnPath
"""
.
stripMargin
// When executing this query
val
result
=
executeUsingCostPlannerOnly
(
query
)
val
shortestPathOperations
=
result
.
executionPlanDescription
().
find
(
"ShortestPath"
)
val
(
shortestPathWithPredicate
,
shortestPathWithoutPredicate
)
=
shortestPathOperations
.
partition
{
op
=>
op
.
variables
.
contains
(
"returnPath"
)
}
// Then the predicate should only be associated with the correct shortestPath pattern
shortestPathWithPredicate
.
size
should
be
(
1
)
shortestPathWithoutPredicate
.
size
should
be
(
1
)
val
withPredicateOther
=
shortestPathWithPredicate
.
head
.
arguments
.
map
(
_
.
toString
).
mkString
(
", "
)
val
withoutPredicateOther
=
shortestPathWithoutPredicate
.
head
.
arguments
.
map
(
_
.
toString
).
mkString
(
", "
)
withPredicateOther
should
include
(
"RelationshipFunction"
)
withoutPredicateOther
should
not
include
"RelationshipFunction"
}
def
executeUsingCostPlannerOnly
(
query
:
String
)
=
eengine
.
execute
(
s
"CYPHER planner=COST $query"
,
Map
.
empty
[
String
,
Any
])
match
{
case
e
:
ClosingExecutionResult
=>
RewindableExecutionResult
(
e
.
inner
)
}
}
This diff is collapsed.
Click to expand it.
community/cypher/cypher-compiler-3.2/src/main/scala/org/neo4j/cypher/internal/compiler/v3_2/planner/logical/steps/planShortestPaths.scala
+
7
-
1
View file @
76c0f0cb
...
...
@@ -36,8 +36,14 @@ case object planShortestPaths {
(
implicit
context
:
LogicalPlanningContext
)
:
LogicalPlan
=
{
val
variables
=
Set
(
shortestPaths
.
name
,
Some
(
shortestPaths
.
rel
.
name
)).
flatten
def
predicateAppliesToShortestPath
(
p
:
Predicate
)
=
// only select predicates related to this pattern (this is code in common with normal MATCH Pattern clauses)
p
.
hasDependenciesMet
(
variables
++
inner
.
availableSymbols
)
&&
// And filter with predicates that explicitly depend on shortestPath variables
(
p
.
dependencies
intersect
variables
).
nonEmpty
val
predicates
=
queryGraph
.
selections
.
predicates
.
collect
{
case
Predicate
(
dependencies
,
expr
:
Expression
)
if
(
dependencies
intersect
variables
).
nonEmpty
=>
expr
case
p
@
Predicate
(
_
,
expr
)
if
predicateAppliesToShortestPath
(
p
)
=>
expr
}.
toIndexedSeq
def
doesNotDependOnFullPath
(
predicate
:
Expression
)
:
Boolean
=
{
...
...
This diff is collapsed.
Click to expand it.
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment
Menu
Projects
Groups
Snippets
Help