Skip to content

Commit

Permalink
repo-sqale: implemented deletion of container by value + test
Browse files Browse the repository at this point in the history
Solution is different then in old repo but very simple, new method
RootUpdateContext#resolveContainerIdsForDeletedValues adds the IDs
so the DB related code handles only "by CID" case.
  • Loading branch information
virgo47 committed Apr 29, 2021
1 parent a19971c commit 30eac25
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 19 deletions.
Expand Up @@ -16,13 +16,10 @@
import com.evolveum.midpoint.repo.sqale.qmodel.common.QContainerMapping;

/**
* Update context for owned containers stored in tables.
* Update context for multi-value containers stored in separate table.
* This can be owned by the root object or another container.
* TODO - this is theory, before implementation:
* Updates are collected as the modifications are processed and then executed by the root context.
* Inserts are executed immediately to allow nested inserts (e.g. container inside the container).
*
* @param <S> schema type of the object stored in the owned (child) table
* @param <S> schema type of the container stored in the owned table
* @param <Q> type of entity path for the owned (child) table
* @param <R> row type related to the {@link Q}
* @param <OR> owner row type
Expand Down
Expand Up @@ -16,7 +16,7 @@
/**
* Update context for nested containers stored in the same table used by the parent context.
*
* @param <S> schema type of the object mapped by nested mapping
* @param <S> schema type of the container mapped by the nested mapping
* @param <Q> entity query type that holds the data for the mapped attributes
* @param <R> row type related to the {@link Q}
*/
Expand Down
Expand Up @@ -14,7 +14,7 @@
import com.querydsl.core.types.Path;
import com.querydsl.sql.dml.SQLUpdateClause;

import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.*;
import com.evolveum.midpoint.prism.delta.ItemDelta;
import com.evolveum.midpoint.prism.equivalence.EquivalenceStrategy;
import com.evolveum.midpoint.repo.sqale.ContainerValueIdGenerator;
Expand All @@ -32,8 +32,7 @@
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType;

/**
* TODO
* Adds execute that processes the modifications and finalizes the update of root entity.
* Root context of the update context tree, see {@link SqaleUpdateContext} for more information.
*
* @param <S> schema type
* @param <Q> type of entity path
Expand Down Expand Up @@ -111,11 +110,33 @@ public QueryTableMapping<S, Q, R> mapping() {
private void processModification(ItemDelta<?, ?> modification)
throws RepositoryException, SchemaException {
cidGenerator.processModification(modification);
resolveContainerIdsForDeletedValues(modification);
modification.applyTo(getPrismObject());

new DelegatingItemDeltaProcessor(this).process(modification);
}

private void resolveContainerIdsForDeletedValues(ItemDelta<?, ?> modification) {
if (!modification.isDelete()) {
return;
}

PrismContainer<Containerable> container =
getPrismObject().findContainer(modification.getPath());
if (container != null) {
for (PrismValue value : modification.getValuesToDelete()) {
//noinspection unchecked
PrismContainerValue<Containerable> pcv = (PrismContainerValue<Containerable>) value;
if (pcv.getId() == null) {
PrismContainerValue<Containerable> existingValue = container.findValue(
pcv, EquivalenceStrategy.REAL_VALUE_CONSIDER_DIFFERENT_IDS);
// We will set CID and use that for DB updates.
pcv.setId(existingValue.getId());
}
}
}
}

/**
* Executes all necessary SQL updates (including sub-entity inserts/deletes)
* for the enclosed {@link #object}.
Expand Down
Expand Up @@ -1881,7 +1881,46 @@ public void test304MultipleModificationsOfExistingAssignment()
}

@Test
public void test305AddingAssignmentWithNewPrefilledCid()
public void test305DeleteAssignmentByContent()
throws ObjectAlreadyExistsException, ObjectNotFoundException, SchemaException {
OperationResult result = createOperationResult();
MUser originalRow = selectObjectByOid(QUser.class, user1Oid);

given("delta deleting assignments without CID by equality for user 1");
ObjectDelta<UserType> delta = prismContext.deltaFor(UserType.class)
.item(UserType.F_ASSIGNMENT)
.delete(new AssignmentType(prismContext).order(50))
.asObjectDelta(user1Oid);

when("modifyObject is called");
repositoryService.modifyObject(UserType.class, user1Oid, delta.getModifications(), result);

then("operation is successful");
assertThatOperationResult(result).isSuccess();

and("serialized form (fullObject) is updated and assignments with only order 50");
UserType userObject = repositoryService.getObject(UserType.class, user1Oid, null, result)
.asObjectable();
assertThat(userObject.getVersion()).isEqualTo(String.valueOf(originalRow.version + 1));
List<AssignmentType> assignments = userObject.getAssignment();
assertThat(assignments).hasSize(2)
.anyMatch(a -> a.getOrder().equals(47))
// this one had order AND target ref, so it's no match
.anyMatch(ass -> ass.getOrder() == 50 && ass.getTargetRef() != null);

and("corresponding assignment row is deleted");
MUser row = selectObjectByOid(QUser.class, user1Oid);
assertThat(row.version).isEqualTo(originalRow.version + 1);

QAssignment<?> a = QAssignmentMapping.INSTANCE.defaultAlias();
List<MAssignment> aRows = select(a, a.ownerOid.eq(UUID.fromString(user1Oid)));
assertThat(aRows).hasSize(2)
.anyMatch(aRow -> aRow.orderValue.equals(47))
.anyMatch(ass -> ass.orderValue == 50 && ass.targetRefTargetOid != null);
}

@Test
public void test310AddingAssignmentWithNewPrefilledCid()
throws ObjectAlreadyExistsException, ObjectNotFoundException, SchemaException {
OperationResult result = createOperationResult();
MUser originalRow = selectObjectByOid(QUser.class, user1Oid);
Expand All @@ -1905,7 +1944,7 @@ public void test305AddingAssignmentWithNewPrefilledCid()
.asObjectable();
assertThat(userObject.getVersion()).isEqualTo(String.valueOf(originalRow.version + 1));
List<AssignmentType> assignments = userObject.getAssignment();
assertThat(assignments).hasSize(4)
assertThat(assignments).hasSize(3)
.anyMatch(a -> a.getId().equals(originalRow.containerIdSeq));

and("new assignment row is created");
Expand All @@ -1915,13 +1954,13 @@ public void test305AddingAssignmentWithNewPrefilledCid()

QAssignment<?> a = QAssignmentMapping.INSTANCE.defaultAlias();
List<MAssignment> aRows = select(a, a.ownerOid.eq(UUID.fromString(user1Oid)));
assertThat(aRows).hasSize(4)
assertThat(aRows).hasSize(3)
.anyMatch(aRow -> aRow.cid.equals(originalRow.containerIdSeq)
&& aRow.orderValue == 1);
}

@Test
public void test306DeleteAssignmentByCid()
public void test311DeleteAssignmentByCid()
throws ObjectAlreadyExistsException, ObjectNotFoundException, SchemaException {
OperationResult result = createOperationResult();
MUser originalRow = selectObjectByOid(QUser.class, user1Oid);
Expand All @@ -1944,7 +1983,7 @@ public void test306DeleteAssignmentByCid()
.asObjectable();
assertThat(userObject.getVersion()).isEqualTo(String.valueOf(originalRow.version + 1));
List<AssignmentType> assignments = userObject.getAssignment();
assertThat(assignments).hasSize(3)
assertThat(assignments).hasSize(2)
.noneMatch(a -> a.getId().equals(originalRow.containerIdSeq - 1));

and("new assignment row is created");
Expand All @@ -1954,12 +1993,12 @@ public void test306DeleteAssignmentByCid()

QAssignment<?> a = QAssignmentMapping.INSTANCE.defaultAlias();
List<MAssignment> aRows = select(a, a.ownerOid.eq(UUID.fromString(user1Oid)));
assertThat(aRows).hasSize(3)
assertThat(aRows).hasSize(2)
.noneMatch(aRow -> aRow.cid.equals(originalRow.containerIdSeq - 1));
}

@Test
public void test307AddingAssignmentWithUsedBytFreeCid()
public void test312AddingAssignmentWithUsedBytFreeCid()
throws ObjectAlreadyExistsException, ObjectNotFoundException, SchemaException {
OperationResult result = createOperationResult();
MUser originalRow = selectObjectByOid(QUser.class, user1Oid);
Expand All @@ -1984,7 +2023,7 @@ public void test307AddingAssignmentWithUsedBytFreeCid()
.asObjectable();
assertThat(userObject.getVersion()).isEqualTo(String.valueOf(originalRow.version + 1));
List<AssignmentType> assignments = userObject.getAssignment();
assertThat(assignments).hasSize(4)
assertThat(assignments).hasSize(3)
.anyMatch(a -> a.getId().equals(originalRow.containerIdSeq - 1));

and("new assignment row is created");
Expand All @@ -1994,15 +2033,15 @@ public void test307AddingAssignmentWithUsedBytFreeCid()

QAssignment<?> a = QAssignmentMapping.INSTANCE.defaultAlias();
List<MAssignment> aRows = select(a, a.ownerOid.eq(UUID.fromString(user1Oid)));
assertThat(aRows).hasSize(4)
assertThat(aRows).hasSize(3)
.anyMatch(aRow -> aRow.cid.equals(originalRow.containerIdSeq - 1)
&& aRow.orderValue == 1);
}

// TODO delete by pattern - as per ItemImpl.remove(V, EquivalenceStrategy)

@Test
public void test309DeleteAllAssignments()
public void test319DeleteAllAssignments()
throws ObjectAlreadyExistsException, ObjectNotFoundException, SchemaException {
OperationResult result = createOperationResult();
MUser originalRow = selectObjectByOid(QUser.class, user1Oid);
Expand Down

0 comments on commit 30eac25

Please sign in to comment.