Skip to content

Commit

Permalink
Made CompiledPlans the default
Browse files Browse the repository at this point in the history
- Fixed some bugs in compiled plans showing up when running all tests
- Forced some tests to use intepreted runtime which uses `PROFILE` and `dumpToString`
  • Loading branch information
pontusmelke committed Apr 30, 2015
1 parent 5fed9ff commit 40ff6cd
Show file tree
Hide file tree
Showing 69 changed files with 337 additions and 147 deletions.
1 change: 1 addition & 0 deletions advanced/neo4j-advanced/LICENSES.txt
Expand Up @@ -3,6 +3,7 @@ libraries. For an overview of the licenses see the NOTICE.txt file.

------------------------------------------------------------------------------
Apache Software License, Version 2.0
Apache Commons Lang
ConcurrentLinkedHashMap
Lucene Core
opencsv
Expand Down
1 change: 1 addition & 0 deletions advanced/neo4j-advanced/NOTICE.txt
Expand Up @@ -26,6 +26,7 @@ Third-party licenses
--------------------

Apache Software License, Version 2.0
Apache Commons Lang
ConcurrentLinkedHashMap
Lucene Core
opencsv
Expand Down
1 change: 1 addition & 0 deletions advanced/server-advanced/LICENSES.txt
Expand Up @@ -4,6 +4,7 @@ libraries. For an overview of the licenses see the NOTICE.txt file.
------------------------------------------------------------------------------
Apache Software License, Version 2.0
Apache Commons Configuration
Apache Commons Lang
Commons BeanUtils
Commons Digester
Commons IO
Expand Down
1 change: 1 addition & 0 deletions advanced/server-advanced/NOTICE.txt
Expand Up @@ -27,6 +27,7 @@ Third-party licenses

Apache Software License, Version 2.0
Apache Commons Configuration
Apache Commons Lang
Commons BeanUtils
Commons Digester
Commons IO
Expand Down
23 changes: 18 additions & 5 deletions community/NOTICE.txt
@@ -1,6 +1,6 @@
Neo4j
Copyright © 2002-2015 Network Engine for Objects in Lund AB (referred to
in this notice as Neo Technology)
in this notice as "Neo Technology")
[http://neotechnology.com]

This product includes software ("Software") developed by Neo Technology.
Expand All @@ -20,9 +20,22 @@ such Commercial Agreement will supersede the GPL and you may use the
software solely pursuant to the terms of the relevant Commercial
Agreement.

Third party libraries
---------------------
Full license texts are found in LICENSES.txt.

See the NOTICE.txt and LICENSES.txt files in the subdirectories for
information on included third party software.
Third-party licenses
--------------------

Apache Software License, Version 2.0
Apache Commons Lang
ConcurrentLinkedHashMap
Lucene Core
opencsv
parboiled-core
parboiled-scala

BSD - Scala License
Scala Library

BSD License
Scala Compiler

Expand Up @@ -890,7 +890,6 @@ RETURN a.name""")
result.toSet should equal (Set(Map("id(n)" -> 0, "id(b)" -> 1)))
}


test("should get all nodes") {
val a = createNode()
val b = createNode()
Expand Down
Expand Up @@ -386,12 +386,11 @@ return coalesce(a.title, a.name)""")
result.length() should equal(2)
}

//TODO change to executeWithAllPlannersAndRuntime when dumpToString is supported
test("array prop output") {
createNode("foo" -> Array(1, 2, 3))

//cannot use executeWithAllPlannersAndRuntimes since we use the statement to look up n
//and executeWithAllPlannersAndRuntimes uses a mocked statement
val result = eengine.execute("match n return n").dumpToString()
val result = executeWithAllPlannersOnInterpretedRuntime("match n return n").dumpToString()

result should include ("[1,2,3]")
}
Expand Down
1 change: 1 addition & 0 deletions community/cypher/cypher-compiler-2.3/LICENSES.txt
Expand Up @@ -3,6 +3,7 @@ libraries. For an overview of the licenses see the NOTICE.txt file.

------------------------------------------------------------------------------
Apache Software License, Version 2.0
Apache Commons Lang
ConcurrentLinkedHashMap
parboiled-core
parboiled-scala
Expand Down
1 change: 1 addition & 0 deletions community/cypher/cypher-compiler-2.3/NOTICE.txt
Expand Up @@ -26,6 +26,7 @@ Third-party licenses
--------------------

Apache Software License, Version 2.0
Apache Commons Lang
ConcurrentLinkedHashMap
parboiled-core
parboiled-scala
Expand Down
5 changes: 5 additions & 0 deletions community/cypher/cypher-compiler-2.3/pom.xml
Expand Up @@ -173,6 +173,11 @@
<artifactId>concurrentlinkedhashmap-lru</artifactId>
</dependency>

<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>

</dependencies>

</project>
Expand Up @@ -20,7 +20,8 @@
package org.neo4j.cypher.internal.compiler.v2_3.birk;

import java.lang.reflect.Array;
import java.util.Collections;
import java.util.ArrayList;
import java.util.List;

import org.neo4j.cypher.internal.compiler.v2_3.CypherTypeException;

Expand Down Expand Up @@ -51,12 +52,39 @@ public static Object add( Object lhs, Object rhs )
return String.valueOf( lhs ) + String.valueOf( rhs );
}

//List addition
if (lhs instanceof List<?> && rhs instanceof List<?>)
{
List<?> lhsList = (List<?>) lhs;
List<?> rhsList = (List<?>) rhs;
List<Object> result = new ArrayList<>( lhsList.size() + rhsList.size() );
result.addAll( lhsList );
result.addAll( rhsList );
return result;
}
else if (lhs instanceof List<?>)
{
List<?> lhsList = (List<?>) lhs;
List<Object> result = new ArrayList<>( lhsList.size() + 1 );
result.addAll( lhsList );
result.add(rhs);
return result;
}
else if (rhs instanceof List<?>)
{
List<?> rhsList = (List<?>) rhs;
List<Object> result = new ArrayList<>( rhsList.size() + 1 );
result.add(lhs);
result.addAll( rhsList );
return result;
}

// array addition
Class<?> lhsClass = lhs.getClass();
Class<?> rhsClass = rhs.getClass();
if ( lhsClass.isArray() && rhsClass.isArray())
{
return addArrays(lhs, rhs);
return addArrays( lhs, rhs );
}
else if ( lhsClass.isArray() )
{
Expand Down
Expand Up @@ -41,10 +41,9 @@
import javax.tools.StandardLocation;
import javax.tools.ToolProvider;

import sun.tools.java.CompilerError;

import org.neo4j.cypher.internal.compiler.v2_3.ExecutionMode;
import org.neo4j.cypher.internal.compiler.v2_3.executionplan.CompletionListener;
import org.neo4j.cypher.internal.compiler.v2_3.TaskCloser;
import org.neo4j.cypher.internal.compiler.v2_3.executionplan.InternalExecutionResult;
import org.neo4j.cypher.internal.compiler.v2_3.planDescription.InternalPlanDescription;
import org.neo4j.cypher.internal.compiler.v2_3.planner.CantCompileQueryException;
Expand Down Expand Up @@ -99,13 +98,13 @@ public static Class<InternalExecutionResult> compile( String className, String c
return clazz;
}

public static InternalExecutionResult newInstance( Class<InternalExecutionResult> clazz, CompletionListener completion, Statement statement,
public static InternalExecutionResult newInstance( Class<InternalExecutionResult> clazz, TaskCloser closer, Statement statement,
GraphDatabaseService db, ExecutionMode executionMode, InternalPlanDescription description, Map<String, Object> params)
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException
{
Constructor<InternalExecutionResult> constructor =
clazz.getDeclaredConstructor( CompletionListener.class, Statement.class, GraphDatabaseService.class, ExecutionMode.class, InternalPlanDescription.class , Map.class);
return constructor.newInstance( completion, statement, db, executionMode, description, params );
clazz.getDeclaredConstructor( TaskCloser.class, Statement.class, GraphDatabaseService.class, ExecutionMode.class, InternalPlanDescription.class , Map.class);
return constructor.newInstance( closer, statement, db, executionMode, description, params );
}

private static class InMemSource extends SimpleJavaFileObject
Expand Down
Expand Up @@ -69,7 +69,7 @@ object CypherCompilerFactory {
logger: InfoLogger,
rewriterSequencer: (String) => RewriterStepSequencer,
plannerName: Option[CostBasedPlannerName],
runtimeName: RuntimeName): CypherCompiler = {
runtimeName: Option[RuntimeName]): CypherCompiler = {
val parser = new CypherParser(monitors.newMonitor[ParserMonitor[Statement]](monitorTag))
val checker = new SemanticChecker(monitors.newMonitor[SemanticCheckMonitor](monitorTag))
val rewriter = new ASTRewriter(rewriterSequencer, monitors.newMonitor[AstRewritingMonitor](monitorTag))
Expand All @@ -79,7 +79,9 @@ object CypherCompilerFactory {
val queryPlanner = new DefaultQueryPlanner(LogicalPlanRewriter(rewriterSequencer))

val pickedPlannerName = plannerName.getOrElse(FallbackPlannerName)
val planner = CostBasedPipeBuilderFactory(monitors, metricsFactory, planningMonitor, clock, queryPlanner = queryPlanner, rewriterSequencer = rewriterSequencer, plannerName = pickedPlannerName, runtimeName = runtimeName)
val pickedRuntimeName = runtimeName.getOrElse(CompiledRuntimeName)
val planner = CostBasedPipeBuilderFactory(monitors, metricsFactory, planningMonitor, clock, queryPlanner = queryPlanner,
rewriterSequencer = rewriterSequencer, plannerName = pickedPlannerName, runtimeName = pickedRuntimeName)
// falling back to legacy planner is allowed only when no cost-based planner is picked explicitly (e.g., COST, IDP)
val pipeBuilder = pickedPlannerName match {
case FallbackPlannerName =>
Expand Down
Expand Up @@ -22,9 +22,12 @@ package org.neo4j.cypher.internal.compiler.v2_3.birk
import java.util
import java.util.concurrent.atomic.AtomicInteger


import org.apache.commons.lang3.StringEscapeUtils
import org.neo4j.cypher.internal.compiler.v2_3.TaskCloser
import org.neo4j.cypher.internal.compiler.v2_3.birk.codegen.{CodeGenContext, Namer}
import org.neo4j.cypher.internal.compiler.v2_3.birk.il._
import org.neo4j.cypher.internal.compiler.v2_3.executionplan.{CompiledPlan, CompletionListener, PlanFingerprint}
import org.neo4j.cypher.internal.compiler.v2_3.executionplan.{CompiledPlan, PlanFingerprint}
import org.neo4j.cypher.internal.compiler.v2_3.helpers.Eagerly
import org.neo4j.cypher.internal.compiler.v2_3.planDescription.InternalPlanDescription
import org.neo4j.cypher.internal.compiler.v2_3.planner.logical.plans._
Expand All @@ -42,15 +45,19 @@ object CodeGenerator {
def generateClass(instructions: Seq[Instruction]) = {
val className = Namer.newClassName()
val source = generateCodeFromInstructions(className, instructions)
// print(indentNicely(source))
Javac.compile(s"$packageName.$className", source)

Javac.compile(s"$packageName.$className",source )
}

implicit class JavaString(name: String) {
def toJava = s"""${StringEscapeUtils.escapeJava(name)}"""
}

object JavaTypes {
val LONG = "long"
val INT = "int"
val OBJECT = "Object"
val OBJECT_ARRAY = "Object[]"
val LIST = "java.util.List"
val MAP = "java.util.Map"
val DOUBLE = "double"
val STRING = "String"
Expand Down Expand Up @@ -111,14 +118,15 @@ object CodeGenerator {
|import org.neo4j.kernel.api.exceptions.KernelException;
|import org.neo4j.kernel.api.ReadOperations;
|import org.neo4j.cypher.internal.compiler.v2_3.birk.ResultRowImpl;
|import org.neo4j.cypher.internal.compiler.v2_3.CypherException;
|import org.neo4j.cypher.internal.compiler.v2_3.executionplan.CompiledExecutionResult;
|import org.neo4j.graphdb.Result.ResultRow;
|import org.neo4j.graphdb.Result.ResultVisitor;
|import org.neo4j.graphdb.Result;
|import org.neo4j.graphdb.Transaction;
|import org.neo4j.cypher.internal.compiler.v2_3.planDescription.InternalPlanDescription;
|import org.neo4j.cypher.internal.compiler.v2_3.ExecutionMode;
|import org.neo4j.cypher.internal.compiler.v2_3.executionplan.CompletionListener;
|import org.neo4j.cypher.internal.compiler.v2_3.TaskCloser;
|import java.util.Map;
|
|$imports
Expand All @@ -131,9 +139,9 @@ object CodeGenerator {
|private final ExecutionMode executionMode;
|private final Map<String, Object> params;
|
|public $className( CompletionListener completion, Statement statement, GraphDatabaseService db, ExecutionMode executionMode, InternalPlanDescription description, Map<String, Object> params )
|public $className( TaskCloser closer, Statement statement, GraphDatabaseService db, ExecutionMode executionMode, InternalPlanDescription description, Map<String, Object> params )
|{
| super( completion, statement );
| super( closer, statement );
| this.ro = statement.readOperations();
| this.db = db;
| this.executionMode = executionMode;
Expand All @@ -157,15 +165,20 @@ object CodeGenerator {
|public <E extends Exception> void accept(final ResultVisitor<E> visitor)
|{
|final ResultRowImpl row = new ResultRowImpl(db);
|$init
|try
|{
|$init
|$methodBody
|success();
|}
|catch (CypherException e)
|{
|throw e;
|}
|catch (Exception e)
|{
|//TODO proper error handling
|//we want to handle KernelExceptions and E coming from visitor
|throw new RuntimeException( e );
|}
|finally
Expand Down Expand Up @@ -195,7 +208,7 @@ class CodeGenerator {

def generate(plan: LogicalPlan, planContext: PlanContext, clock: Clock, semanticTable: SemanticTable) = {
plan match {
case _: ProduceResult =>
case res: ProduceResult =>
val clazz = generateClass(createInstructions(plan, semanticTable))

val fp = planContext.statistics match {
Expand All @@ -208,10 +221,11 @@ class CodeGenerator {
val idMap = LogicalPlanIdentificationBuilder(plan)
val description: InternalPlanDescription = LogicalPlan2PlanDescription(plan, idMap)

val builder = (st: Statement, db: GraphDatabaseService, mode: ExecutionMode, params: Map[String, Any], completion: CompletionListener) =>
Javac.newInstance(clazz, completion, st, db, mode, description, asJavaHashMap(params))
val builder = (st: Statement, db: GraphDatabaseService, mode: ExecutionMode, params: Map[String, Any], closer: TaskCloser) =>
Javac.newInstance(clazz, closer, st, db, mode, description, asJavaHashMap(params))

CompiledPlan(updating = false, None, fp, GreedyPlannerName, builder)
val columns = res.nodes ++ res.relationships ++ res.other
CompiledPlan(updating = false, None, fp, GreedyPlannerName, description, columns, builder)

case _ => throw new CantCompileQueryException("Can only compile plans with ProduceResult on top")
}
Expand Down
Expand Up @@ -182,7 +182,9 @@ object LogicalPlanConverter {
(methodHandle, ProjectProperties(projectionInstructions, action))
}

private def createProjectionInstruction(expression: Expression, context: CodeGenContext): ProjectionInstruction =
private def createProjectionInstruction(expression: Expression, context: CodeGenContext): ProjectionInstruction = {
def safeToString(a: Any) = if (a != null) a.toString else "null"

expression match {
case nodeOrRel@Identifier(name)
if context.semanticTable.isNode(nodeOrRel) || context.semanticTable.isRelationship(nodeOrRel) =>
Expand All @@ -199,16 +201,17 @@ object LogicalPlanConverter {
case Parameter(name) => ProjectParameter(name)

case lit: IntegerLiteral =>
ProjectLiteral(JavaSymbol(s"${lit.value.toString}L", LONG))
val value = if (lit.value != null) s"${lit.value.toString}L" else "null"
ProjectLiteral(JavaSymbol(value, LONG))

case lit: DoubleLiteral =>
ProjectLiteral(JavaSymbol(lit.value.toString, DOUBLE))
ProjectLiteral(JavaSymbol(safeToString(lit.value), DOUBLE))

case lit: StringLiteral =>
ProjectLiteral(JavaSymbol( s""""${lit.value}"""", STRING))
ProjectLiteral(JavaSymbol( s""""${safeToString(lit.value)}"""", STRING))

case lit: Literal =>
ProjectLiteral(JavaSymbol(lit.value.toString, OBJECT))
ProjectLiteral(JavaSymbol(safeToString(lit.value), OBJECT))

case Collection(exprs) =>
ProjectCollection(exprs.map(e => createProjectionInstruction(e, context)))
Expand All @@ -231,6 +234,6 @@ object LogicalPlanConverter {

case other => throw new CantCompileQueryException(s"Projection of $other not yet supported")
}
}
}

}

0 comments on commit 40ff6cd

Please sign in to comment.