-
Notifications
You must be signed in to change notification settings - Fork 2.3k
/
ProcedureExecutionResult.scala
105 lines (91 loc) · 4.65 KB
/
ProcedureExecutionResult.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
/*
* Copyright (c) 2002-2016 "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.compiler.v3_0.executionplan.procs
import java.util
import org.neo4j.cypher.internal.compiler.v3_0.codegen.ResultRowImpl
import org.neo4j.cypher.internal.compiler.v3_0.executionplan.{InternalQueryType, StandardInternalExecutionResult}
import org.neo4j.cypher.internal.compiler.v3_0.helpers.JavaResultValueConverter
import org.neo4j.cypher.internal.compiler.v3_0.planDescription.InternalPlanDescription
import org.neo4j.cypher.internal.compiler.v3_0.spi.{InternalResultVisitor, ProcedureSignature, QueryContext}
import org.neo4j.cypher.internal.compiler.v3_0.{ExecutionMode, InternalQueryStatistics, ProfileMode, TaskCloser}
import org.neo4j.cypher.internal.frontend.v3_0.ProfilerStatisticsNotReadyException
import scala.collection.JavaConverters._
/**
* Execution result of a Procedure
*
* @param context The QueryContext used to communicate with the kernel.
* @param taskCloser called when done with the result, cleans up resources.
* @param signature The signature of the procedure.
* @param args The argument to the procedure.
* @param executionPlanDescriptionGenerator Generator for the plan description of the result.
* @param executionMode The execution mode.
*/
class ProcedureExecutionResult[E <: Exception](context: QueryContext,
taskCloser: TaskCloser,
signature: ProcedureSignature,
args: Seq[Any],
executionPlanDescriptionGenerator: () => InternalPlanDescription,
val executionMode: ExecutionMode)
extends StandardInternalExecutionResult(context, Some(taskCloser)) {
// The signature mode is taking care of eagerization
private final val javaValues = new JavaResultValueConverter(isGraphKernelResultValue)
private final val executionResults = executeCall
private final val outputs = signature.outputSignature
protected def executeCall: Iterator[Array[AnyRef]] =
signature.mode.call(context, signature, args.map(javaValues.asDeepJavaResultValue))
override protected def createInner = new util.Iterator[util.Map[String, Any]]() {
override def next(): util.Map[String, Any] =
try { resultAsMap( executionResults.next( ) ) }
catch { case e: NoSuchElementException => success(); throw e }
override def hasNext: Boolean = if (executionResults.hasNext) true else { success(); false }
}
override def accept[EX <: Exception](visitor: InternalResultVisitor[EX]) = {
executionResults.foreach { res => visitor.visit(new ResultRowImpl(resultAsRefMap(res))) }
success()
close()
}
override def javaColumns: java.util.List[String] = signature.outputSignature.seq.map(_.name).asJava
// TODO Look into having the kernel track updates, rather than cypher middle-layers, only sensible way I can think
// of to get accurate stats for procedure code
override def queryStatistics() = context.getOptStatistics.getOrElse(InternalQueryStatistics())
override def executionType: InternalQueryType = signature.mode.queryType
private def resultAsMap(rowData: Array[AnyRef]): util.Map[String, Any] = {
val mapData = new util.HashMap[String, Any](rowData.length)
var i = 0
outputs.foreach { field =>
mapData.put(field.name, rowData(i))
i = i + 1
}
mapData
}
private def resultAsRefMap(rowData: Array[AnyRef]): util.Map[String, AnyRef] = {
val mapData = new util.HashMap[String, AnyRef](rowData.length)
var i = 0
outputs.foreach { field =>
mapData.put(field.name, rowData(i))
i = i + 1
}
mapData
}
override def executionPlanDescription(): InternalPlanDescription = executionMode match {
case ProfileMode if executionResults.hasNext => throw new ProfilerStatisticsNotReadyException()
case _ => executionPlanDescriptionGenerator()
}
}