Commit 402a6dd9 authored by fickludd's avatar fickludd Committed by Johan Teleman
Browse files

Fix bug with slot allocation of foreach with missing type information

parent 11e17e7b
Showing with 22 additions and 9 deletions
+22 -9
......@@ -51,8 +51,7 @@ class SemanticTable(
throw new InternalException(s"Did not find any type information for variable $s", e)
}
def getActualTypeFor(expr: Expression): TypeSpec =
types.getOrElse(expr, throw new InternalException(s"Did not find any type information for expression $expr")).actual
def getActualTypeFor(expr: Expression): Option[TypeSpec] = types.get(expr).map(_.actual)
def containsNode(expr: String): Boolean = types.exists {
case (v@Variable(name), _) => name == expr && isNode(v) // NOTE: Profiling showed that checking node type last is better
......
......@@ -201,4 +201,18 @@ class ForeachAcceptanceTest extends ExecutionEngineFunSuite with CypherCompariso
TestConfiguration(Versions(Versions.V3_1, Versions.V3_3), Planners.Cost, Runtimes.Default)
failWithError(config, query, List("Expected to find a node at"))
}
test("should FOREACH over nodes in path") {
val a = createNode()
val b = createNode()
relate(a, b)
val query =
"""MATCH p = ()-->()
|FOREACH (n IN nodes(p) | SET n.marked = true)""".stripMargin
val result = executeWith(Configs.Interpreted - Configs.Cost2_3, query)
assertStats(result, propertiesWritten = 2)
}
}
......@@ -58,7 +58,7 @@ object SlotAllocation {
argumentSizes: ArgumentSizes)
/**
* Allocate slot for every operator in the logical plan tree {@code lp}.
* Allocate slot for every operator in the logical plan tree `lp`.
*
* @param lp the logical plan to process.
* @return the slot configurations of every operator.
......@@ -245,7 +245,7 @@ object SlotAllocation {
}
/**
* Compute the slot configuration of a leaf logical plan operator {@code lp}.
* Compute the slot configuration of a leaf logical plan operator `lp`.
*
* @param lp the operator to compute slots for.
* @param nullable true if new slots are nullable
......@@ -290,7 +290,7 @@ object SlotAllocation {
}
/**
* Compute the slot configuration of a single source logical plan operator {@code lp}.
* Compute the slot configuration of a single source logical plan operator `lp`.
*
* @param lp the operator to compute slots for.
* @param nullable true if new slots are nullable
......@@ -502,7 +502,7 @@ object SlotAllocation {
}
/**
* Compute the slot configuration of a branching logical plan operator {@code lp}.
* Compute the slot configuration of a branching logical plan operator `lp`.
*
* @param lp the operator to compute slots for.
* @param nullable true if new slots are nullable
......@@ -655,9 +655,9 @@ object SlotAllocation {
case ForeachApply(_, _, variableName, listExpression) =>
// The slot for the iteration variable of foreach needs to be available as an argument on the rhs of the apply
// so we allocate it on the lhs (even though its value will not be needed after the foreach is done)
val typeSpec = semanticTable.getActualTypeFor(listExpression)
val listOfNodes = typeSpec.contains(ListType(CTNode))
val listOfRels = typeSpec.contains(ListType(CTRelationship))
val maybeTypeSpec = semanticTable.getActualTypeFor(listExpression)
val listOfNodes = maybeTypeSpec.exists(_.contains(ListType(CTNode)))
val listOfRels = maybeTypeSpec.exists(_.contains(ListType(CTRelationship)))
(listOfNodes, listOfRels) match {
case (true, false) => lhs.newLong(variableName, true, CTNode)
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment