Skip to content

Commit

Permalink
Merge pull request #9426 from pontusmelke/3.3-logical-plan-cut
Browse files Browse the repository at this point in the history
Move code from one place to another
  • Loading branch information
systay committed May 30, 2017
2 parents 28e7dc1 + c743e2f commit 0d953c7
Show file tree
Hide file tree
Showing 688 changed files with 3,623 additions and 4,684 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,8 @@ package org.neo4j.cypher.internal.compiler.v3_3

import java.time.Clock

import org.neo4j.cypher.internal.compiler.v3_3.executionplan.{PlanFingerprint, PlanFingerprintReference}
import org.neo4j.cypher.internal.compiler.v3_3.helpers.RuntimeTypeConverter
import org.neo4j.cypher.internal.compiler.v3_3.phases.CompilerContext
import org.neo4j.cypher.internal.compiler.v3_3.planner.logical.{Metrics, MetricsFactory, QueryGraphSolver}
import org.neo4j.cypher.internal.compiler.v3_3.planner.logical.{ExpressionEvaluator, Metrics, MetricsFactory, QueryGraphSolver}
import org.neo4j.cypher.internal.compiler.v3_3.spi.PlanContext
import org.neo4j.cypher.internal.frontend.v3_3.InputPosition
import org.neo4j.cypher.internal.frontend.v3_3.phases.{BaseContext, CompilationPhaseTracer, InternalNotificationLogger, Monitors}
Expand All @@ -37,38 +35,10 @@ trait ContextCreator[Context <: BaseContext] {
debugOptions: Set[String],
offset: Option[InputPosition],
monitors: Monitors,
createFingerprintReference: Option[PlanFingerprint] => PlanFingerprintReference,
typeConverter: RuntimeTypeConverter,
metricsFactory: MetricsFactory,
queryGraphSolver: QueryGraphSolver,
config: CypherCompilerConfiguration,
updateStrategy: UpdateStrategy,
clock: Clock): Context
}

object CommunityContextCreator extends ContextCreator[CompilerContext] {
override def create(tracer: CompilationPhaseTracer,
notificationLogger: InternalNotificationLogger,
planContext: PlanContext,
queryText: String,
debugOptions: Set[String],
offset: Option[InputPosition],
monitors: Monitors,
createFingerprintReference: Option[PlanFingerprint] => PlanFingerprintReference,
typeConverter: RuntimeTypeConverter,
metricsFactory: MetricsFactory,
queryGraphSolver: QueryGraphSolver,
config: CypherCompilerConfiguration,
updateStrategy: UpdateStrategy,
clock: Clock): CompilerContext = {
val exceptionCreator = new SyntaxExceptionCreator(queryText, offset)

val metrics: Metrics = if (planContext == null)
null
else
metricsFactory.newMetrics(planContext.statistics)

new CompilerContext(exceptionCreator, tracer, notificationLogger, planContext, typeConverter, createFingerprintReference,
monitors, metrics, queryGraphSolver, config, updateStrategy, debugOptions, clock)
}
}
clock: Clock,
evaluator: ExpressionEvaluator): Context
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,73 +21,31 @@ package org.neo4j.cypher.internal.compiler.v3_3

import java.time.Clock

import org.neo4j.cypher.internal.compiler.v3_3.executionplan._
import org.neo4j.cypher.internal.compiler.v3_3.executionplan.procs.ProcedureCallOrSchemaCommandPlanBuilder
import org.neo4j.cypher.internal.compiler.v3_3.helpers.RuntimeTypeConverter
import org.neo4j.cypher.internal.compiler.v3_3.phases.{CompilerContext, _}
import org.neo4j.cypher.internal.compiler.v3_3.planner.logical._
import org.neo4j.cypher.internal.compiler.v3_3.planner.logical.plans.LogicalPlan
import org.neo4j.cypher.internal.compiler.v3_3.planner.logical.plans.rewriter.PlanRewriter
import org.neo4j.cypher.internal.compiler.v3_3.planner.{CheckForUnresolvedTokens, ResolveTokens}
import org.neo4j.cypher.internal.compiler.v3_3.spi.PlanContext
import org.neo4j.cypher.internal.frontend.v3_3.InputPosition
import org.neo4j.cypher.internal.frontend.v3_3.ast.Statement
import org.neo4j.cypher.internal.frontend.v3_3.ast.rewriters.ASTRewriter
import org.neo4j.cypher.internal.frontend.v3_3.helpers.rewriting.RewriterStepSequencer
import org.neo4j.cypher.internal.frontend.v3_3.phases._
import org.neo4j.cypher.internal.ir.v3_3.UnionQuery

case class CypherCompiler[Context <: CompilerContext](createExecutionPlan: Transformer[Context, CompilationState, CompilationState],
astRewriter: ASTRewriter,
cacheAccessor: CacheAccessor[Statement, ExecutionPlan],
planCacheFactory: () => LFUCache[Statement, ExecutionPlan],
cacheMonitor: CypherCacheFlushingMonitor[CacheAccessor[Statement, ExecutionPlan]],
monitors: Monitors,
sequencer: String => RewriterStepSequencer,
createFingerprintReference: Option[PlanFingerprint] => PlanFingerprintReference,
typeConverter: RuntimeTypeConverter,
metricsFactory: MetricsFactory,
queryGraphSolver: QueryGraphSolver,
config: CypherCompilerConfiguration,
updateStrategy: UpdateStrategy,
clock: Clock,
contextCreation: ContextCreator[Context]) {

def planQuery(queryText: String,
context: PlanContext,
notificationLogger: InternalNotificationLogger,
plannerName: String = "",
debugOptions: Set[String] = Set.empty,
offset: Option[InputPosition] = None): (ExecutionPlan, Map[String, Any]) = {
val state = parseQuery(queryText, queryText, notificationLogger, plannerName, debugOptions, None, CompilationPhaseTracer.NO_TRACING)
planPreparedQuery(state, notificationLogger, context, debugOptions, offset, CompilationPhaseTracer.NO_TRACING)
}
case class CypherCompiler[Context <: CompilerContext](astRewriter: ASTRewriter,
monitors: Monitors,
sequencer: String => RewriterStepSequencer,
metricsFactory: MetricsFactory,
config: CypherCompilerConfiguration,
updateStrategy: UpdateStrategy,
clock: Clock,
contextCreation: ContextCreator[Context]) {
def normalizeQuery(state: BaseState, context: Context): BaseState = prepareForCaching.transform(state, context)

def planPreparedQuery(state: BaseState,
notificationLogger: InternalNotificationLogger,
planContext: PlanContext,
debugOptions: Set[String],
offset: Option[InputPosition] = None,
tracer: CompilationPhaseTracer): (ExecutionPlan, Map[String, Any]) = {
val context: Context = contextCreation.create(tracer, notificationLogger, planContext, state.queryText,
debugOptions, state.startPosition, monitors, createFingerprintReference, typeConverter, metricsFactory,
queryGraphSolver, config, updateStrategy, clock)
val preparedCompilationState = prepareForCaching.transform(state, context)
val cache = provideCache(cacheAccessor, cacheMonitor, planContext)
val isStale = (plan: ExecutionPlan) => plan.isStale(planContext.txIdProvider, planContext.statistics)

def createPlan(): ExecutionPlan = {
val result: CompilationState = planAndCreateExecPlan.transform(preparedCompilationState, context)
result.executionPlan
}

val executionPlan = if (debugOptions.isEmpty)
cache.getOrElseUpdate(state.statement(), state.queryText, isStale, createPlan())._1
else
createPlan()
context: Context): LogicalPlanState = planPipeLine.transform(state, context)

(executionPlan, preparedCompilationState.extractedParams())
}

def parseQuery(queryText: String,
rawQueryText: String,
Expand All @@ -97,11 +55,10 @@ case class CypherCompiler[Context <: CompilerContext](createExecutionPlan: Trans
offset: Option[InputPosition],
tracer: CompilationPhaseTracer): BaseState = {
val plannerName = PlannerNameFor(plannerNameText)
val startState = CompilationState(queryText, offset, plannerName)
val startState = LogicalPlanState(queryText, offset, plannerName)
//TODO: these nulls are a short cut
val context = contextCreation.create(tracer, notificationLogger, planContext = null, rawQueryText, debugOptions,
offset, monitors, createFingerprintReference, typeConverter, metricsFactory, queryGraphSolver, config,
updateStrategy, clock)
offset, monitors, metricsFactory, null, config, updateStrategy, clock, evaluator = null)
CompilationPhases.parsing(sequencer).transform(startState, context)
}

Expand All @@ -110,39 +67,28 @@ case class CypherCompiler[Context <: CompilerContext](createExecutionPlan: Trans
ProcedureDeprecationWarnings andThen
ProcedureWarnings

val irConstruction: Transformer[CompilerContext, BaseState, CompilationState] =
val irConstruction: Transformer[CompilerContext, BaseState, LogicalPlanState] =
ResolveTokens andThen
CreatePlannerQuery.adds(CompilationContains[UnionQuery]) andThen
OptionalMatchRemover

val costBasedPlanning =
val costBasedPlanning: Transformer[CompilerContext, LogicalPlanState, LogicalPlanState] =
QueryPlanner().adds(CompilationContains[LogicalPlan]) andThen
PlanRewriter(sequencer) andThen
If((s: CompilationState) => s.unionQuery.readOnly) (
If((s: LogicalPlanState) => s.unionQuery.readOnly) (
CheckForUnresolvedTokens
)

val standardPipeline: Transformer[Context, BaseState, CompilationState] =
val standardPipeline: Transformer[Context, BaseState, LogicalPlanState] =
CompilationPhases.lateAstRewriting andThen
irConstruction andThen
costBasedPlanning andThen
createExecutionPlan.adds(CompilationContains[ExecutionPlan])
costBasedPlanning

val planAndCreateExecPlan: Transformer[Context, BaseState, CompilationState] =
val planPipeLine: Transformer[Context, BaseState, LogicalPlanState] =
ProcedureCallOrSchemaCommandPlanBuilder andThen
If((s: CompilationState) => s.maybeExecutionPlan.isEmpty)(
If((s: LogicalPlanState) => s.maybeLogicalPlan.isEmpty)(
standardPipeline
)

private def provideCache(cacheAccessor: CacheAccessor[Statement, ExecutionPlan],
monitor: CypherCacheFlushingMonitor[CacheAccessor[Statement, ExecutionPlan]],
planContext: PlanContext): QueryCache[Statement, ExecutionPlan] =
planContext.getOrCreateFromSchemaState(cacheAccessor, {
monitor.cacheFlushDetected(cacheAccessor)
val lRUCache = planCacheFactory()
new QueryCache(cacheAccessor, lRUCache)
})

}

case class CypherCompilerConfiguration(queryCacheSize: Int,
Expand All @@ -155,22 +101,3 @@ case class CypherCompilerConfiguration(queryCacheSize: Int,
errorIfShortestPathHasCommonNodesAtRuntime: Boolean,
legacyCsvQuoteEscaping: Boolean,
nonIndexedLabelWarningThreshold: Long)


trait CypherCacheFlushingMonitor[T] {
def cacheFlushDetected(justBeforeKey: T) {}
}

trait CypherCacheHitMonitor[T] {
def cacheHit(key: T) {}
def cacheMiss(key: T) {}
def cacheDiscard(key: T, userKey: String) {}
}

trait InfoLogger {
def info(message: String)
}

trait CypherCacheMonitor[T, E] extends CypherCacheHitMonitor[T] with CypherCacheFlushingMonitor[E]

trait AstCacheMonitor extends CypherCacheMonitor[Statement, CacheAccessor[Statement, ExecutionPlan]]
Original file line number Diff line number Diff line change
Expand Up @@ -21,71 +21,27 @@ package org.neo4j.cypher.internal.compiler.v3_3

import java.time.Clock

import org.neo4j.cypher.internal.compiler.v3_3.executionplan._
import org.neo4j.cypher.internal.compiler.v3_3.helpers.RuntimeTypeConverter
import org.neo4j.cypher.internal.compiler.v3_3.phases.{CompilationState, CompilerContext}
import org.neo4j.cypher.internal.compiler.v3_3.phases.{CompilerContext, LogicalPlanState}
import org.neo4j.cypher.internal.compiler.v3_3.planner.logical._
import org.neo4j.cypher.internal.compiler.v3_3.planner.logical.idp._
import org.neo4j.cypher.internal.frontend.v3_3.ast.Statement
import org.neo4j.cypher.internal.frontend.v3_3.ast.rewriters.{ASTRewriter, IfNoParameter}
import org.neo4j.cypher.internal.frontend.v3_3.helpers.rewriting.RewriterStepSequencer
import org.neo4j.cypher.internal.frontend.v3_3.phases.{Monitors, Transformer}

class CypherCompilerFactory[C <: CompilerContext, T <: Transformer[C, CompilationState, CompilationState]] {
class CypherCompilerFactory[C <: CompilerContext, T <: Transformer[C, LogicalPlanState, LogicalPlanState]] {
val monitorTag = "cypher3.3"

def costBasedCompiler(config: CypherCompilerConfiguration,
clock: Clock,
monitors: Monitors, logger: InfoLogger,
monitors: Monitors,
rewriterSequencer: (String) => RewriterStepSequencer,
plannerName: Option[CostBasedPlannerName],
runtimeName: Option[RuntimeName],
updateStrategy: Option[UpdateStrategy],
typeConverter: RuntimeTypeConverter,
runtimeBuilder: RuntimeBuilder[T],
contextCreator: ContextCreator[C]): CypherCompiler[C] = {
val rewriter = new ASTRewriter(rewriterSequencer, IfNoParameter)
val metricsFactory = CachedMetricsFactory(SimpleMetricsFactory)

// Pick runtime based on input
val runtimePipeline = runtimeBuilder.create(runtimeName, config.useErrorsOverWarnings)

val planner = plannerName.getOrElse(CostBasedPlannerName.default)
val queryGraphSolver = createQueryGraphSolver(planner, monitors, config)

val actualUpdateStrategy: UpdateStrategy = updateStrategy.getOrElse(defaultUpdateStrategy)

val createFingerprintReference: (Option[PlanFingerprint]) => PlanFingerprintReference =
new PlanFingerprintReference(clock, config.queryPlanTTL, config.statsDivergenceThreshold, _)
val planCacheFactory = () => new LFUCache[Statement, ExecutionPlan](config.queryCacheSize)
monitors.addMonitorListener(logStalePlanRemovalMonitor(logger), monitorTag)
val cacheMonitor = monitors.newMonitor[AstCacheMonitor](monitorTag)
val cache = new MonitoringCacheAccessor[Statement, ExecutionPlan](cacheMonitor)

CypherCompiler(runtimePipeline, rewriter, cache, planCacheFactory, cacheMonitor, monitors, rewriterSequencer,
createFingerprintReference, typeConverter, metricsFactory, queryGraphSolver, config, actualUpdateStrategy, clock,
contextCreator)
}

def createQueryGraphSolver(n: CostBasedPlannerName, monitors: Monitors, config: CypherCompilerConfiguration): QueryGraphSolver = n match {
case IDPPlannerName =>
val monitor = monitors.newMonitor[IDPQueryGraphSolverMonitor]()
val solverConfig = new ConfigurableIDPSolverConfig(
maxTableSize = config.idpMaxTableSize,
iterationDurationLimit = config.idpIterationDuration
)
val singleComponentPlanner = SingleComponentPlanner(monitor, solverConfig)
IDPQueryGraphSolver(singleComponentPlanner, cartesianProductsOrValueJoins, monitor)

case DPPlannerName =>
val monitor = monitors.newMonitor[IDPQueryGraphSolverMonitor]()
val singleComponentPlanner = SingleComponentPlanner(monitor, DPSolverConfig)
IDPQueryGraphSolver(singleComponentPlanner, cartesianProductsOrValueJoins, monitor)
}

private def logStalePlanRemovalMonitor(log: InfoLogger) = new AstCacheMonitor {
override def cacheDiscard(key: Statement, userKey: String) {
log.info(s"Discarded stale query from the query cache: $userKey")
}
CypherCompiler( rewriter, monitors, rewriterSequencer,
metricsFactory, config, actualUpdateStrategy, clock, contextCreator)
}
}

0 comments on commit 0d953c7

Please sign in to comment.