Skip to content

Commit

Permalink
MID-4048: Added support in PG native repository for ref with subfilter
Browse files Browse the repository at this point in the history
  • Loading branch information
tonydamage committed May 25, 2022
1 parent 2ba24df commit 0671064
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
package com.evolveum.midpoint.repo.sqale.filtering;

import java.util.List;
import java.util.Optional;
import java.util.UUID;
import java.util.function.Function;

Expand All @@ -21,14 +22,18 @@

import com.evolveum.midpoint.prism.PrismConstants;
import com.evolveum.midpoint.prism.PrismReferenceValue;
import com.evolveum.midpoint.prism.query.ObjectFilter;
import com.evolveum.midpoint.prism.query.RefFilter;
import com.evolveum.midpoint.repo.sqale.SqaleQueryContext;
import com.evolveum.midpoint.repo.sqale.qmodel.common.QUri;
import com.evolveum.midpoint.repo.sqale.qmodel.object.MObjectType;
import com.evolveum.midpoint.repo.sqale.qmodel.object.QObject;
import com.evolveum.midpoint.repo.sqlbase.RepositoryException;
import com.evolveum.midpoint.repo.sqlbase.SqlQueryContext;
import com.evolveum.midpoint.repo.sqlbase.filtering.item.ItemValueFilterProcessor;
import com.evolveum.midpoint.repo.sqlbase.querydsl.FlexibleRelationalPathBase;
import com.evolveum.midpoint.repo.sqlbase.querydsl.UuidPath;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType;

/**
* Filter processor for reference item paths embedded in table as three columns.
Expand Down Expand Up @@ -71,7 +76,7 @@ <Q extends FlexibleRelationalPathBase<R>, R> RefItemFilterProcessor(
}

@Override
public Predicate process(RefFilter filter) {
public Predicate process(RefFilter filter) throws RepositoryException {
if (filter instanceof RefFilterWithRepoPath) {
return processRepoFilter((RefFilterWithRepoPath) filter);
}
Expand All @@ -81,17 +86,40 @@ public Predicate process(RefFilter filter) {
if (values == null || values.isEmpty()) {
return filter.isOidNullAsAny() ? null : oidPath.isNull();
}
Predicate predicate = null;
ObjectFilter targetFilter = filter.getFilter();
if (values.size() == 1) {
return processSingleValue(filter, values.get(0));
var value = values.get(0);
predicate = processSingleValue(filter, value);
if (targetFilter != null) {
var targetType = Optional.ofNullable(value.getTargetType()).orElse(filter.getDefinition().getTargetTypeName());
predicate = ExpressionUtils.and(predicate, targetFilterPredicate(targetType,targetFilter));
}
return predicate;
} else {
for (PrismReferenceValue ref : values) {
predicate = ExpressionUtils.or(predicate, processSingleValue(filter, ref));
}
}

Predicate predicate = null;
for (PrismReferenceValue ref : values) {
predicate = ExpressionUtils.or(predicate, processSingleValue(filter, ref));

if (targetFilter != null) {
predicate = ExpressionUtils.and(predicate, targetFilterPredicate(filter.getDefinition().getTargetTypeName(),targetFilter));
}

return predicate;
}

private Predicate targetFilterPredicate(@Nullable QName targetType, ObjectFilter targetFilter) throws RepositoryException {
targetType = targetType != null ? targetType : ObjectType.COMPLEX_TYPE;
var targetClass = targetType != null ? context.prismContext().getSchemaRegistry().getCompileTimeClassForObjectType(targetType) : ObjectType.class;
var subquery = context.subquery(context.repositoryContext().getMappingBySchemaType(targetClass));
var targetPath = subquery.path(QObject.class);
subquery.sqlQuery().where(oidPath.eq(targetPath.oid));
subquery.processFilter(targetFilter);
return subquery.sqlQuery().exists();
}

/**
* Process reference filter used in {@link ReferencedByFilterProcessor}.
*
Expand Down Expand Up @@ -128,7 +156,6 @@ private Predicate processSingleValue(RefFilter filter, PrismReferenceValue ref)
predicateWithNotTreated(targetNamePath,
targetNamePath.eq(ref.getTargetName().getOrig())));
}

return predicate;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import com.evolveum.midpoint.repo.sqale.qmodel.ref.MReference;
import com.evolveum.midpoint.repo.sqale.qmodel.ref.QReference;
import com.evolveum.midpoint.repo.sqale.qmodel.ref.QReferenceMapping;
import com.evolveum.midpoint.repo.sqlbase.RepositoryException;
import com.evolveum.midpoint.repo.sqlbase.SqlQueryContext;
import com.evolveum.midpoint.repo.sqlbase.filtering.item.ItemValueFilterProcessor;
import com.evolveum.midpoint.repo.sqlbase.querydsl.FlexibleRelationalPathBase;
Expand Down Expand Up @@ -41,7 +42,7 @@ public RefTableItemFilterProcessor(
}

@Override
public Predicate process(RefFilter filter) {
public Predicate process(RefFilter filter) throws RepositoryException {
SqlQueryContext<?, Q, R> refContext = context.subquery(referenceMapping);
SQLQuery<?> subquery = refContext.sqlQuery();
Q ref = refContext.path();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,38 +7,25 @@
package com.evolveum.midpoint.repo.sqale.filtering;

import com.querydsl.core.types.Predicate;
import com.querydsl.sql.SQLQuery;

import javax.xml.namespace.QName;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import com.evolveum.midpoint.prism.ComplexTypeDefinition;
import com.evolveum.midpoint.prism.PrismConstants;
import com.evolveum.midpoint.prism.PrismContainerDefinition;
import com.evolveum.midpoint.prism.path.ItemPath;
import com.evolveum.midpoint.prism.path.ObjectReferencePathSegment;
import com.evolveum.midpoint.prism.path.ParentPathSegment;
import com.evolveum.midpoint.prism.query.ExistsFilter;
import com.evolveum.midpoint.prism.query.ObjectFilter;
import com.evolveum.midpoint.prism.query.OwnedByFilter;
import com.evolveum.midpoint.prism.query.ReferencedByFilter;
import com.evolveum.midpoint.repo.sqale.SqaleQueryContext;
import com.evolveum.midpoint.repo.sqale.mapping.CountMappingResolver;
import com.evolveum.midpoint.repo.sqale.qmodel.object.QObject;
import com.evolveum.midpoint.repo.sqale.qmodel.ref.QObjectReference;
import com.evolveum.midpoint.repo.sqale.qmodel.object.QObjectMapping;
import com.evolveum.midpoint.repo.sqlbase.QueryException;
import com.evolveum.midpoint.repo.sqlbase.RepositoryException;
import com.evolveum.midpoint.repo.sqlbase.SqlQueryContext;
import com.evolveum.midpoint.repo.sqlbase.filtering.FilterProcessor;
import com.evolveum.midpoint.repo.sqlbase.mapping.ItemRelationResolver;
import com.evolveum.midpoint.repo.sqlbase.mapping.ItemRelationResolver.ResolutionResult;
import com.evolveum.midpoint.repo.sqlbase.mapping.QueryModelMapping;
import com.evolveum.midpoint.repo.sqlbase.mapping.QueryTableMapping;
import com.evolveum.midpoint.repo.sqlbase.mapping.TableRelationResolver;
import com.evolveum.midpoint.repo.sqlbase.querydsl.FlexibleRelationalPathBase;
import com.evolveum.midpoint.repo.sqlbase.querydsl.QuerydslUtils;

import com.evolveum.midpoint.repo.sqlbase.querydsl.UuidPath;

/**
Expand All @@ -50,19 +37,11 @@
public class ReferencedByFilterProcessor<Q extends FlexibleRelationalPathBase<R>, R>
implements FilterProcessor<ReferencedByFilter> {

private static final ItemPath TARGET = ItemPath.create(new ParentPathSegment());
private final SqaleQueryContext<?, Q, R> context;
private final QueryModelMapping<?, Q, R> mapping;

public ReferencedByFilterProcessor(SqaleQueryContext<?, Q, R> context) {
public ReferencedByFilterProcessor(SqaleQueryContext<?, Q, R> context) throws QueryException {
QueryException.check(context.mapping() instanceof QObjectMapping, "ReferencedBy can only be used on object");
this.context = context;
this.mapping = context.mapping();
}

private ReferencedByFilterProcessor(
SqaleQueryContext<?, Q, R> context, QueryModelMapping<?, Q, R> mapping) {
this.context = context;
this.mapping = mapping;
}

@Override
Expand All @@ -80,7 +59,6 @@ private <TQ extends FlexibleRelationalPathBase<TR>, TR> Predicate process(
// We use our package private RefFilter and logic in existing ref filter implementation
// to sneak OID from parent
targetContext.processFilter(internalRefFilter(path, relation,context.path(QObject.class).oid));

// We add nested filter for referencing object
targetContext.processFilter(innerFilter);
return targetContext.sqlQuery().exists();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2505,5 +2505,21 @@ public void test980findRoleByAssignmentOfUser() throws Exception {
display(queryRecorder.getQueryBuffer().toString());
}
}

@Test
public void test981findUserByAssignmentTarget() throws Exception {
queryRecorder.clearBufferAndStartRecording();
try {
searchObjectTest("User by Assignment targetRef with ref and target subfilter", UserType.class, f ->
f.ref(ItemPath.create(F_ASSIGNMENT, AssignmentType.F_TARGET_REF), RoleType.COMPLEX_TYPE, relation2)
.item(RoleType.F_NAME).eq("role-ass-vs-ind")
,
user3Oid
);
} finally {
queryRecorder.stopRecording();
display(queryRecorder.getQueryBuffer().toString());
}
}
// endregion
}

0 comments on commit 0671064

Please sign in to comment.