Skip to content

Commit

Permalink
Temporal already had enum defined
Browse files Browse the repository at this point in the history
Temporal already had a Field enum, remove the newly created one and join
with the others
  • Loading branch information
pontusmelke committed Sep 10, 2018
1 parent b0b756d commit 2cb61b0
Show file tree
Hide file tree
Showing 14 changed files with 297 additions and 241 deletions.
Expand Up @@ -20,16 +20,24 @@
package org.neo4j.cypher.internal.compiler.v3_4.planner package org.neo4j.cypher.internal.compiler.v3_4.planner


import org.neo4j.cypher.internal.compiler.v3_4.phases.LogicalPlanState import org.neo4j.cypher.internal.compiler.v3_4.phases.LogicalPlanState
import org.neo4j.cypher.internal.frontend.v3_4.ast._
import org.neo4j.cypher.internal.frontend.v3_4.notification.{InternalNotification, MissingLabelNotification, MissingPropertyNameNotification, MissingRelTypeNotification} import org.neo4j.cypher.internal.frontend.v3_4.notification.{InternalNotification, MissingLabelNotification, MissingPropertyNameNotification, MissingRelTypeNotification}
import org.neo4j.cypher.internal.frontend.v3_4.phases.CompilationPhaseTracer.CompilationPhase.LOGICAL_PLANNING import org.neo4j.cypher.internal.frontend.v3_4.phases.CompilationPhaseTracer.CompilationPhase.LOGICAL_PLANNING
import org.neo4j.cypher.internal.frontend.v3_4.phases.{BaseContext, VisitorPhase} import org.neo4j.cypher.internal.frontend.v3_4.phases.{BaseContext, VisitorPhase}
import org.neo4j.cypher.internal.v3_4.expressions.{LabelName, Property, PropertyKeyName, RelTypeName} import org.neo4j.cypher.internal.v3_4.expressions.{LabelName, Property, PropertyKeyName, RelTypeName}
import org.neo4j.values.storable.TemporalValue.TemporalFields
import org.neo4j.values.storable.{DurationFields, PointFields, TemporalValue}

import scala.collection.JavaConverters._


object CheckForUnresolvedTokens extends VisitorPhase[BaseContext, LogicalPlanState] { object CheckForUnresolvedTokens extends VisitorPhase[BaseContext, LogicalPlanState] {


private val specialPropertyKey: Set[String] =
(TemporalFields.allFields().asScala ++
DurationFields.values().map(_.propertyKey) ++
PointFields.values().map(_.propertyKey)).toSet

override def visit(value: LogicalPlanState, context: BaseContext): Unit = { override def visit(value: LogicalPlanState, context: BaseContext): Unit = {
val table = value.semanticTable val table = value.semanticTable()
def isEmptyLabel(label: String) = !table.resolvedLabelNames.contains(label) def isEmptyLabel(label: String) = !table.resolvedLabelNames.contains(label)
def isEmptyRelType(relType: String) = !table.resolvedRelTypeNames.contains(relType) def isEmptyRelType(relType: String) = !table.resolvedRelTypeNames.contains(relType)
def isEmptyPropertyName(name: String) = !table.resolvedPropertyKeyNames.contains(name) def isEmptyPropertyName(name: String) = !table.resolvedPropertyKeyNames.contains(name)
Expand All @@ -41,7 +49,7 @@ object CheckForUnresolvedTokens extends VisitorPhase[BaseContext, LogicalPlanSta
case rel@RelTypeName(name) if isEmptyRelType(name) => acc => case rel@RelTypeName(name) if isEmptyRelType(name) => acc =>
(acc :+ MissingRelTypeNotification(rel.position, name), Some(identity)) (acc :+ MissingRelTypeNotification(rel.position, name), Some(identity))


case Property(_, prop@PropertyKeyName(name)) if isEmptyPropertyName(name) => acc => case Property(_, prop@PropertyKeyName(name)) if !specialPropertyKey(name) && isEmptyPropertyName(name) => acc =>
(acc :+ MissingPropertyNameNotification(prop.position, name), Some(identity)) (acc :+ MissingPropertyNameNotification(prop.position, name), Some(identity))
} }


Expand Down
Expand Up @@ -28,6 +28,7 @@ import org.neo4j.cypher.internal.util.v3_4.test_helpers.CypherFunSuite
import org.neo4j.cypher.internal.frontend.v3_4.semantics.SemanticTable import org.neo4j.cypher.internal.frontend.v3_4.semantics.SemanticTable
import org.neo4j.cypher.internal.planner.v3_4.spi.IDPPlannerName import org.neo4j.cypher.internal.planner.v3_4.spi.IDPPlannerName
import org.neo4j.cypher.internal.util.v3_4.{InputPosition, LabelId, PropertyKeyId, RelTypeId} import org.neo4j.cypher.internal.util.v3_4.{InputPosition, LabelId, PropertyKeyId, RelTypeId}
import org.neo4j.values.storable.PointFields


class CheckForUnresolvedTokensTest extends CypherFunSuite with AstRewritingTestSupport with LogicalPlanConstructionTestSupport { class CheckForUnresolvedTokensTest extends CypherFunSuite with AstRewritingTestSupport with LogicalPlanConstructionTestSupport {


Expand Down Expand Up @@ -124,6 +125,60 @@ class CheckForUnresolvedTokensTest extends CypherFunSuite with AstRewritingTestS
checkForTokens(ast, semanticTable) shouldBe empty checkForTokens(ast, semanticTable) shouldBe empty
} }


test("don't warn when using point properties") {
//given
val semanticTable = new SemanticTable
semanticTable.resolvedPropertyKeyNames.put("prop", PropertyKeyId(42))

PointFields.values().foreach { property =>
//when
val ast = parse(s"MATCH (a) WHERE point(a.prop).${property.propertyKey} = 42 RETURN a")

//then
checkForTokens(ast, semanticTable) shouldBe empty
}
}

test("don't warn when using temporal properties") {
//given
val semanticTable = new SemanticTable
semanticTable.resolvedPropertyKeyNames.put("prop", PropertyKeyId(42))

PointFields.values().foreach { property =>
//when
val ast = parse(s"MATCH (a) WHERE date(a.prop).${property.propertyKey} = 42 RETURN a")

//then
checkForTokens(ast, semanticTable) shouldBe empty
}
}

test("don't warn when using duration properties") {
//given
val semanticTable = new SemanticTable
semanticTable.resolvedPropertyKeyNames.put("prop", PropertyKeyId(42))

PointFields.values().foreach { property =>
//when
val ast = parse(s"MATCH (a) WHERE duration(a.prop).${property.propertyKey} = 42 RETURN a")

//then
checkForTokens(ast, semanticTable) shouldBe empty
}
}

test("don't warn when using temporal property") {
//given
val semanticTable = new SemanticTable
semanticTable.resolvedPropertyKeyNames.put("prop", PropertyKeyId(42))

//when
val ast = parse("MATCH (a) WHERE point(a.prop).y = 42 RETURN a")

//then
checkForTokens(ast, semanticTable) shouldBe empty
}

private def checkForTokens(ast: Query, semanticTable: SemanticTable): Set[InternalNotification] = { private def checkForTokens(ast: Query, semanticTable: SemanticTable): Set[InternalNotification] = {
val notificationLogger = new RecordingNotificationLogger val notificationLogger = new RecordingNotificationLogger
val compilationState = LogicalPlanState(queryText = "apa", startPosition = None, plannerName = IDPPlannerName, new StubSolveds, new StubCardinalities, maybeStatement = Some(ast), maybeSemanticTable = Some(semanticTable)) val compilationState = LogicalPlanState(queryText = "apa", startPosition = None, plannerName = IDPPlannerName, new StubSolveds, new StubCardinalities, maybeStatement = Some(ast), maybeSemanticTable = Some(semanticTable))
Expand Down
Expand Up @@ -21,6 +21,8 @@


import java.time.Clock; import java.time.Clock;
import java.time.ZoneId; import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.time.temporal.IsoFields;
import java.time.temporal.TemporalUnit; import java.time.temporal.TemporalUnit;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
Expand All @@ -40,7 +42,6 @@
import org.neo4j.kernel.impl.proc.Procedures; import org.neo4j.kernel.impl.proc.Procedures;
import org.neo4j.procedure.Description; import org.neo4j.procedure.Description;
import org.neo4j.values.AnyValue; import org.neo4j.values.AnyValue;
import org.neo4j.values.storable.TemporalProperties;
import org.neo4j.values.storable.TemporalValue; import org.neo4j.values.storable.TemporalValue;
import org.neo4j.values.storable.TextValue; import org.neo4j.values.storable.TextValue;
import org.neo4j.values.storable.Values; import org.neo4j.values.storable.Values;
Expand Down Expand Up @@ -283,15 +284,51 @@ public T apply( Context ctx, AnyValue[] args ) throws ProcedureException
if ( unit instanceof TextValue && input instanceof TemporalValue && fields instanceof MapValue ) if ( unit instanceof TextValue && input instanceof TemporalValue && fields instanceof MapValue )
{ {
return function.truncate( return function.truncate(
TemporalProperties.fromName( ((TextValue) unit).stringValue() ).unit, unit( ((TextValue) unit).stringValue() ),
(TemporalValue) input, (TemporalValue)input,
(MapValue) fields, (MapValue) fields,
function.defaultZone ); function.defaultZone );
} }
} }
throw new ProcedureException( Status.Procedure.ProcedureCallFailed, throw new ProcedureException( Status.Procedure.ProcedureCallFailed, "Invalid call signature for " + getClass().getSimpleName() +
"Invalid call signature for " + getClass().getSimpleName() +
": Provided input was " + Arrays.toString( args ) ); ": Provided input was " + Arrays.toString( args ) );
} }

private static TemporalUnit unit( String unit )
{
switch ( unit )
{
case "millennium":
return ChronoUnit.MILLENNIA;
case "century":
return ChronoUnit.CENTURIES;
case "decade":
return ChronoUnit.DECADES;
case "year":
return ChronoUnit.YEARS;
case "weekYear":
return IsoFields.WEEK_BASED_YEARS;
case "quarter":
return IsoFields.QUARTER_YEARS;
case "month":
return ChronoUnit.MONTHS;
case "week":
return ChronoUnit.WEEKS;
case "day":
return ChronoUnit.DAYS;
case "hour":
return ChronoUnit.HOURS;
case "minute":
return ChronoUnit.MINUTES;
case "second":
return ChronoUnit.SECONDS;
case "millisecond":
return ChronoUnit.MILLIS;
case "microsecond":
return ChronoUnit.MICROS;
default:
throw new IllegalArgumentException( "Unsupported unit: " + unit );
}
}
} }
} }

0 comments on commit 2cb61b0

Please sign in to comment.