Skip to content

UPDATE statement corrupts Composite unique index on (STRING, INTEGER) properties #812

@vic0824

Description

@vic0824

ArcadeDB Version: v23.1.2-SNAPSHOT (build 75a9319/1674650185130/main)

JDK Version: openjdk version "11.0.12" 2021-07-20 LTS

OS: Windows 10 Enterprise 22H2

Expected behavior

a composite unique index on (STRING, INTEGER) properties is correctly updated when an UPDATE statement is executed to modify the value of one of the indexed properties.

Actual behavior

If the value of one of the indexed properties is updated (preserving the uniqueness), a DuplicatedKeyException is thrown, showing that the indexed value of the other property was null, instead of the correct value. The value of the other property guaranteed the uniqueness, so by replacing the correct value with null, the engine has created the conditions for a duplicate key.

Steps to reproduce

  1. Create a database
  2. Create a document type
  3. Create 3 properties associated to the Document type: id (INTEGER), processor (STRING), status (STRING)
  4. Create a composite unique index on (status, id)
  5. Insert two documents into the type: {"id":"1","status":"PENDING","processor":"SIR1LRM-7.1"} and {"id":"2","status":"PENDING","processor":"SIR1LRM-7.1"} (this should add two entries into the index: [PENDING, 1] and [PENDING, 2])
  6. update the document with id = 1, setting the status value to "ERROR" (this should update the index, which should now contain [ERROR, 1] and [PENDING, 2])
  7. update the document with id = 2, setting the status value to "ERROR" (this should update the index, which should now contain [ERROR, 1] and [ERROR, 2])
  8. verify that the following exception is thrown: com.arcadedb.exception.DuplicatedKeyException: Duplicated key [ERROR, null] found on index 'Order[status,id]' already assigned to record #1:0 and that the second update has been rolled back
  9. repeat the test, reversing the order of the properties in the index, i.e. creating an index on (id, status), and verify that the second update is performed correctly and no exception is thrown

The attached testCompositeIndex method demonstrates steps 1 - 8 and produces the following result:

INSERT INTO Order SET id = ?, status = ?, processor = ?; parameters: 1, SIR1LRM-7.1, PENDING
result = {"id":"1","status":"PENDING","processor":"SIR1LRM-7.1","@cat":"d","@type":"Order","@rid":"#1:0"}
INSERT INTO Order SET id = ?, status = ?, processor = ?; parameters: 2, SIR1LRM-7.1, PENDING
result = {"id":"2","status":"PENDING","processor":"SIR1LRM-7.1","@cat":"d","@type":"Order","@rid":"#2:0"}
UPDATE Order SET status = ? RETURN AFTER WHERE id = ?, parameters: [ERROR, 1]
result = {"id":"1","status":"ERROR","processor":"SIR1LRM-7.1","@cat":"d","@type":"Order","@rid":"#1:0"}
UPDATE Order SET status = ? RETURN AFTER WHERE id = ?, parameters: [ERROR, 2]
result = {"id":"2","status":"ERROR","processor":"SIR1LRM-7.1","@cat":"d","@type":"Order","@rid":"#2:0"}
Exception in thread "main" com.arcadedb.exception.DuplicatedKeyException: Duplicated key [ERROR, null] found on index 'Order[status,id]' already assigned to record #1:0
	at com.arcadedb.database.TransactionIndexContext.checkUniqueIndexKeys(TransactionIndexContext.java:338)
	at com.arcadedb.database.TransactionIndexContext.checkUniqueIndexKeys(TransactionIndexContext.java:373)
	at com.arcadedb.database.TransactionIndexContext.commit(TransactionIndexContext.java:162)
	at com.arcadedb.database.TransactionContext.commit1stPhase(TransactionContext.java:479)
	at com.arcadedb.database.TransactionContext.commit(TransactionContext.java:114)
	at com.arcadedb.database.EmbeddedDatabase.lambda$commit$2(EmbeddedDatabase.java:366)
	at com.arcadedb.database.EmbeddedDatabase.executeInReadLock(EmbeddedDatabase.java:1326)
	at com.arcadedb.database.EmbeddedDatabase.commit(EmbeddedDatabase.java:361)
	at com.arcadedb.database.EmbeddedDatabase.transaction(EmbeddedDatabase.java:1000)
	at com.arcadedb.database.EmbeddedDatabase.transaction(EmbeddedDatabase.java:965)
	at com.arcadedb.server.ServerDatabase.transaction(ServerDatabase.java:301)
	at eu.serco.csrs.persistence.ArcadeDBTest.testCompositeIndex(ArcadeDBTest.java:153)
	at eu.serco.csrs.persistence.ArcadeDBTest.main(ArcadeDBTest.java:67)

testCompositeIndex.zip

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions