Skip to content

Commit

Permalink
Show planner and version for procedure plan description
Browse files Browse the repository at this point in the history
  • Loading branch information
pontusmelke committed Sep 11, 2017
1 parent 7382005 commit 95da30a
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 65 deletions.
Expand Up @@ -19,6 +19,7 @@
*/ */
package org.neo4j.cypher.internal.compatibility.v3_3.runtime.executionplan.procs package org.neo4j.cypher.internal.compatibility.v3_3.runtime.executionplan.procs


import org.neo4j.cypher.CypherVersion
import org.neo4j.cypher.internal.InternalExecutionResult import org.neo4j.cypher.internal.InternalExecutionResult
import org.neo4j.cypher.internal.compatibility.v3_3.runtime._ import org.neo4j.cypher.internal.compatibility.v3_3.runtime._
import org.neo4j.cypher.internal.compatibility.v3_3.runtime.commands.convert.ExpressionConverters import org.neo4j.cypher.internal.compatibility.v3_3.runtime.commands.convert.ExpressionConverters
Expand Down Expand Up @@ -46,7 +47,7 @@ import org.neo4j.values.virtual.MapValue
* latter case we will have to resort to runtime type checking. * latter case we will have to resort to runtime type checking.
* *
* @param signature the signature of the procedure * @param signature the signature of the procedure
* @param argExprs the arguments to the procedure * @param argExprs the arguments to the procedure
*/ */
case class ProcedureCallExecutionPlan(signature: ProcedureSignature, case class ProcedureCallExecutionPlan(signature: ProcedureSignature,
argExprs: Seq[Expression], argExprs: Seq[Expression],
Expand All @@ -56,85 +57,93 @@ case class ProcedureCallExecutionPlan(signature: ProcedureSignature,
converter: ExpressionConverters) converter: ExpressionConverters)
extends ExecutionPlan { extends ExecutionPlan {


assert(resultSymbols.size == resultIndices.size) assert(resultSymbols.size == resultIndices.size)


private val resultMappings = resultSymbols.indices.map(i => { private val resultMappings = resultSymbols.indices.map(i => {
val r = resultIndices(i) val r = resultIndices(i)
(r._1, r._2, resultSymbols(i)._2) (r._1, r._2, resultSymbols(i)._2)
}) })


private val argExprCommands: Seq[expressions.Expression] = argExprs.map(converter.toCommandExpression) ++ private val argExprCommands: Seq[expressions.Expression] = argExprs.map(converter.toCommandExpression) ++
signature.inputSignature.drop(argExprs.size).flatMap(_.default).map(o => Literal(o.value)) signature.inputSignature.drop(argExprs.size).flatMap(_.default).map(o => Literal(o.value))


override def run(ctx: QueryContext, planType: ExecutionMode, params: MapValue): InternalExecutionResult = { override def run(ctx: QueryContext, planType: ExecutionMode, params: MapValue): InternalExecutionResult = {
val input = evaluateArguments(ctx, params) val input = evaluateArguments(ctx, params)


val taskCloser = new TaskCloser val taskCloser = new TaskCloser
taskCloser.addTask(ctx.transactionalContext.close) taskCloser.addTask(ctx.transactionalContext.close)


planType match { planType match {
case NormalMode => createNormalExecutionResult(ctx, taskCloser, input, planType) case NormalMode => createNormalExecutionResult(ctx, taskCloser, input, planType)
case ExplainMode => createExplainedExecutionResult(ctx, taskCloser, input, notifications) case ExplainMode => createExplainedExecutionResult(ctx, taskCloser, input, notifications)
case ProfileMode => createProfiledExecutionResult(ctx, taskCloser, input, planType) case ProfileMode => createProfiledExecutionResult(ctx, taskCloser, input, planType)
}
} }
}


private def createNormalExecutionResult(ctx: QueryContext, taskCloser: TaskCloser, private def createNormalExecutionResult(ctx: QueryContext, taskCloser: TaskCloser,
input: Seq[Any], planType: ExecutionMode) = { input: Seq[Any], planType: ExecutionMode) = {
val descriptionGenerator = () => createNormalPlan val descriptionGenerator = () => createNormalPlan
val callMode = ProcedureCallMode.fromAccessMode(signature.accessMode) val callMode = ProcedureCallMode.fromAccessMode(signature.accessMode)
new ProcedureExecutionResult(ctx, taskCloser, signature.name, callMode, input, new ProcedureExecutionResult(ctx, taskCloser, signature.name, callMode, input,
resultMappings, descriptionGenerator, planType) resultMappings, descriptionGenerator, planType)
} }


private def createExplainedExecutionResult(ctx: QueryContext, taskCloser: TaskCloser, input: Seq[Any], private def createExplainedExecutionResult(ctx: QueryContext, taskCloser: TaskCloser, input: Seq[Any],
notifications: Set[Notification]) = { notifications: Set[Notification]) = {
// close all statements // close all statements
taskCloser.close(success = true) taskCloser.close(success = true)
val callMode = ProcedureCallMode.fromAccessMode(signature.accessMode) val callMode = ProcedureCallMode.fromAccessMode(signature.accessMode)
val columns = signature.outputSignature.map(_.seq.map(_.name).toList).getOrElse(List.empty) val columns = signature.outputSignature.map(_.seq.map(_.name).toList).getOrElse(List.empty)
ExplainExecutionResult(columns.toArray, createNormalPlan, callMode.queryType, notifications) ExplainExecutionResult(columns.toArray, createNormalPlan, callMode.queryType, notifications)
} }


private def createProfiledExecutionResult(ctx: QueryContext, taskCloser: TaskCloser, private def createProfiledExecutionResult(ctx: QueryContext, taskCloser: TaskCloser,
input: Seq[Any], planType: ExecutionMode) = { input: Seq[Any], planType: ExecutionMode) = {
val rowCounter = Counter() val rowCounter = Counter()
val descriptionGenerator = createProfilePlanGenerator(rowCounter) val descriptionGenerator = createProfilePlanGenerator(rowCounter)
val callMode = ProcedureCallMode.fromAccessMode(signature.accessMode) val callMode = ProcedureCallMode.fromAccessMode(signature.accessMode)
new ProcedureExecutionResult(ctx, taskCloser, signature.name, callMode, input, new ProcedureExecutionResult(ctx, taskCloser, signature.name, callMode, input,
resultMappings, descriptionGenerator, planType) { resultMappings, descriptionGenerator, planType) {
override protected def executeCall: Iterator[Array[AnyRef]] = rowCounter.track(super.executeCall) override protected def executeCall: Iterator[Array[AnyRef]] = rowCounter.track(super.executeCall)
}
} }
}


private def evaluateArguments(ctx: QueryContext, params: MapValue): Seq[Any] = { private def evaluateArguments(ctx: QueryContext, params: MapValue): Seq[Any] = {
val state = new QueryState(ctx, ExternalCSVResource.empty, params) val state = new QueryState(ctx, ExternalCSVResource.empty, params)
argExprCommands.map(expr => ctx.asObject(expr.apply(ExecutionContext.empty)(state))) argExprCommands.map(expr => ctx.asObject(expr.apply(ExecutionContext.empty)(state)))
} }


private def createNormalPlan = private def createNormalPlan =
PlanDescriptionImpl(new Id, "ProcedureCall", NoChildren, PlanDescriptionImpl(new Id, "ProcedureCall", NoChildren,
Seq(createSignatureArgument, arguments,
Runtime(ProcedureRuntimeName.toTextOutput),
RuntimeImpl(ProcedureRuntimeName.name)),
resultSymbols.map(_._1).toSet resultSymbols.map(_._1).toSet
) )


private def createProfilePlanGenerator(rowCounter: Counter) = () => private def createProfilePlanGenerator(rowCounter: Counter) = () =>
PlanDescriptionImpl(new Id, "ProcedureCall", NoChildren, PlanDescriptionImpl(new Id, "ProcedureCall", NoChildren,
Seq(createSignatureArgument, DbHits(1), Rows(rowCounter.counted), arguments,
Runtime(ProcedureRuntimeName.toTextOutput), resultSymbols.map(_._1).toSet
RuntimeImpl(ProcedureRuntimeName.name)), )
resultSymbols.map(_._1).toSet
) private def arguments = Seq(createSignatureArgument,

Runtime(runtimeUsed.toTextOutput),
private def createSignatureArgument = RuntimeImpl(runtimeUsed.name),
Signature(signature.name, Seq.empty, resultSymbols) Planner(plannerUsed.toTextOutput),

PlannerImpl(plannerUsed.name),
override def notifications(planContext: PlanContext): Seq[InternalNotification] = Seq.empty Version(CypherVersion.default.name))
override def isPeriodicCommit: Boolean = false
override def runtimeUsed = ProcedureRuntimeName
override def isStale(lastTxId: () => Long, statistics: GraphStatistics) = false private def createSignatureArgument =
override def plannerUsed = ProcedurePlannerName Signature(signature.name, Seq.empty, resultSymbols)
}
override def notifications(planContext: PlanContext): Seq[InternalNotification] = Seq.empty

override def isPeriodicCommit: Boolean = false

override def runtimeUsed = ProcedureRuntimeName

override def isStale(lastTxId: () => Long, statistics: GraphStatistics) = false

override def plannerUsed = ProcedurePlannerName
}


Expand Up @@ -207,7 +207,7 @@ public void shouldShowInterpretedRuntimeInExecutionPlan()
} }


@Test @Test
public void shouldShowProcedureRuntimeInExecutionPlan() public void shouldShowArgumentsExecutionPlan()
{ {
// Given // Given
Result result = db.execute( "EXPLAIN CALL db.labels" ); Result result = db.execute( "EXPLAIN CALL db.labels" );
Expand All @@ -216,6 +216,26 @@ public void shouldShowProcedureRuntimeInExecutionPlan()
Map<String,Object> arguments = result.getExecutionPlanDescription().getArguments(); Map<String,Object> arguments = result.getExecutionPlanDescription().getArguments();


// Then // Then
assertThat( arguments.get( "version" ), equalTo( "3.3" ) );
assertThat( arguments.get( "planner" ), equalTo( "PROCEDURE" ) );
assertThat( arguments.get( "planner-impl" ), equalTo( "PROCEDURE" ) );
assertThat( arguments.get( "runtime" ), equalTo( "PROCEDURE" ) );
assertThat( arguments.get( "runtime-impl" ), equalTo( "PROCEDURE" ) );
}

@Test
public void shouldShowArgumentsInProfileExecutionPlan()
{
// Given
Result result = db.execute( "PROFILE CALL db.labels" );

// When
Map<String,Object> arguments = result.getExecutionPlanDescription().getArguments();

// Then
assertThat( arguments.get( "version" ), equalTo( "3.3" ) );
assertThat( arguments.get( "planner" ), equalTo( "PROCEDURE" ) );
assertThat( arguments.get( "planner-impl" ), equalTo( "PROCEDURE" ) );
assertThat( arguments.get( "runtime" ), equalTo( "PROCEDURE" ) ); assertThat( arguments.get( "runtime" ), equalTo( "PROCEDURE" ) );
assertThat( arguments.get( "runtime-impl" ), equalTo( "PROCEDURE" ) ); assertThat( arguments.get( "runtime-impl" ), equalTo( "PROCEDURE" ) );
} }
Expand Down

0 comments on commit 95da30a

Please sign in to comment.