Skip to content

Commit

Permalink
Move CompiledOrderabilityUtils to compiler module
Browse files Browse the repository at this point in the history
This allows both runtimes to use the same code for comparing and ordering values.

Also introduces NodeIdWrapper and RelationshipIdWrapper as SPI interfaces.
  • Loading branch information
Mats-SX committed Feb 28, 2017
1 parent f90ce04 commit 0296d52
Show file tree
Hide file tree
Showing 19 changed files with 112 additions and 33 deletions.
@@ -0,0 +1,25 @@
/*
* Copyright (c) 2002-2017 "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_2.spi;

public interface NodeIdWrapper
{
long id();
}
@@ -0,0 +1,25 @@
/*
* Copyright (c) 2002-2017 "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_2.spi;

public interface RelationshipIdWrapper
{
long id();
}
Expand Up @@ -17,7 +17,7 @@
* 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.codegen;
package org.neo4j.cypher.internal.compiler.v3_2.util;

import java.util.Arrays;
import java.util.Comparator;
Expand All @@ -28,8 +28,10 @@
import java.util.stream.IntStream;
import java.util.stream.LongStream;

import org.neo4j.cypher.UnorderableValueException;
import org.neo4j.cypher.internal.compiler.v3_2.spi.NodeIdWrapper;
import org.neo4j.cypher.internal.compiler.v3_2.spi.RelationshipIdWrapper;
import org.neo4j.cypher.internal.frontend.v3_2.IncomparableValuesException;
import org.neo4j.cypher.internal.frontend.v3_2.UnorderableValueException;
import org.neo4j.graphdb.Path;
import org.neo4j.graphdb.PropertyContainer;
import org.neo4j.helpers.MathUtil;
Expand Down
Expand Up @@ -20,7 +20,7 @@
package org.neo4j.cypher.internal.compiler.v3_2

import java.io.PrintWriter
import java.util
import java.{util => javaUtil}
import java.util.Collections

import org.neo4j.cypher.internal.compiler.v3_2.executionplan.{InternalExecutionResult, InternalQueryType}
Expand All @@ -35,9 +35,9 @@ case class ExplainExecutionResult(columns: List[String],
notifications: Set[InternalNotification])
extends InternalExecutionResult {

def javaIterator: ResourceIterator[util.Map[String, Any]] = new EmptyResourceIterator()
def javaIterator: ResourceIterator[javaUtil.Map[String, Any]] = new EmptyResourceIterator()
def columnAs[T](column: String) = Iterator.empty
def javaColumns: util.List[String] = Collections.emptyList()
def javaColumns: javaUtil.List[String] = Collections.emptyList()

def queryStatistics() = InternalQueryStatistics()

Expand Down
Expand Up @@ -17,7 +17,7 @@
* 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.codegen;
package org.neo4j.cypher.internal.compiler.v3_2.util;

import org.junit.Rule;
import org.junit.Test;
Expand All @@ -26,6 +26,8 @@
import java.util.Arrays;
import java.util.HashMap;

import org.neo4j.cypher.internal.compiler.v3_2.spi.NodeIdWrapper;
import org.neo4j.cypher.internal.compiler.v3_2.spi.RelationshipIdWrapper;
import org.neo4j.cypher.internal.frontend.v3_2.IncomparableValuesException;

import static java.lang.String.format;
Expand All @@ -43,12 +45,12 @@ public class CompiledOrderabilityUtilsTest
new HashMap<Long,Long>(),

// NODE
new NodeIdWrapper( 1 ),
new NodeIdWrapper( 2 ),
(NodeIdWrapper) () -> 1,
(NodeIdWrapper) () -> 2,

// RELATIONSHIP
new RelationshipIdWrapper( 1 ),
new RelationshipIdWrapper( 2 ),
(RelationshipIdWrapper) () -> 1,
(RelationshipIdWrapper) () -> 2,

// LIST
new String[]{"boo"},
Expand All @@ -65,15 +67,15 @@ public class CompiledOrderabilityUtilsTest
new long[]{1, 2, 3, Long.MIN_VALUE},
new int[]{1, 2, 3, Integer.MIN_VALUE},
new Object[]{1L, 2, 3, Double.NaN},
new Object[]{1L, 2, 3, new NodeIdWrapper(-1)},
new Object[]{1L, 2, 3, (NodeIdWrapper) () -> -1},
new Long[]{1L, 2L, 4L},
new int[]{2},
new Integer[]{3},
new double[]{4D},
new Double[]{5D},
new float[]{6},
new Float[]{7F},
new Object[]{new RelationshipIdWrapper(-1)},
new Object[]{(RelationshipIdWrapper) () -> -1},

// TODO: PATH

Expand Down
Expand Up @@ -31,6 +31,8 @@
import java.util.stream.IntStream;
import java.util.stream.LongStream;

import org.neo4j.cypher.internal.compiler.v3_2.spi.NodeIdWrapper;
import org.neo4j.cypher.internal.compiler.v3_2.spi.RelationshipIdWrapper;
import org.neo4j.cypher.internal.frontend.v3_2.CypherTypeException;
import org.neo4j.cypher.internal.frontend.v3_2.IncomparableValuesException;
import org.neo4j.graphdb.Node;
Expand Down Expand Up @@ -171,11 +173,11 @@ public static Object loadParameter( Object value )
{
if ( value instanceof Node )
{
return new NodeIdWrapper( ((Node) value).getId() );
return new NodeIdWrapperImpl( ((Node) value).getId() );
}
else if ( value instanceof Relationship )
{
return new RelationshipIdWrapper( ((Relationship) value).getId() );
return new RelationshipIdWrapperImpl( ((Relationship) value).getId() );
}
else
{
Expand Down Expand Up @@ -349,6 +351,7 @@ else if ( list instanceof boolean[] )
throw new IllegalArgumentException( format( "Can not be converted to stream: %s", list.getClass().getName() ) );
}

@SuppressWarnings( "unused" ) // called from compiled code
public static long unboxNodeOrNull( NodeIdWrapper value )
{
if ( value == null )
Expand All @@ -358,6 +361,7 @@ public static long unboxNodeOrNull( NodeIdWrapper value )
return value.id();
}

@SuppressWarnings( "unused" ) // called from compiled code
public static long unboxRelationshipOrNull( RelationshipIdWrapper value )
{
if ( value == null )
Expand Down
Expand Up @@ -19,15 +19,18 @@
*/
package org.neo4j.cypher.internal.codegen;

public final class NodeIdWrapper
import org.neo4j.cypher.internal.compiler.v3_2.spi.NodeIdWrapper;

public final class NodeIdWrapperImpl implements NodeIdWrapper
{
private final long id;

public NodeIdWrapper( long id )
public NodeIdWrapperImpl( long id )
{
this.id = id;
}

@Override
public long id()
{
return id;
Expand All @@ -43,7 +46,7 @@ public boolean equals( Object o )

NodeIdWrapper that = (NodeIdWrapper) o;

return id == that.id;
return id == that.id();

}

Expand Down
Expand Up @@ -22,8 +22,10 @@
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.function.LongFunction;
import java.util.stream.LongStream;

import org.neo4j.cypher.internal.compiler.v3_2.spi.NodeIdWrapper;
import org.neo4j.graphdb.Node;

import static java.lang.String.format;
Expand Down Expand Up @@ -61,7 +63,7 @@ else if ( list instanceof Node[] )
// This method is only used when we do not know the element type at compile time, so it has to box the elements
public Iterator<NodeIdWrapper> iterator()
{
return inner.mapToObj( NodeIdWrapper::new ).iterator();
return inner.mapToObj( (LongFunction<NodeIdWrapper>) NodeIdWrapperImpl::new ).iterator();
}

private static final PrimitiveNodeStream empty = new PrimitiveNodeStream( LongStream.empty() );
Expand Down
Expand Up @@ -22,8 +22,10 @@
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.function.LongFunction;
import java.util.stream.LongStream;

import org.neo4j.cypher.internal.compiler.v3_2.spi.RelationshipIdWrapper;
import org.neo4j.graphdb.Relationship;

import static java.lang.String.format;
Expand Down Expand Up @@ -63,7 +65,7 @@ else if ( list instanceof Relationship[] )
// This method is only used when we do not know the element type at compile time, so it has to box the elements
public Iterator<RelationshipIdWrapper> iterator()
{
return inner.mapToObj( RelationshipIdWrapper::new ).iterator();
return inner.mapToObj( (LongFunction<RelationshipIdWrapper>) RelationshipIdWrapperImpl::new ).iterator();
}

private static final PrimitiveRelationshipStream empty = new PrimitiveRelationshipStream( LongStream.empty() );
Expand Down
Expand Up @@ -19,15 +19,18 @@
*/
package org.neo4j.cypher.internal.codegen;

public final class RelationshipIdWrapper
import org.neo4j.cypher.internal.compiler.v3_2.spi.RelationshipIdWrapper;

public final class RelationshipIdWrapperImpl implements RelationshipIdWrapper
{
private final long id;

public RelationshipIdWrapper( long id )
public RelationshipIdWrapperImpl( long id )
{
this.id = id;
}

@Override
public long id()
{
return id;
Expand All @@ -41,7 +44,7 @@ public boolean equals( Object o )
if ( o == null || getClass() != o.getClass() )
{ return false; }

RelationshipIdWrapper that = (RelationshipIdWrapper) o;
RelationshipIdWrapperImpl that = (RelationshipIdWrapperImpl) o;

return id == that.id;

Expand Down
Expand Up @@ -37,6 +37,8 @@ object exceptionHandler extends MapToPublicExceptions[CypherException] {

override def patternException(message: String, cause: Throwable) = new PatternException(message, cause)

override def unorderableValueException(value: String) = new UnorderableValueException(value)

override def invalidArgumentException(message: String, cause: Throwable) = new InvalidArgumentException(message, cause)

override def mergeConstraintConflictException(message: String, cause: Throwable) = new MergeConstraintConflictException(message, cause)
Expand Down
Expand Up @@ -230,7 +230,7 @@ case class GeneratedMethodStructure(fields: Fields, generator: CodeBlock, aux: A
override def materializeNode(nodeIdVar: String) =
invoke(nodeManager, newNodeProxyById, generator.load(nodeIdVar))

override def node(nodeIdVar: String) = createNewInstance(typeRef[NodeIdWrapper], (typeRef[Long], generator.load(nodeIdVar)))
override def node(nodeIdVar: String) = createNewInstance(typeRef[NodeIdWrapperImpl], (typeRef[Long], generator.load(nodeIdVar)))

override def nullablePrimitive(varName: String, codeGenType: CodeGenType, onSuccess: Expression) = codeGenType match {
case CodeGenType(CTNode, IntType) | CodeGenType(CTRelationship, IntType) =>
Expand All @@ -253,7 +253,7 @@ case class GeneratedMethodStructure(fields: Fields, generator: CodeBlock, aux: A
override def materializeRelationship(relIdVar: String) =
invoke(nodeManager, newRelationshipProxyById, generator.load(relIdVar))

override def relationship(relIdVar: String) = createNewInstance(typeRef[RelationshipIdWrapper],
override def relationship(relIdVar: String) = createNewInstance(typeRef[RelationshipIdWrapperImpl],
(typeRef[Long], generator.load(relIdVar)))

override def trace[V](planStepId: String)(block: MethodStructure[Expression] => V) = if (!tracing) block(this)
Expand Down
Expand Up @@ -89,8 +89,8 @@ object Methods {
val fetchNextRelationship = method[RelationshipIterator, Long]("next")
val newNodeProxyById = method[NodeManager, NodeProxy]("newNodeProxyById", typeRef[Long])
val newRelationshipProxyById = method[NodeManager, RelationshipProxy]("newRelationshipProxyById", typeRef[Long])
val nodeId = method[NodeIdWrapper, Long]("id")
val relId = method[RelationshipIdWrapper, Long]("id")
val nodeId = method[NodeIdWrapperImpl, Long]("id")
val relId = method[RelationshipIdWrapperImpl, Long]("id")
val set = method[ResultRowImpl, Unit]("set", typeRef[String], typeRef[Object])
val visit = method[InternalResultVisitor[_], Boolean]("visit", typeRef[InternalResultRow])
val executeOperator = method[QueryExecutionTracer, QueryExecutionEvent]("executeOperator", typeRef[Id])
Expand Down
Expand Up @@ -148,8 +148,8 @@ class CompiledConversionUtilsTest extends CypherFunSuite {

val testLoadParameter = Seq(
(null, null),
(node, new NodeIdWrapper(11L)),
(rel, new RelationshipIdWrapper(13L))
(node, new NodeIdWrapperImpl(11L)),
(rel, new RelationshipIdWrapperImpl(13L))
)

testLoadParameter.foreach {
Expand Down
Expand Up @@ -108,6 +108,11 @@ class IncomparableValuesException(details: Option[String], lhs: String, rhs: Str
def this(lhs: String, rhs: String) = this(None, lhs, rhs)
}

class UnorderableValueException(value: String) extends CypherException {
override def mapToPublic[T <: Throwable](mapper: MapToPublicExceptions[T]): T =
mapper.unorderableValueException(value)
}

class PeriodicCommitInOpenTransactionException extends CypherException {
override def mapToPublic[T <: Throwable](mapper: MapToPublicExceptions[T]) = mapper.periodicCommitInOpenTransactionException(this)
}
Expand Down
Expand Up @@ -32,6 +32,8 @@ trait MapToPublicExceptions[T <: Throwable] {

def loadExternalResourceException(message: String, cause: Throwable): T

def unorderableValueException(value: String): T

def incomparableValuesException(operator: Option[String], lhs: String, rhs: String, cause: Throwable): T

def arithmeticException(message: String, cause: Throwable): T
Expand Down
Expand Up @@ -22,10 +22,11 @@ package org.neo4j.cypher.internal.spi.v3_2.codegen
import org.neo4j.codegen.FieldReference.field
import org.neo4j.codegen.Parameter.param
import org.neo4j.codegen._
import org.neo4j.cypher.internal.codegen.{CompiledEquivalenceUtils, CompiledOrderabilityUtils}
import org.neo4j.cypher.internal.codegen.CompiledEquivalenceUtils
import org.neo4j.cypher.internal.compiled_runtime.v3_2.codegen.CodeGenContext
import org.neo4j.cypher.internal.compiled_runtime.v3_2.codegen.ir.expressions.{CodeGenType, ReferenceType, RepresentationType}
import org.neo4j.cypher.internal.compiled_runtime.v3_2.codegen.spi._
import org.neo4j.cypher.internal.compiler.v3_2.util.CompiledOrderabilityUtils
import org.neo4j.cypher.internal.frontend.v3_2.helpers._
import org.neo4j.cypher.internal.frontend.v3_2.symbols

Expand Down
Expand Up @@ -30,11 +30,12 @@ import org.neo4j.collection.primitive._
import org.neo4j.collection.primitive.hopscotch.LongKeyIntValueTable
import org.neo4j.cypher.internal.codegen.CompiledConversionUtils.CompositeKey
import org.neo4j.cypher.internal.codegen._
import org.neo4j.cypher.internal.compiled_runtime.v3_2.codegen.ir.expressions.{BoolType, CodeGenType, FloatType, IntType, Parameter => _, ReferenceType, _}
import org.neo4j.cypher.internal.compiled_runtime.v3_2.codegen.ir.expressions.{BoolType, CodeGenType, FloatType, IntType, ReferenceType, Parameter => _, _}
import org.neo4j.cypher.internal.compiled_runtime.v3_2.codegen.spi._
import org.neo4j.cypher.internal.compiled_runtime.v3_2.codegen.{CodeGenContext, QueryExecutionEvent}
import org.neo4j.cypher.internal.compiler.v3_2.ast.convert.commands.DirectionConverter.toGraphDb
import org.neo4j.cypher.internal.compiler.v3_2.planDescription.Id
import org.neo4j.cypher.internal.compiler.v3_2.spi.{NodeIdWrapper, RelationshipIdWrapper}
import org.neo4j.cypher.internal.frontend.v3_2.helpers._
import org.neo4j.cypher.internal.frontend.v3_2.symbols.{CTNode, CTRelationship, ListType}
import org.neo4j.cypher.internal.frontend.v3_2.{ParameterNotFoundException, SemanticDirection, symbols}
Expand Down Expand Up @@ -396,9 +397,9 @@ class GeneratedMethodStructure(val fields: Fields, val generator: CodeBlock, aux

override def box(expression: Expression, codeGenType: CodeGenType) = codeGenType match {
case CodeGenType(symbols.CTNode, IntType) =>
createNewInstance(typeRef[NodeIdWrapper], (typeRef[Long], expression))
createNewInstance(typeRef[NodeIdWrapperImpl], (typeRef[Long], expression))
case CodeGenType(symbols.CTRelationship, IntType) =>
createNewInstance(typeRef[RelationshipIdWrapper], (typeRef[Long], expression))
createNewInstance(typeRef[RelationshipIdWrapperImpl], (typeRef[Long], expression))
case _ => Expression.box(expression)
}

Expand Down

0 comments on commit 0296d52

Please sign in to comment.