Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
mederly committed Jul 6, 2021
2 parents b9d0551 + b3ca05c commit da752b9
Show file tree
Hide file tree
Showing 39 changed files with 438 additions and 182 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import org.jetbrains.annotations.NotNull;

import com.evolveum.midpoint.prism.query.*;
import com.evolveum.midpoint.repo.sqale.filtering.ExistsFilterProcessor;
import com.evolveum.midpoint.repo.sqale.filtering.InOidFilterProcessor;
import com.evolveum.midpoint.repo.sqale.filtering.OrgFilterProcessor;
import com.evolveum.midpoint.repo.sqale.filtering.TypeFilterProcessor;
Expand Down Expand Up @@ -71,8 +72,7 @@ public Predicate process(@NotNull ObjectFilter filter) throws RepositoryExceptio
// TODO
throw new QueryException("TODO filter " + filter);
} else if (filter instanceof ExistsFilter) {
// TODO
throw new QueryException("TODO filter " + filter);
return new ExistsFilterProcessor<>(this).process((ExistsFilter) filter);
} else if (filter instanceof TypeFilter) {
return new TypeFilterProcessor<>(this).process((TypeFilter) filter);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ private QName resolvePath(ItemPath path) {
path = path.rest();

QueryModelMapping<?, ?, ?> mapping = context.mapping();
ItemRelationResolver<?, ?> relationResolver = mapping.getRelationResolver(firstName);
ItemRelationResolver<?, ?, ?, ?> relationResolver = mapping.getRelationResolver(firstName);
if (relationResolver == null) {
return null; // unmapped, not persisted, nothing to do
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* Copyright (C) 2010-2021 Evolveum and contributors
*
* This work is dual-licensed under the Apache License 2.0
* and European Union Public License. See LICENSE file for details.
*/
package com.evolveum.midpoint.repo.sqale.filtering;

import com.querydsl.core.types.Predicate;

import com.evolveum.midpoint.prism.path.ItemPath;
import com.evolveum.midpoint.prism.query.ExistsFilter;
import com.evolveum.midpoint.prism.query.ObjectFilter;
import com.evolveum.midpoint.repo.sqale.SqaleQueryContext;
import com.evolveum.midpoint.repo.sqale.mapping.CountMappingResolver;
import com.evolveum.midpoint.repo.sqlbase.RepositoryException;
import com.evolveum.midpoint.repo.sqlbase.filtering.FilterProcessor;
import com.evolveum.midpoint.repo.sqlbase.mapping.ItemRelationResolver;
import com.evolveum.midpoint.repo.sqlbase.mapping.QueryModelMapping;
import com.evolveum.midpoint.repo.sqlbase.querydsl.FlexibleRelationalPathBase;

/**
* Filter processor that resolves {@link ExistsFilter}.
*
* @param <Q> query type of the original context
* @param <R> row type related to {@link Q}
*/
public class ExistsFilterProcessor<Q extends FlexibleRelationalPathBase<R>, R>
implements FilterProcessor<ExistsFilter> {

private final SqaleQueryContext<?, Q, R> context;
private final QueryModelMapping<?, Q, R> mapping;

public ExistsFilterProcessor(SqaleQueryContext<?, Q, R> context) {
this.context = context;
this.mapping = context.mapping();
}

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

@Override
public Predicate process(ExistsFilter filter) throws RepositoryException {
return process(filter.getFullPath(), filter);
}

private <TQ extends FlexibleRelationalPathBase<TR>, TR> Predicate process(
ItemPath path, ExistsFilter filter) throws RepositoryException {
if (path.isEmpty()) {
ObjectFilter innerFilter = filter.getFilter();

// empty filter means EXISTS, NOT can be added before the filter
return innerFilter != null
? context.process(innerFilter)
: null;
}

ItemRelationResolver<Q, R, TQ, TR> resolver = mapping.relationResolver(path.firstName());
// Instead of cleaner but arguably confusing solution that would follow the code lower
// we resolve this corner case here and now.
if (resolver instanceof CountMappingResolver<?, ?, ?>) {
return ((CountMappingResolver<?, Q, R>) resolver).createExistsPredicate(context);
}

ItemRelationResolver.ResolutionResult<TQ, TR> resolution = resolver.resolve(context);
//noinspection unchecked
SqaleQueryContext<?, TQ, TR> subcontext = (SqaleQueryContext<?, TQ, TR>) resolution.context;
ExistsFilterProcessor<TQ, TR> nestedProcessor =
new ExistsFilterProcessor<>(subcontext, resolution.mapping);
Predicate predicate = nestedProcessor.process(path.rest(), filter);
if (resolution.subquery) {
return subcontext.sqlQuery().where(predicate).exists();
} else {
return predicate;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
import com.evolveum.midpoint.repo.sqlbase.SqlQueryContext;
import com.evolveum.midpoint.repo.sqlbase.filtering.ValueFilterValues;
import com.evolveum.midpoint.repo.sqlbase.filtering.item.FilterOperation;
import com.evolveum.midpoint.repo.sqlbase.filtering.item.ItemFilterProcessor;
import com.evolveum.midpoint.repo.sqlbase.filtering.item.ItemValueFilterProcessor;
import com.evolveum.midpoint.repo.sqlbase.querydsl.FlexibleRelationalPathBase;
import com.evolveum.midpoint.util.DOMUtil;
import com.evolveum.midpoint.util.QNameUtil;
Expand All @@ -54,7 +54,7 @@
* Filter processor for extension items stored in JSONB.
* This takes care of any supported type, scalar or array, and handles any operation.
*/
public class ExtensionItemFilterProcessor extends ItemFilterProcessor<ValueFilter<?, ?>> {
public class ExtensionItemFilterProcessor extends ItemValueFilterProcessor<ValueFilter<?, ?>> {

// QName.toString produces different results, QNameUtil must be used here:
public static final String STRING_TYPE = QNameUtil.qNameToUri(DOMUtil.XSD_STRING);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public Predicate process(OrgFilter filter) throws QueryException {

if (filter.getScope() == OrgFilter.Scope.ONE_LEVEL) {
QObjectReference<MObject> ref = getNewRefAlias();
SQLQuery<Integer> subQuery = subQuery(ref)
SQLQuery<?> subQuery = subQuery(ref)
.where(ref.ownerOid.eq(objectPath.oid)
.and(ref.targetOid.eq(UUID.fromString(oidParam))));
if (relationId != null) {
Expand All @@ -80,7 +80,7 @@ public Predicate process(OrgFilter filter) throws QueryException {
} else if (filter.getScope() == OrgFilter.Scope.SUBTREE) {
QObjectReference<MObject> ref = getNewRefAlias();
QOrgClosure oc = getNewClosureAlias();
SQLQuery<Integer> subQuery = subQuery(ref)
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))));
Expand All @@ -100,7 +100,7 @@ public Predicate process(OrgFilter filter) throws QueryException {
}
}

private SQLQuery<Integer> subQuery(FlexibleRelationalPathBase<?> entityPath) {
private SQLQuery<?> subQuery(FlexibleRelationalPathBase<?> entityPath) {
return new SQLQuery<>().select(QuerydslUtils.EXPRESSION_ONE)
.from(entityPath);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
import com.evolveum.midpoint.repo.sqale.qmodel.common.QUri;
import com.evolveum.midpoint.repo.sqale.qmodel.object.MObjectType;
import com.evolveum.midpoint.repo.sqlbase.SqlQueryContext;
import com.evolveum.midpoint.repo.sqlbase.filtering.item.ItemFilterProcessor;
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;

Expand All @@ -31,7 +31,7 @@
* OID is represented by UUID column, type by ID (see {@link MObjectType} and relation
* by Integer (foreign key) to {@link QUri}.
*/
public class RefItemFilterProcessor extends ItemFilterProcessor<RefFilter> {
public class RefItemFilterProcessor extends ItemValueFilterProcessor<RefFilter> {

// only oidPath is strictly not-null, but then the filter better not ask for type or relation
private final UuidPath oidPath;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@
package com.evolveum.midpoint.repo.sqale.filtering;

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

import com.evolveum.midpoint.prism.query.RefFilter;
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.SqlQueryContext;
import com.evolveum.midpoint.repo.sqlbase.filtering.item.ItemFilterProcessor;
import com.evolveum.midpoint.repo.sqlbase.filtering.item.ItemValueFilterProcessor;
import com.evolveum.midpoint.repo.sqlbase.querydsl.FlexibleRelationalPathBase;

/**
Expand All @@ -27,7 +28,7 @@
*/
public class RefTableItemFilterProcessor<Q extends QReference<R, OR>, R extends MReference,
OQ extends FlexibleRelationalPathBase<OR>, OR>
extends ItemFilterProcessor<RefFilter> {
extends ItemValueFilterProcessor<RefFilter> {

private final SqlQueryContext<?, OQ, OR> context;
private final QReferenceMapping<Q, R, OQ, OR> referenceMapping;
Expand All @@ -41,13 +42,14 @@ public RefTableItemFilterProcessor(

@Override
public Predicate process(RefFilter filter) {
// TODO change to EXISTS to fix SqaleRepoSearchObjectTest.test401SearchObjectNotHavingSpecifiedRef
// This also fixes the number of right result for such filter, or for filter using multiple values
SqlQueryContext<?, Q, R> refContext =
context.leftJoin(referenceMapping, referenceMapping.joinOnPredicate());
QReference<?, ?> ref = refContext.path();

return new RefItemFilterProcessor(context, ref.targetOid, ref.targetType, ref.relationId)
.process(filter);
SqlQueryContext<?, Q, R> refContext = context.subquery(referenceMapping);
SQLQuery<?> subquery = refContext.sqlQuery();
Q ref = refContext.path();
return subquery
.where(referenceMapping.correlationPredicate().apply(context.path(), ref))
.where(new RefItemFilterProcessor(
context, ref.targetOid, ref.targetType, ref.relationId)
.process(filter))
.exists();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import java.util.function.BiFunction;

import com.querydsl.core.types.Predicate;
import com.querydsl.sql.SQLQuery;
import org.jetbrains.annotations.NotNull;

import com.evolveum.midpoint.prism.Containerable;
Expand All @@ -34,16 +35,16 @@
public class ContainerTableRelationResolver<
Q extends FlexibleRelationalPathBase<R>, R,
TS extends Containerable, TQ extends QContainer<TR, R> & QOwnedBy<R>, TR extends MContainer>
implements SqaleItemRelationResolver<Q, R> {
implements SqaleItemRelationResolver<Q, R, TQ, TR> {

private final QContainerMapping<TS, TQ, TR, R> targetMapping;
private final BiFunction<Q, TQ, Predicate> joinPredicate;
private final BiFunction<Q, TQ, Predicate> correlationPredicate;

public ContainerTableRelationResolver(
@NotNull QContainerMapping<TS, TQ, TR, R> targetMapping,
@NotNull BiFunction<Q, TQ, Predicate> joinPredicate) {
@NotNull BiFunction<Q, TQ, Predicate> correlationPredicate) {
this.targetMapping = targetMapping;
this.joinPredicate = joinPredicate;
this.correlationPredicate = correlationPredicate;
}

/**
Expand All @@ -54,11 +55,13 @@ public ContainerTableRelationResolver(
* @return result with context for JOINed entity path and its mapping
*/
@Override
public ResolutionResult resolve(SqlQueryContext<?, Q, R> context) {
SqlQueryContext<TS, TQ, TR> joinContext =
context.leftJoin(targetMapping.queryType(), joinPredicate);
public ResolutionResult<TQ, TR> resolve(SqlQueryContext<?, Q, R> context) {
SqlQueryContext<TS, TQ, TR> subcontext =
context.subquery(targetMapping.queryType());
SQLQuery<?> subquery = subcontext.sqlQuery();
subquery.where(correlationPredicate.apply(context.path(), subcontext.path()));

return new ResolutionResult(joinContext, joinContext.mapping());
return new ResolutionResult<>(subcontext, subcontext.mapping(), true);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Copyright (C) 2010-2021 Evolveum and contributors
*
* This work is dual-licensed under the Apache License 2.0
* and European Union Public License. See LICENSE file for details.
*/
package com.evolveum.midpoint.repo.sqale.mapping;

import java.util.function.Function;

import com.querydsl.core.types.Predicate;
import com.querydsl.core.types.dsl.NumberPath;

import com.evolveum.midpoint.prism.Containerable;
import com.evolveum.midpoint.prism.path.ItemPath;
import com.evolveum.midpoint.repo.sqale.SqaleQueryContext;
import com.evolveum.midpoint.repo.sqale.update.NestedContainerUpdateContext;
import com.evolveum.midpoint.repo.sqale.update.SqaleUpdateContext;
import com.evolveum.midpoint.repo.sqlbase.SqlQueryContext;
import com.evolveum.midpoint.repo.sqlbase.querydsl.FlexibleRelationalPathBase;

/**
* Resolver that maps the container item to the count column.
*
* @param <S> schema type for the nested container
* @param <Q> query type of entity where the mapping is nested and declared
* @param <R> row type of {@link Q}
*/
public class CountMappingResolver<S extends Containerable, Q extends FlexibleRelationalPathBase<R>, R>
implements SqaleItemRelationResolver<Q, R, Q, R> {

private final Function<Q, NumberPath<Integer>> rootToCount;

public CountMappingResolver(Function<Q, NumberPath<Integer>> rootToCount) {
this.rootToCount = rootToCount;
}

/** Should not be called, the count must be treated before this happens. */
@Override
public ResolutionResult<Q, R> resolve(SqlQueryContext<?, Q, R> context) {
throw new UnsupportedOperationException("resolution not supported for count mapping");
}

@Override
public NestedContainerUpdateContext<S, Q, R> resolve(
SqaleUpdateContext<?, Q, R> context, ItemPath ignored) {
throw new UnsupportedOperationException("TODO");
// TODO test for ShadowType.pendingOperation modification is needed
// return new NestedContainerUpdateContext<>(context, mapping);
}

/** This creates the predicate representing the EXISTS filter. */
public Predicate createExistsPredicate(SqaleQueryContext<?, Q, R> context) {
return rootToCount.apply(context.path()).gt(0);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import com.evolveum.midpoint.prism.query.ObjectFilter;
import com.evolveum.midpoint.prism.query.ValueFilter;
import com.evolveum.midpoint.repo.sqale.delta.ItemDeltaProcessor;
import com.evolveum.midpoint.repo.sqale.delta.item.ExtensionItemDeltaProcessor;
import com.evolveum.midpoint.repo.sqale.filtering.ExtensionItemFilterProcessor;
import com.evolveum.midpoint.repo.sqale.jsonb.JsonbPath;
import com.evolveum.midpoint.repo.sqale.qmodel.ext.MExtItemHolderType;
import com.evolveum.midpoint.repo.sqale.update.SqaleUpdateContext;
import com.evolveum.midpoint.repo.sqlbase.SqlQueryContext;
import com.evolveum.midpoint.repo.sqlbase.filtering.item.ItemFilterProcessor;
import com.evolveum.midpoint.repo.sqlbase.filtering.item.ItemValueFilterProcessor;
import com.evolveum.midpoint.repo.sqlbase.querydsl.FlexibleRelationalPathBase;

/**
Expand Down Expand Up @@ -57,10 +57,10 @@ public ExtensionItemSqlMapper(
}

@Override
public @Nullable <T extends ObjectFilter> ItemFilterProcessor<T> createFilterProcessor(
public @Nullable <T extends ValueFilter<?, ?>> ItemValueFilterProcessor<T> createFilterProcessor(
SqlQueryContext<?, ?, ?> sqlQueryContext) {
//noinspection unchecked
return (ItemFilterProcessor<T>) new ExtensionItemFilterProcessor(
return (ItemValueFilterProcessor<T>) new ExtensionItemFilterProcessor(
sqlQueryContext,
(Function<FlexibleRelationalPathBase<?>, JsonbPath>) rootToExtensionPath,
holderType);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
* @param <R> row type of {@link Q}
*/
public class ExtensionMappingResolver<Q extends FlexibleRelationalPathBase<R>, R>
implements SqaleItemRelationResolver<Q, R> {
implements SqaleItemRelationResolver<Q, R, Q, R> {

private final ExtensionMapping<Q, R> mapping;
private final Function<Q, JsonbPath> rootToExtensionPath;
Expand All @@ -38,9 +38,9 @@ public ExtensionMappingResolver(

/** Returns the same context and nested mapping. */
@Override
public ResolutionResult resolve(SqlQueryContext<?, Q, R> context) {
public ResolutionResult<Q, R> resolve(SqlQueryContext<?, Q, R> context) {
// Needed item definition comes in the filter, no need for sub-context, mapping is enough.
return new ResolutionResult(context, mapping);
return new ResolutionResult<>(context, mapping);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
* @param <R> row type of {@link Q}
*/
public class NestedMappingResolver<S extends Containerable, Q extends FlexibleRelationalPathBase<R>, R>
implements SqaleItemRelationResolver<Q, R> {
implements SqaleItemRelationResolver<Q, R, Q, R> {

private final SqaleNestedMapping<S, Q, R> mapping;

Expand All @@ -31,8 +31,8 @@ public NestedMappingResolver(SqaleNestedMapping<S, Q, R> mapping) {

/** Returns the same context and nested mapping. */
@Override
public ResolutionResult resolve(SqlQueryContext<?, Q, R> context) {
return new ResolutionResult(context, mapping);
public ResolutionResult<Q, R> resolve(SqlQueryContext<?, Q, R> context) {
return new ResolutionResult<>(context, mapping);
}

@Override
Expand Down

0 comments on commit da752b9

Please sign in to comment.