use of org.neo4j.internal.kernel.api.exceptions.schema.ConstraintValidationException in project neo4j by neo4j.
the class KernelTransactionImplementation method commitTransaction.
private long commitTransaction() throws KernelException {
boolean success = false;
long txId = READ_ONLY_ID;
TransactionListenersState listenersState = null;
try (CommitEvent commitEvent = transactionEvent.beginCommitEvent()) {
listenersState = eventListeners.beforeCommit(txState, this, storageReader);
if (listenersState != null && listenersState.isFailed()) {
Throwable cause = listenersState.failure();
if (cause instanceof TransientFailureException) {
throw (TransientFailureException) cause;
}
if (cause instanceof Status.HasStatus) {
throw new TransactionFailureException(((Status.HasStatus) cause).status(), cause, cause.getMessage());
}
throw new TransactionFailureException(Status.Transaction.TransactionHookFailed, cause, cause.getMessage());
}
// Convert changes into commands and commit
if (hasChanges()) {
forceThawLocks();
lockClient.prepareForCommit();
// Gather up commands from the various sources
HeapTrackingArrayList<StorageCommand> extractedCommands = HeapTrackingCollections.newArrayList(memoryTracker);
storageEngine.createCommands(extractedCommands, txState, storageReader, commandCreationContext, lockClient, lockTracer(), lastTransactionIdWhenStarted, this::enforceConstraints, cursorContext, memoryTracker);
/* Here's the deal: we track a quick-to-access hasChanges in transaction state which is true
* if there are any changes imposed by this transaction. Some changes made inside a transaction undo
* previously made changes in that same transaction, and so at some point a transaction may have
* changes and at another point, after more changes seemingly,
* the transaction may not have any changes.
* However, to track that "undoing" of the changes is a bit tedious, intrusive and hard to maintain
* and get right.... So to really make sure the transaction has changes we re-check by looking if we
* have produced any commands to add to the logical log.
*/
if (!extractedCommands.isEmpty()) {
// Finish up the whole transaction representation
PhysicalTransactionRepresentation transactionRepresentation = new PhysicalTransactionRepresentation(extractedCommands);
long timeCommitted = clocks.systemClock().millis();
transactionRepresentation.setHeader(EMPTY_BYTE_ARRAY, startTimeMillis, lastTransactionIdWhenStarted, timeCommitted, leaseClient.leaseId(), securityContext.subject());
// Commit the transaction
success = true;
TransactionToApply batch = new TransactionToApply(transactionRepresentation, cursorContext);
kernelTransactionMonitor.beforeApply();
txId = commitProcess.commit(batch, commitEvent, INTERNAL);
commitTime = timeCommitted;
}
}
success = true;
return txId;
} catch (ConstraintValidationException | CreateConstraintFailureException e) {
throw new ConstraintViolationTransactionFailureException(e.getUserMessage(tokenRead()), e);
} finally {
if (!success) {
rollback(listenersState);
} else {
transactionId = txId;
afterCommit(listenersState);
}
transactionMonitor.addHeapTransactionSize(memoryTracker.heapHighWaterMark());
transactionMonitor.addNativeTransactionSize(memoryTracker.usedNativeMemory());
}
}
use of org.neo4j.internal.kernel.api.exceptions.schema.ConstraintValidationException in project neo4j by neo4j.
the class ConstraintTestBase method shouldCheckUniquenessWhenAddingLabel.
@Test
void shouldCheckUniquenessWhenAddingLabel() throws Exception {
// GIVEN
long nodeConflicting, nodeNotConflicting;
addConstraints("FOO", "prop");
try (org.neo4j.graphdb.Transaction tx = graphDb.beginTx()) {
Node conflict = tx.createNode();
conflict.setProperty("prop", 1337);
nodeConflicting = conflict.getId();
Node ok = tx.createNode();
ok.setProperty("prop", 42);
nodeNotConflicting = ok.getId();
// Existing node
Node existing = tx.createNode();
existing.addLabel(Label.label("FOO"));
existing.setProperty("prop", 1337);
tx.commit();
}
int label;
try (KernelTransaction tx = beginTransaction()) {
label = tx.tokenWrite().labelGetOrCreateForName("FOO");
// This is ok, since it will satisfy constraint
assertTrue(tx.dataWrite().nodeAddLabel(nodeNotConflicting, label));
try {
tx.dataWrite().nodeAddLabel(nodeConflicting, label);
fail();
} catch (ConstraintValidationException e) {
// ignore
}
tx.commit();
}
// Verify
try (KernelTransaction tx = beginTransaction();
NodeCursor nodeCursor = tx.cursors().allocateNodeCursor(tx.cursorContext())) {
// Node without conflict
tx.dataRead().singleNode(nodeNotConflicting, nodeCursor);
assertTrue(nodeCursor.next());
assertTrue(nodeCursor.labels().contains(label));
// Node with conflict
tx.dataRead().singleNode(nodeConflicting, nodeCursor);
assertTrue(nodeCursor.next());
assertFalse(nodeCursor.labels().contains(label));
}
}
use of org.neo4j.internal.kernel.api.exceptions.schema.ConstraintValidationException in project neo4j by neo4j.
the class ConstraintTestBase method shouldCheckUniquenessWhenAddingProperties.
@Test
void shouldCheckUniquenessWhenAddingProperties() throws Exception {
// GIVEN
long nodeConflicting, nodeNotConflicting;
addConstraints("FOO", "prop");
try (org.neo4j.graphdb.Transaction tx = graphDb.beginTx()) {
Node conflict = tx.createNode();
conflict.addLabel(Label.label("FOO"));
nodeConflicting = conflict.getId();
Node ok = tx.createNode();
ok.addLabel(Label.label("BAR"));
nodeNotConflicting = ok.getId();
// Existing node
Node existing = tx.createNode();
existing.addLabel(Label.label("FOO"));
existing.setProperty("prop", 1337);
tx.commit();
}
int property;
try (KernelTransaction tx = beginTransaction()) {
property = tx.tokenWrite().propertyKeyGetOrCreateForName("prop");
// This is ok, since it will satisfy constraint
tx.dataWrite().nodeSetProperty(nodeNotConflicting, property, intValue(1337));
try {
tx.dataWrite().nodeSetProperty(nodeConflicting, property, intValue(1337));
fail();
} catch (ConstraintValidationException e) {
// ignore
}
tx.commit();
}
// Verify
try (KernelTransaction tx = beginTransaction();
NodeCursor nodeCursor = tx.cursors().allocateNodeCursor(tx.cursorContext());
PropertyCursor propertyCursor = tx.cursors().allocatePropertyCursor(tx.cursorContext(), tx.memoryTracker())) {
// Node without conflict
tx.dataRead().singleNode(nodeNotConflicting, nodeCursor);
assertTrue(nodeCursor.next());
nodeCursor.properties(propertyCursor);
assertTrue(hasKey(propertyCursor, property));
// Node with conflict
tx.dataRead().singleNode(nodeConflicting, nodeCursor);
assertTrue(nodeCursor.next());
nodeCursor.properties(propertyCursor);
assertFalse(hasKey(propertyCursor, property));
}
}
use of org.neo4j.internal.kernel.api.exceptions.schema.ConstraintValidationException in project neo4j by neo4j.
the class TransactionImpl method createNode.
@Override
public Node createNode(Label... labels) {
var ktx = kernelTransaction();
try {
TokenWrite tokenWrite = ktx.tokenWrite();
int[] labelIds = new int[labels.length];
String[] labelNames = new String[labels.length];
for (int i = 0; i < labelNames.length; i++) {
labelNames[i] = labels[i].name();
}
tokenWrite.labelGetOrCreateForNames(labelNames, labelIds);
Write write = ktx.dataWrite();
long nodeId = write.nodeCreateWithLabels(labelIds);
return newNodeEntity(nodeId);
} catch (ConstraintValidationException e) {
throw new ConstraintViolationException("Unable to add label.", e);
} catch (SchemaKernelException e) {
throw new IllegalArgumentException(e);
} catch (KernelException e) {
throw new ConstraintViolationException(e.getMessage(), e);
}
}
use of org.neo4j.internal.kernel.api.exceptions.schema.ConstraintValidationException in project neo4j by neo4j.
the class NodeEntity method addLabel.
@Override
public void addLabel(Label label) {
KernelTransaction transaction = internalTransaction.kernelTransaction();
int labelId;
try {
labelId = transaction.tokenWrite().labelGetOrCreateForName(label.name());
} catch (IllegalTokenNameException e) {
throw new ConstraintViolationException(format("Invalid label name '%s'.", label.name()), e);
} catch (TokenCapacityExceededKernelException e) {
throw new ConstraintViolationException(e.getMessage(), e);
} catch (KernelException e) {
throw new TransactionFailureException("Unknown error trying to create label token", e);
}
try {
transaction.dataWrite().nodeAddLabel(getId(), labelId);
} catch (ConstraintValidationException e) {
throw new ConstraintViolationException(e.getUserMessage(transaction.tokenRead()), e);
} catch (EntityNotFoundException e) {
throw new NotFoundException("No node with id " + getId() + " found.", e);
} catch (KernelException e) {
throw new ConstraintViolationException(e.getMessage(), e);
}
}
Aggregations