Skip to content

Commit

Permalink
Warn users when using morsel runtime
Browse files Browse the repository at this point in the history
  • Loading branch information
pontusmelke committed Nov 15, 2017
1 parent 47b6fe6 commit fff8ae1
Show file tree
Hide file tree
Showing 8 changed files with 50 additions and 17 deletions.
Expand Up @@ -265,6 +265,8 @@ enum Statement implements Status
"This query is not supported by the chosen runtime." ),
FeatureDeprecationWarning( ClientNotification,
"This feature is deprecated and will be removed in future versions." ),
ExperimentalFeature( ClientNotification,
"This feature is experimental and should not be used in production systems." ),
JoinHintUnsupportedWarning( ClientNotification,
"Queries with join hints are not supported by the RULE planner." ),

Expand Down
Expand Up @@ -21,14 +21,14 @@ package org.neo4j.cypher.internal

import java.time.Clock

import org.neo4j.cypher.internal.util.v3_4.InputPosition
import org.neo4j.cypher.internal.compiler.v3_4.CypherCompilerConfiguration
import org.neo4j.cypher.internal.frontend.v3_4.helpers.fixedPoint
import org.neo4j.cypher.internal.frontend.v3_4.phases.CompilationPhaseTracer
import org.neo4j.cypher.internal.util.v3_4.InputPosition
import org.neo4j.cypher.{InvalidArgumentException, SyntaxException, exceptionHandler, _}
import org.neo4j.graphdb.factory.GraphDatabaseSettings
import org.neo4j.graphdb.impl.notification.NotificationCode.{CREATE_UNIQUE_UNAVAILABLE_FALLBACK, RULE_PLANNER_UNAVAILABLE_FALLBACK, START_DEPRECATED, START_UNAVAILABLE_FALLBACK}
import org.neo4j.graphdb.impl.notification.NotificationDetail.Factory.startDeprecated
import org.neo4j.graphdb.impl.notification.NotificationDetail.Factory.message
import org.neo4j.kernel.GraphDatabaseQueryService
import org.neo4j.kernel.api.KernelAPI
import org.neo4j.kernel.configuration.Config
Expand Down Expand Up @@ -202,7 +202,7 @@ class CompilerEngineDelegator(graph: GraphDatabaseQueryService,

private def createStartDeprecatedNotification(ex: util.v3_4.SyntaxException, preParsedQuery: PreParsedQuery) = {
val pos = convertInputPosition(ex.pos.getOrElse(preParsedQuery.offset))
START_DEPRECATED.notification(pos, startDeprecated(ex.getMessage))
START_DEPRECATED.notification(pos, message("START", ex.getMessage))
}

private def createUniqueNotification(ex: util.v3_4.SyntaxException, preParsedQuery: PreParsedQuery) = {
Expand Down
Expand Up @@ -19,8 +19,8 @@
*/
package org.neo4j.cypher.internal.compatibility.v3_4.runtime.helpers

import org.neo4j.cypher.internal.util.v3_4.InputPosition
import org.neo4j.cypher.internal.frontend.v3_4.notification.{DeprecatedPlannerNotification, InternalNotification, PlannerUnsupportedNotification, RuntimeUnsupportedNotification, _}
import org.neo4j.cypher.internal.util.v3_4.InputPosition
import org.neo4j.graphdb
import org.neo4j.graphdb.impl.notification.{NotificationCode, NotificationDetail}

Expand All @@ -30,7 +30,7 @@ object InternalWrapping {

def asKernelNotification(offset: Option[InputPosition])(notification: InternalNotification) = notification match {
case DeprecatedStartNotification(pos, message) =>
NotificationCode.START_DEPRECATED.notification(pos.withOffset(offset).asInputPosition, NotificationDetail.Factory.startDeprecated(message))
NotificationCode.START_DEPRECATED.notification(pos.withOffset(offset).asInputPosition, NotificationDetail.Factory.message("START", message))
case CartesianProductNotification(pos, variables) =>
NotificationCode.CARTESIAN_PRODUCT.notification(pos.withOffset(offset).asInputPosition, NotificationDetail.Factory.cartesianProduct(variables.asJava))
case LengthOnNonPathNotification(pos) =>
Expand Down Expand Up @@ -75,6 +75,8 @@ object InternalWrapping {
NotificationCode.DEPRECATED_PLANNER.notification(graphdb.InputPosition.empty)
case ProcedureWarningNotification(pos, name, warning) =>
NotificationCode.PROCEDURE_WARNING.notification(pos.withOffset(offset).asInputPosition, NotificationDetail.Factory.procedureWarning(name, warning))
case ExperimentalFeatureNotification(msg) =>
NotificationCode.EXPERIMENTAL_FEATURE.notification(graphdb.InputPosition.empty, NotificationDetail.Factory.message("MORSEL", msg))
}

private implicit class ConvertibleCompilerInputPosition(pos: InputPosition) {
Expand Down
Expand Up @@ -68,3 +68,5 @@ case class DeprecatedVarLengthBindingNotification(position: InputPosition, varia
case class DeprecatedRelTypeSeparatorNotification(position: InputPosition) extends InternalNotification

case object DeprecatedPlannerNotification extends InternalNotification

case class ExperimentalFeatureNotification(msg: String) extends InternalNotification
Expand Up @@ -189,8 +189,11 @@ public enum NotificationCode
START_DEPRECATED(
SeverityLevel.WARNING,
Status.Statement.FeatureDeprecationWarning,
"START has been deprecated and will be removed in a future version."
);
"START has been deprecated and will be removed in a future version."),
EXPERIMENTAL_FEATURE(
SeverityLevel.WARNING,
Status.Statement.ExperimentalFeature,
"You are using an experimental feature");

private final Status status;
private final String description;
Expand Down
Expand Up @@ -102,14 +102,14 @@ public static NotificationDetail indexSeekOrScan( Set<String> labels )
return createNotificationDetail( labels, "indexed label", "indexed labels" );
}

public static NotificationDetail startDeprecated( String message )
public static NotificationDetail message( String name, String message )
{
return new NotificationDetail()
{
@Override
public String name()
{
return "START";
return name;
}

@Override
Expand Down
Expand Up @@ -56,5 +56,18 @@ class MorselRuntimeAcceptanceTest extends ExecutionEngineFunSuite {
result.getExecutionPlanDescription.getArguments.get("runtime") should not equal "MORSEL"
}

test("should warn that morsels are experimental") {
//Given
import scala.collection.JavaConverters._

val result = graph.execute("CYPHER runtime=morsel EXPLAIN MATCH (n) RETURN n")

// When (exhaust result)
val notifications = result.getNotifications.asScala.toSet

//Then
notifications.head.getDescription should equal("You are using an experimental feature (use the morsel runtime at " +
"your own peril, not recommended to be run on production systems)")

}
}
Expand Up @@ -24,14 +24,15 @@ import org.neo4j.cypher.internal.compatibility.v3_4.runtime._
import org.neo4j.cypher.internal.compatibility.v3_4.runtime.compiled.EnterpriseRuntimeContext
import org.neo4j.cypher.internal.compatibility.v3_4.runtime.executionplan.StandardInternalExecutionResult.IterateByAccepting
import org.neo4j.cypher.internal.compatibility.v3_4.runtime.executionplan.{NewRuntimeSuccessRateMonitor, StandardInternalExecutionResult}
import org.neo4j.cypher.internal.compatibility.v3_4.runtime.helpers.InternalWrapping.asKernelNotification
import org.neo4j.cypher.internal.compatibility.v3_4.runtime.phases.CompilationState
import org.neo4j.cypher.internal.compatibility.v3_4.runtime.slotted.expressions.SlottedExpressionConverters
import org.neo4j.cypher.internal.compiler.v3_4.phases.LogicalPlanState
import org.neo4j.cypher.internal.compiler.v3_4.planner.CantCompileQueryException
import org.neo4j.cypher.internal.frontend.v3_4.PlannerName
import org.neo4j.cypher.internal.frontend.v3_4.notification.InternalNotification
import org.neo4j.cypher.internal.frontend.v3_4.notification.{ExperimentalFeatureNotification, InternalNotification}
import org.neo4j.cypher.internal.frontend.v3_4.phases.CompilationPhaseTracer.CompilationPhase
import org.neo4j.cypher.internal.frontend.v3_4.phases.{CompilationPhaseTracer, Condition, Phase}
import org.neo4j.cypher.internal.frontend.v3_4.phases.{CompilationPhaseTracer, Condition, InternalNotificationLogger, Phase}
import org.neo4j.cypher.internal.planner.v3_4.spi.{GraphStatistics, PlanContext}
import org.neo4j.cypher.internal.runtime.interpreted.commands.convert.{CommunityExpressionConverter, ExpressionConverters}
import org.neo4j.cypher.internal.runtime.planDescription.InternalPlanDescription.Arguments.{Runtime, RuntimeImpl}
Expand Down Expand Up @@ -63,8 +64,11 @@ object BuildVectorizedExecutionPlan extends Phase[EnterpriseRuntimeContext, Logi
else context.dispatcher
val fieldNames = from.statement().returnColumns.toArray

context.notificationLogger.log(
ExperimentalFeatureNotification("use the morsel runtime at your own peril, " +
"not recommended to be run on production systems"))
val execPlan = VectorizedExecutionPlan(from.plannerName, operators, pipelines, physicalPlan, fieldNames,
dispatcher)
dispatcher, context.notificationLogger)
runtimeSuccessRateMonitor.newPlanSeen(from.logicalPlan)
new CompilationState(from, Some(execPlan))
} catch {
Expand All @@ -88,7 +92,8 @@ object BuildVectorizedExecutionPlan extends Phase[EnterpriseRuntimeContext, Logi
pipelineInformation: Map[LogicalPlanId, PipelineInformation],
physicalPlan: LogicalPlan,
fieldNames: Array[String],
dispatcher: Dispatcher) extends executionplan.ExecutionPlan {
dispatcher: Dispatcher,
notificationLogger: InternalNotificationLogger) extends executionplan.ExecutionPlan {
override def run(queryContext: QueryContext, planType: ExecutionMode, params: MapValue): InternalExecutionResult = {
val taskCloser = new TaskCloser
taskCloser.addTask(queryContext.transactionalContext.close)
Expand All @@ -97,9 +102,15 @@ object BuildVectorizedExecutionPlan extends Phase[EnterpriseRuntimeContext, Logi
.addArgument(Runtime(MorselRuntimeName.toTextOutput))
.addArgument(RuntimeImpl(MorselRuntimeName.name))

new VectorizedOperatorExecutionResult(operators, physicalPlan, planDescription, queryContext,
params, fieldNames, taskCloser, dispatcher)
}
if (planType == ExplainMode) {
//close all statements
taskCloser.close(success = true)
ExplainExecutionResult(fieldNames, planDescription(), READ_ONLY,
notificationLogger.notifications.map(asKernelNotification(notificationLogger.offset)))
} else new VectorizedOperatorExecutionResult(operators, physicalPlan, planDescription, queryContext,
params, fieldNames, taskCloser, dispatcher)
}


override def isPeriodicCommit: Boolean = false

Expand Down Expand Up @@ -133,7 +144,7 @@ class VectorizedOperatorExecutionResult(operators: Pipeline,

override def executionMode: ExecutionMode = NormalMode

override def notifications: Iterable[Notification] = ???
override def notifications: Iterable[Notification] = Iterable.empty[Notification]

override def withNotifications(notification: Notification*): InternalExecutionResult = this
}
Expand Down

0 comments on commit fff8ae1

Please sign in to comment.