Permalink
Browse files

Fixes problem when trying to delete entities multiple times

  • Loading branch information...
1 parent da1293f commit 8af4b57cba9cd81a8af90cc3f0b21dac19ffcb4d @systay committed Jun 27, 2012
@@ -24,7 +24,8 @@ import org.neo4j.cypher.internal.pipes.{QueryState, ExecutionContext}
import org.neo4j.cypher.CypherTypeException
import org.neo4j.cypher.internal.symbols.AnyType
import collection.JavaConverters._
-import org.neo4j.graphdb.{PropertyContainer, Path, Relationship, Node}
+import org.neo4j.graphdb._
+import org.neo4j.kernel.impl.core.NodeManager
case class DeleteEntityAction(elementToDelete: Expression)
extends UpdateAction {
@@ -41,18 +42,21 @@ case class DeleteEntityAction(elementToDelete: Expression)
}
private def delete(x: PropertyContainer, state: QueryState) {
+ val nodeManager: NodeManager = state.graphDatabaseAPI.getNodeManager
+
x match {
- case n: Node => {
+ case n: Node if (!nodeManager.isDeleted(n)) =>
state.deletedNodes.increase()
n.delete()
- }
- case r: Relationship => {
+
+ case r: Relationship if (!nodeManager.isDeleted(r))=>
state.deletedRelationships.increase()
r.delete()
- }
+
+ case _ => // Entity is already deleted. No need to do anything
+
}
}
-
def identifier = Seq.empty
def rewrite(f: (Expression) => Expression) = DeleteEntityAction(elementToDelete.rewrite(f))
@@ -27,6 +27,7 @@ import org.neo4j.graphdb.{GraphDatabaseService, Transaction}
import collection.mutable.{Queue, Map => MutableMap}
import scala.collection.JavaConverters._
import java.util.HashMap
+import org.neo4j.kernel.GraphDatabaseAPI
/**
* Pipe is a central part of Cypher. Most pipes are decorators - they
@@ -51,9 +52,7 @@ class NullPipe extends Pipe {
}
object MutableMaps {
- // def create = new java.util.HashMap[String,Any](100).asScala
- // def create = new java.util.HashMap[String,Any](100).asScala
- def create = collection.mutable.Map[String,Any]() // new java.util.HashMap[String,Any](100).asScala
+ def create = collection.mutable.Map[String,Any]()
def create(size : Int) = new java.util.HashMap[String,Any](size).asScala
def create(input : scala.collection.Map[String,Any]) = new java.util.HashMap[String,Any](input.asJava).asScala
def create(input : Seq[(String,Any)]) = {
@@ -74,10 +73,15 @@ class QueryState(val db: GraphDatabaseService,
val propertySet = new Counter
val deletedNodes = new Counter
val deletedRelationships = new Counter
+
+ def graphDatabaseAPI: GraphDatabaseAPI = if (db.isInstanceOf[GraphDatabaseAPI])
+ db.asInstanceOf[GraphDatabaseAPI]
+ else
+ throw new IllegalStateException("Graph database does not implement GraphDatabaseAPI")
}
class Counter {
- private var counter = 0L;
+ private var counter = 0L
def count = counter
@@ -126,9 +130,4 @@ case class ExecutionContext(m: MutableMap[String, Any] = MutableMaps.create,
def newWith(newEntry : (String,Any)) = {
copy(m = (MutableMaps.create(this.m) += newEntry))
}
-/*
- def newWith(newEntries : (String,Any)*) = {
- copy(m = this.m.clone() ++ newEntries)
- }
-*/
}
@@ -440,6 +440,14 @@ return distinct center""")
assertStats(result, nodesCreated = 1, relationshipsCreated = 2)
}
+
+ @Test
+ def delete_and_delete_again() {
+ createNode()
+ val result = parseAndExecute("start a=node(1) delete a foreach( x in [1] : delete a)")
+
+ assertStats(result, deletedNodes = 1)
+ }
}
trait StatisticsChecker extends Assertions {
@@ -29,6 +29,8 @@
import java.util.concurrent.locks.ReentrantLock;
import java.util.logging.Level;
import java.util.logging.Logger;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
import javax.transaction.TransactionManager;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
@@ -68,8 +70,6 @@
private long referenceNodeId = 0;
- private Config config;
-
private final GraphDatabaseService graphDbService;
private final Cache<NodeImpl> nodeCache;
private final Cache<RelationshipImpl> relCache;
@@ -104,7 +104,6 @@ public NodeManager( Config config, GraphDatabaseService graphDb, LockManager loc
NodeProxy.NodeLookup nodeLookup, RelationshipProxy.RelationshipLookups relationshipLookups,
Cache<NodeImpl> nodeCache, Cache<RelationshipImpl> relCache )
{
- this.config = config;
this.graphDbService = graphDb;
this.lockManager = lockManager;
this.transactionManager = transactionManager;
@@ -1153,29 +1152,63 @@ public RelationshipTypeHolder getRelationshipTypeHolder()
return this.relTypeHolder;
}
- public void addNodePropertyTracker(
- PropertyTracker<Node> nodePropertyTracker )
+ public void addNodePropertyTracker( PropertyTracker<Node> nodePropertyTracker )
{
nodePropertyTrackers.add( nodePropertyTracker );
}
- public void removeNodePropertyTracker(
- PropertyTracker<Node> nodePropertyTracker )
+ public void removeNodePropertyTracker( PropertyTracker<Node> nodePropertyTracker )
{
nodePropertyTrackers.remove( nodePropertyTracker );
}
- public void addRelationshipPropertyTracker(
- PropertyTracker<Relationship> relationshipPropertyTracker )
+ public void addRelationshipPropertyTracker( PropertyTracker<Relationship> relationshipPropertyTracker )
{
relationshipPropertyTrackers.add( relationshipPropertyTracker );
}
- public void removeRelationshipPropertyTracker(
- PropertyTracker<Relationship> relationshipPropertyTracker )
+ public void removeRelationshipPropertyTracker(PropertyTracker<Relationship> relationshipPropertyTracker )
{
relationshipPropertyTrackers.remove( relationshipPropertyTracker );
}
+
+ public Boolean isDeleted( PropertyContainer resource )
+ {
+ Transaction transaction;
+ try
+ {
+ transaction = transactionManager.getTransaction();
+ } catch ( SystemException se )
+ {
+ // our TM never throws this exception
+ log.log( Level.SEVERE, "Failed to retrieve transaction", se );
+ return false;
+ }
+
+ if ( transaction == null )
+ {
+ return false;
+ }
+
+ boolean dontCreateIfMissing = false;
+ LockReleaser.PrimitiveElement primitiveElement = lockReleaser.getPrimitiveElement( transaction, dontCreateIfMissing );
+
+ if ( primitiveElement == null )
+ {
+ return false;
+ }
+
+ LockReleaser.CowEntityElement cowEntity;
+ if ( resource instanceof Node )
+ {
+ cowEntity = primitiveElement.nodeElement( ((Node) resource).getId(), false );
+ } else
+ {
+ cowEntity = primitiveElement.relationshipElement( ((Relationship) resource).getId(), false );
+ }
+
+ return cowEntity != null && cowEntity.deleted;
+ }
PersistenceManager getPersistenceManager()
{

0 comments on commit 8af4b57

Please sign in to comment.