use of com.evolveum.midpoint.repo.sqale.qmodel.object.MObject in project midpoint by Evolveum.
the class SqaleRepositoryService method executeOverwriteObject.
/**
* Overwrite is more like update than add.
*/
private <T extends ObjectType> String executeOverwriteObject(@NotNull PrismObject<T> newObject) throws SchemaException, RepositoryException, ObjectAlreadyExistsException {
String oid = newObject.getOid();
UUID oidUuid = checkOid(oid);
long opHandle = registerOperationStart(OP_ADD_OBJECT_OVERWRITE, newObject);
try (JdbcSession jdbcSession = sqlRepoContext.newJdbcSession().startTransaction()) {
try {
// noinspection ConstantConditions
RootUpdateContext<T, QObject<MObject>, MObject> updateContext = prepareUpdateContext(jdbcSession, newObject.getCompileTimeClass(), oidUuid);
PrismObject<T> prismObject = updateContext.getPrismObject();
// no precondition check for overwrite
invokeConflictWatchers(w -> w.beforeModifyObject(prismObject));
newObject.setUserData(RepositoryService.KEY_ORIGINAL_OBJECT, prismObject.clone());
ObjectDelta<T> delta = prismObject.diff(newObject, EquivalenceStrategy.LITERAL);
Collection<? extends ItemDelta<?, ?>> modifications = delta.getModifications();
logger.trace("overwriteAddObjectAttempt: originalOid={}, modifications={}", oid, modifications);
Collection<? extends ItemDelta<?, ?>> executedModifications = updateContext.execute(modifications, false);
replaceObject(updateContext, updateContext.getPrismObject());
if (!executedModifications.isEmpty()) {
invokeConflictWatchers((w) -> w.afterModifyObject(oid));
}
logger.trace("OBJECT after:\n{}", prismObject.debugDumpLazily());
} catch (ObjectNotFoundException e) {
// so it is just plain addObject after all
new AddObjectContext<>(sqlRepoContext, newObject).execute(jdbcSession);
invokeConflictWatchers((w) -> w.afterAddObject(oid, newObject));
}
jdbcSession.commit();
return oid;
} catch (RuntimeException e) {
SqaleUtils.handlePostgresException(e);
throw e;
} finally {
registerOperationFinish(opHandle);
}
}
use of com.evolveum.midpoint.repo.sqale.qmodel.object.MObject in project midpoint by Evolveum.
the class SqaleRepoModifyObjectTest method test952ReindexFixingColumnsOutOfSync.
@Test
public void test952ReindexFixingColumnsOutOfSync() throws SchemaException, ObjectNotFoundException, ObjectAlreadyExistsException {
OperationResult result = createOperationResult();
given("user existing in the repository");
String name = "user" + getTestNumber();
UserType user = new UserType(prismContext).name(name).emailAddress(name + "@goodmail.com").subtype("subtype-1").subtype("subtype-2").assignment(new AssignmentType(prismContext).order(1));
String oid = repositoryService.addObject(user.asPrismObject(), null, result);
and("object aggregate is modified in the DB (simulating out-of-sync data)");
QAssignment<MObject> a = QAssignmentMapping.getAssignmentMapping().defaultAlias();
UUID oidUuid = UUID.fromString(oid);
try (JdbcSession jdbcSession = startTransaction()) {
jdbcSession.newInsert(a).set(a.ownerOid, oidUuid).set(a.cid, -1L).set(a.containerType, MContainerType.ASSIGNMENT).set(a.ownerType, MObjectType.USER).set(a.orderValue, // test number, hopefully unique
952).execute();
QUser u = QUserMapping.getUserMapping().defaultAlias();
jdbcSession.newUpdate(u).set(u.emailAddress, "bad@badmail.com").set(u.subtypes, new String[] { "subtype-952" }).set(u.costCenter, "invasive value").where(u.oid.eq(oidUuid)).execute();
jdbcSession.commit();
}
and("search provides obviously bad results");
assertThat(repositorySearchObjects(UserType.class, prismContext.queryFor(UserType.class).item(UserType.F_EMAIL_ADDRESS).eq(name + "@goodmail.com").build(), result)).isEmpty();
assertThat(repositorySearchObjects(UserType.class, prismContext.queryFor(UserType.class).item(UserType.F_COST_CENTER).eq("invasive value").build(), result)).hasSize(// can find by bad value, that's wrong
1);
assertThat(repositorySearchObjects(UserType.class, prismContext.queryFor(UserType.class).item(UserType.F_ASSIGNMENT, AssignmentType.F_ORDER).eq(952).build(), result)).hasSize(// can find by wrong assignment
1);
assertThat(repositorySearchObjects(UserType.class, prismContext.queryFor(UserType.class).item(UserType.F_SUBTYPE).eq("subtype-952").build(), result)).hasSize(// can find by wrong subtype
1);
when("reindex is called to fix it");
repositoryService.modifyObject(UserType.class, oid, Collections.emptyList(), RepoModifyOptions.createForceReindex(), result);
then("the searches work as expected");
assertThat(repositorySearchObjects(UserType.class, prismContext.queryFor(UserType.class).item(UserType.F_EMAIL_ADDRESS).eq(name + "@goodmail.com").build(), result)).hasSize(1).extracting(o -> o.getOid()).containsExactlyInAnyOrder(// can find by the original mail, that's good!
oid);
assertThat(repositorySearchObjects(UserType.class, prismContext.queryFor(UserType.class).item(UserType.F_COST_CENTER).eq("invasive value").build(), result)).isEmpty();
assertThat(repositorySearchObjects(UserType.class, prismContext.queryFor(UserType.class).item(UserType.F_ASSIGNMENT, AssignmentType.F_ORDER).eq(952).build(), result)).isEmpty();
assertThat(repositorySearchObjects(UserType.class, prismContext.queryFor(UserType.class).item(UserType.F_ASSIGNMENT, AssignmentType.F_ORDER).eq(1).build(), result)).extracting(o -> o.getOid()).contains(// good, can have more results, but our user is there too
oid);
and("database values are as good as new");
MUser userRow = selectObjectByOid(QUser.class, oid);
// tested by search above as well
assertThat(userRow.emailAddress).isEqualTo(name + "@goodmail.com");
assertThat(userRow.costCenter).isNull();
assertThat(userRow.subtypes).containsExactlyInAnyOrder("subtype-1", "subtype-2");
List<MAssignment> assRows = select(a, a.ownerOid.eq(oidUuid));
// single row with proper order is returned, wrong row is gone
assertThat(assRows).hasSize(1);
assertThat(assRows.get(0).orderValue).isEqualTo(1);
}
use of com.evolveum.midpoint.repo.sqale.qmodel.object.MObject in project midpoint by Evolveum.
the class SqaleRepositoryService method readByOid.
/**
* Read object using provided {@link JdbcSession} as a part of already running transaction.
*/
private <S extends ObjectType> S readByOid(@NotNull JdbcSession jdbcSession, @NotNull Class<S> schemaType, @NotNull UUID oid, Collection<SelectorOptions<GetOperationOptions>> options) throws SchemaException, ObjectNotFoundException {
SqaleTableMapping<S, QObject<MObject>, MObject> rootMapping = sqlRepoContext.getMappingBySchemaType(schemaType);
QObject<MObject> root = rootMapping.defaultAlias();
Tuple result = jdbcSession.newQuery().from(root).select(rootMapping.selectExpressions(root, options)).where(root.oid.eq(oid)).fetchOne();
if (result == null || result.get(root.fullObject) == null) {
throw new ObjectNotFoundException(schemaType, oid.toString());
}
return rootMapping.toSchemaObject(result, root, options, jdbcSession, false);
}
use of com.evolveum.midpoint.repo.sqale.qmodel.object.MObject in project midpoint by Evolveum.
the class SqaleRepositoryService method executeGetVersion.
private <T extends ObjectType> String executeGetVersion(Class<T> type, UUID oid) throws ObjectNotFoundException {
long opHandle = registerOperationStart(OP_GET_VERSION, type);
try (JdbcSession jdbcSession = sqlRepoContext.newJdbcSession().startReadOnlyTransaction()) {
SqaleTableMapping<T, QObject<MObject>, MObject> rootMapping = sqlRepoContext.getMappingBySchemaType(type);
QObject<MObject> root = rootMapping.defaultAlias();
Integer version = jdbcSession.newQuery().select(root.version).from(root).where(root.oid.eq(oid)).fetchOne();
if (version == null) {
throw new ObjectNotFoundException(type, oid.toString());
}
String versionString = version.toString();
invokeConflictWatchers((w) -> w.afterGetVersion(oid.toString(), versionString));
return versionString;
} finally {
registerOperationFinish(opHandle);
}
}
use of com.evolveum.midpoint.repo.sqale.qmodel.object.MObject in project midpoint by Evolveum.
the class OrgFilterProcessor method process.
@Override
public Predicate process(OrgFilter filter) throws QueryException {
// necessary for lazy refresh of org closure
context.markContainsOrgFilter();
FlexibleRelationalPathBase<?> path = context.root();
if (!(path instanceof QObject)) {
throw new QueryException("Org filter can only be used for objects," + " not for path " + path + " of type " + path.getClass());
}
QObject<?> objectPath = (QObject<?>) path;
if (filter.isRoot()) {
QObjectReference<MObject> ref = getNewRefAlias();
return subQuery(ref).where(ref.ownerOid.eq(objectPath.oid)).notExists();
}
if (filter.getOrgRef() == null) {
throw new QueryException("No organization reference defined in the search query.");
}
String oidParam = filter.getOrgRef().getOid();
if (oidParam == null) {
throw new QueryException("No oid specified in organization reference " + filter.getOrgRef().debugDump());
}
QName relation = filter.getOrgRef().getRelation();
// null means ANY (not "default") here, so we only search/normalize non-nulls
Integer relationId = relation != null ? context.repositoryContext().searchCachedRelationId(relation) : null;
if (filter.getScope() == OrgFilter.Scope.ONE_LEVEL) {
QObjectReference<MObject> ref = getNewRefAlias();
SQLQuery<?> subQuery = subQuery(ref).where(ref.ownerOid.eq(objectPath.oid).and(ref.targetOid.eq(UUID.fromString(oidParam))));
if (relationId != null) {
subQuery.where(ref.relationId.eq(relationId));
}
return subQuery.exists();
} else if (filter.getScope() == OrgFilter.Scope.SUBTREE) {
QObjectReference<MObject> ref = getNewRefAlias();
QOrgClosure oc = getNewClosureAlias();
SQLQuery<?> subQuery = subQuery(ref).join(oc).on(oc.descendantOid.eq(ref.targetOid)).where(ref.ownerOid.eq(objectPath.oid).and(oc.ancestorOid.eq(UUID.fromString(oidParam))));
if (relationId != null) {
subQuery.where(ref.relationId.eq(relationId));
}
return subQuery.exists();
} else if (filter.getScope() == OrgFilter.Scope.ANCESTORS) {
QOrgClosure oc = getNewClosureAlias();
return subQuery(oc).where(oc.ancestorOid.eq(objectPath.oid).and(oc.descendantOid.eq(UUID.fromString(oidParam))).and(oc.ancestorOid.ne(oc.descendantOid))).exists();
} else {
throw new QueryException("Unknown scope if org filter: " + filter);
}
}
Aggregations