Search in sources :

Example 1 with S_MatchingRuleEntry

use of com.evolveum.midpoint.prism.query.builder.S_MatchingRuleEntry in project midpoint by Evolveum.

the class SqaleAuditService method iterativeSearchCondition.

/**
 * Similar to {@link SqaleRepositoryService#lastOidCondition}.
 *
 * TODO, lots of possible improvements:
 *
 * * Just like in repo iterative search this is added to the original filter with `AND`.
 * However, if `timestamp` is used in the original filter, it could be replaced by stricter
 * `timestamp` condition based on the `lastProcessedObject` - this is not implemented yet.
 * ** TODO: If provided, do we want to add another timestamp condition?
 * Would it help with partitions?
 * Probably, with ID condition + ordering, it's not a big deal to leave it out.
 *
 * * Support for multiple order specifications from the client is not supported.
 * Perhaps some short-term stateful filter/order object would be better to construct this,
 * especially if it could be used in both repo and audit (with strict order attribute
 * provided in constructor for example).
 *
 * [NOTE]
 * ====
 * Both `timestamp` and `repoId` is used for iterative search condition, but *only `repoId`*
 * is used for additional ordering to assure strict reliable ordering.
 * This can be further complicated by the fact that both `repoId` and `timestamp`
 * can be part of custom ordering from client (this is different from repository, where `oid`
 * is not valid for filter and ordering on the model level, even when it's usable for repository).
 * If used on the top-level `AND` group, they can be be replaced by next iteration condition,
 * which is likely more selective.
 *
 * As for the ordering, if multiple ordering is used (*not supported yet*) if `repoId` is used,
 * anything after it can be omitted as irrelevant.
 * ====
 *
 * TODO: Currently, single path ordering is supported. Finish multi-path too.
 * TODO: What about nullable columns?
 */
@Nullable
private ObjectFilter iterativeSearchCondition(@Nullable AuditEventRecordType lastProcessedObject, List<? extends ObjectOrdering> providedOrdering) {
    if (lastProcessedObject == null) {
        return null;
    }
    // TODO inspect originalFilter to detect timestamp/repoId conditions.
    // Only top level AND filter should be checked, anything else is irrelevant
    // for the decision whether to skip additional timestamp condition.
    // BTW: We CANNOT skip repoId condition, that one is CRITICAL for proper iterating.
    Long lastProcessedId = lastProcessedObject.getRepoId();
    XMLGregorianCalendar lastProcessedTimestamp = lastProcessedObject.getTimestamp();
    if (providedOrdering == null || providedOrdering.isEmpty()) {
        return prismContext().queryFor(AuditEventRecordType.class).item(AuditEventRecordType.F_REPO_ID).gt(lastProcessedId).and().item(AuditEventRecordType.F_TIMESTAMP).ge(lastProcessedTimestamp).buildFilter();
    }
    if (providedOrdering.size() == 1) {
        ObjectOrdering objectOrdering = providedOrdering.get(0);
        ItemPath orderByPath = objectOrdering.getOrderBy();
        boolean asc = objectOrdering.getDirection() == OrderDirection.ASCENDING;
        S_ConditionEntry filter = prismContext().queryFor(AuditEventRecordType.class).item(orderByPath);
        @SuppressWarnings("unchecked") Item<PrismValue, ItemDefinition<?>> item = lastProcessedObject.asPrismContainerValue().findItem(orderByPath);
        if (item.size() > 1) {
            throw new IllegalArgumentException("Multi-value property for ordering is forbidden - item: " + item);
        } else if (item.isEmpty()) {
        // TODO what if it's nullable? is it null-first or last?
        // See: https://www.postgresql.org/docs/13/queries-order.html
        // "By default, null values sort as if larger than any non-null value; that is,
        // NULLS FIRST is the default for DESC order, and NULLS LAST otherwise."
        } else {
            S_MatchingRuleEntry matchingRuleEntry = asc ? filter.gt(item.getRealValue()) : filter.lt(item.getRealValue());
            filter = matchingRuleEntry.or().block().item(orderByPath).eq(item.getRealValue()).and().item(AuditEventRecordType.F_REPO_ID);
            return (asc ? filter.gt(lastProcessedId) : filter.lt(lastProcessedId)).endBlock().buildFilter();
        }
    }
    throw new IllegalArgumentException("Shouldn't get here with check in executeSearchObjectsIterative()");
}
Also used : S_ConditionEntry(com.evolveum.midpoint.prism.query.builder.S_ConditionEntry) ItemDefinition(com.evolveum.midpoint.prism.ItemDefinition) S_MatchingRuleEntry(com.evolveum.midpoint.prism.query.builder.S_MatchingRuleEntry) PrismValue(com.evolveum.midpoint.prism.PrismValue) XMLGregorianCalendar(javax.xml.datatype.XMLGregorianCalendar) AuditEventRecordType(com.evolveum.midpoint.xml.ns._public.common.audit_3.AuditEventRecordType) CanonicalItemPath(com.evolveum.midpoint.prism.path.CanonicalItemPath) ItemPath(com.evolveum.midpoint.prism.path.ItemPath) Nullable(org.jetbrains.annotations.Nullable)

Example 2 with S_MatchingRuleEntry

use of com.evolveum.midpoint.prism.query.builder.S_MatchingRuleEntry in project midpoint by Evolveum.

the class NodeFoundDeadHelper method markTasksAsNotRunning.

/**
 * We know that the specified nodes went from `UP` to the `DOWN` state. So we want to mark the relevant
 * tasks as not running on these nodes.
 */
void markTasksAsNotRunning(Set<String> nodes, OperationResult result) throws SchemaException {
    Iterator<String> iterator = nodes.iterator();
    if (!iterator.hasNext()) {
        return;
    }
    // TODO create a utility method to create multi-valued "eq" disjunction
    S_MatchingRuleEntry q = PrismContext.get().queryFor(TaskType.class).item(TaskType.F_NODE).eq(iterator.next());
    while (iterator.hasNext()) {
        q = q.or().item(TaskType.F_NODE).eq(iterator.next());
    }
    ObjectQuery query = q.build();
    List<PrismObject<TaskType>> tasksOnDeadNodes = repositoryService.searchObjects(TaskType.class, query, null, result);
    LOGGER.info("Going to mark tasks as not running:\n{}\n{}", DebugUtil.debugDumpLazily(query, 1), DebugUtil.debugDumpLazily(tasksOnDeadNodes, 1));
    for (PrismObject<TaskType> task : tasksOnDeadNodes) {
        try {
            markTaskAsNotRunning(task, nodes, result);
        } catch (Exception e) {
            LoggingUtils.logException(LOGGER, "Task couldn't be marked as not running: {}", e, task);
        // We continue to mark the other tasks as not running
        }
    }
}
Also used : PrismObject(com.evolveum.midpoint.prism.PrismObject) TaskType(com.evolveum.midpoint.xml.ns._public.common.common_3.TaskType) S_MatchingRuleEntry(com.evolveum.midpoint.prism.query.builder.S_MatchingRuleEntry) ObjectQuery(com.evolveum.midpoint.prism.query.ObjectQuery) SchemaException(com.evolveum.midpoint.util.exception.SchemaException) CommonException(com.evolveum.midpoint.util.exception.CommonException)

Example 3 with S_MatchingRuleEntry

use of com.evolveum.midpoint.prism.query.builder.S_MatchingRuleEntry in project midpoint by Evolveum.

the class SqlAuditServiceImpl method iterativeSearchCondition.

/**
 * See {@code SqaleRepositoryService.iterativeSearchCondition()} for more info.
 * This is unsupported version only for Ninja usage.
 */
@Nullable
private ObjectFilter iterativeSearchCondition(@Nullable AuditEventRecordType lastProcessedObject, List<? extends ObjectOrdering> providedOrdering) {
    if (lastProcessedObject == null) {
        return null;
    }
    Long lastProcessedId = lastProcessedObject.getRepoId();
    XMLGregorianCalendar lastProcessedTimestamp = lastProcessedObject.getTimestamp();
    if (providedOrdering == null || providedOrdering.isEmpty()) {
        return schemaService.prismContext().queryFor(AuditEventRecordType.class).item(AuditEventRecordType.F_REPO_ID).gt(lastProcessedId).and().item(AuditEventRecordType.F_TIMESTAMP).ge(lastProcessedTimestamp).buildFilter();
    }
    if (providedOrdering.size() == 1) {
        ObjectOrdering objectOrdering = providedOrdering.get(0);
        ItemPath orderByPath = objectOrdering.getOrderBy();
        boolean asc = objectOrdering.getDirection() == OrderDirection.ASCENDING;
        S_ConditionEntry filter = schemaService.prismContext().queryFor(AuditEventRecordType.class).item(orderByPath);
        @SuppressWarnings("unchecked") Item<PrismValue, ItemDefinition<?>> item = lastProcessedObject.asPrismContainerValue().findItem(orderByPath);
        if (item.size() > 1) {
            throw new IllegalArgumentException("Multi-value property for ordering is forbidden - item: " + item);
        } else if (item.isEmpty()) {
        // TODO what if it's nullable? is it null-first or last?
        // See: https://www.postgresql.org/docs/13/queries-order.html
        // "By default, null values sort as if larger than any non-null value; that is,
        // NULLS FIRST is the default for DESC order, and NULLS LAST otherwise."
        } else {
            S_MatchingRuleEntry matchingRuleEntry = asc ? filter.gt(item.getRealValue()) : filter.lt(item.getRealValue());
            filter = matchingRuleEntry.or().block().item(orderByPath).eq(item.getRealValue()).and().item(AuditEventRecordType.F_REPO_ID);
            return (asc ? filter.gt(lastProcessedId) : filter.lt(lastProcessedId)).endBlock().buildFilter();
        }
    }
    throw new IllegalArgumentException("Shouldn't get here with check in executeSearchObjectsIterative()");
}
Also used : S_ConditionEntry(com.evolveum.midpoint.prism.query.builder.S_ConditionEntry) S_MatchingRuleEntry(com.evolveum.midpoint.prism.query.builder.S_MatchingRuleEntry) XMLGregorianCalendar(javax.xml.datatype.XMLGregorianCalendar) CanonicalItemPath(com.evolveum.midpoint.prism.path.CanonicalItemPath) ItemPath(com.evolveum.midpoint.prism.path.ItemPath) Nullable(org.jetbrains.annotations.Nullable)

Example 4 with S_MatchingRuleEntry

use of com.evolveum.midpoint.prism.query.builder.S_MatchingRuleEntry in project midpoint by Evolveum.

the class SqaleRepositoryService method lastOidCondition.

/**
 * Without requested ordering, this is easy: `WHERE oid > lastOid`
 *
 * But with outside ordering we need to respect it and for ordering by X, Y, Z use
 * (`original conditions AND` is taken care of outside of this method):
 *
 * ----
 * ... WHERE original conditions AND (
 * X > last.X
 * OR (X = last.X AND Y > last.Y)
 * OR (X = last.X AND Y = last.Y AND Z > last.Z)
 * OR (X = last.X AND Y = last.Y ...if all equal AND OID > last.OID)
 * ----
 *
 * This is suddenly much more fun, isn't it?
 * Of course the condition `>` or `<` depends on `ASC` vs `DESC`.
 *
 * TODO: Currently, single path ordering is supported. Finish multi-path too.
 * TODO: What about nullable columns?
 */
@Nullable
private <T extends ObjectType> ObjectFilter lastOidCondition(PrismObject<T> lastProcessedObject, List<? extends ObjectOrdering> providedOrdering) {
    if (lastProcessedObject == null) {
        return null;
    }
    String lastProcessedOid = lastProcessedObject.getOid();
    if (providedOrdering == null || providedOrdering.isEmpty()) {
        return prismContext().queryFor(lastProcessedObject.getCompileTimeClass()).item(OID_PATH).gt(lastProcessedOid).buildFilter();
    }
    if (providedOrdering.size() == 1) {
        ObjectOrdering objectOrdering = providedOrdering.get(0);
        ItemPath orderByPath = objectOrdering.getOrderBy();
        boolean asc = objectOrdering.getDirection() == OrderDirection.ASCENDING;
        S_ConditionEntry filter = prismContext().queryFor(lastProcessedObject.getCompileTimeClass()).item(orderByPath);
        // noinspection rawtypes
        Item<PrismValue, ItemDefinition<Item>> item = lastProcessedObject.findItem(orderByPath);
        if (item.size() > 1) {
            throw new IllegalArgumentException("Multi-value property for ordering is forbidden - item: " + item);
        } else if (item.isEmpty()) {
        // TODO what if it's nullable? is it null-first or last?
        // See: https://www.postgresql.org/docs/13/queries-order.html
        // "By default, null values sort as if larger than any non-null value; that is,
        // NULLS FIRST is the default for DESC order, and NULLS LAST otherwise."
        } else {
            S_MatchingRuleEntry matchingRuleEntry = asc ? filter.gt(item.getRealValue()) : filter.lt(item.getRealValue());
            filter = matchingRuleEntry.or().block().item(orderByPath).eq(item.getRealValue()).and().item(OID_PATH);
            return (asc ? filter.gt(lastProcessedOid) : filter.lt(lastProcessedOid)).endBlock().buildFilter();
        }
    }
    throw new IllegalArgumentException("Shouldn't get here with check in executeSearchObjectsIterative()");
/*
        TODO: Unfinished - this is painful with fluent API. Should I call
         prismContext().queryFor(lastProcessedObject.getCompileTimeClass()) for each component
         and then use ObjectQueryUtil.filterAnd/Or?
        // we need to handle the complicated case with externally provided ordering
        S_FilterEntryOrEmpty orBlock = prismContext()
                .queryFor(lastProcessedObject.getCompileTimeClass()).block();
        orLoop:
        for (ObjectOrdering orMasterOrdering : providedOrdering) {
            Iterator<? extends ObjectOrdering> iterator = providedOrdering.iterator();
            while (iterator.hasNext()) {
                S_FilterEntryOrEmpty andBlock = orBlock.block();
                ObjectOrdering ordering = iterator.next();
                if (ordering.equals(orMasterOrdering)) {
                    // ...
                    continue orLoop;
                }
                orBlock = andBlock.endBlock();
            }

        }
        return orBlock.endBlock().buildFilter();
        */
}
Also used : S_ConditionEntry(com.evolveum.midpoint.prism.query.builder.S_ConditionEntry) PolyString(com.evolveum.midpoint.prism.polystring.PolyString) S_MatchingRuleEntry(com.evolveum.midpoint.prism.query.builder.S_MatchingRuleEntry) ItemPath(com.evolveum.midpoint.prism.path.ItemPath) Nullable(org.jetbrains.annotations.Nullable)

Aggregations

S_MatchingRuleEntry (com.evolveum.midpoint.prism.query.builder.S_MatchingRuleEntry)4 ItemPath (com.evolveum.midpoint.prism.path.ItemPath)3 S_ConditionEntry (com.evolveum.midpoint.prism.query.builder.S_ConditionEntry)3 Nullable (org.jetbrains.annotations.Nullable)3 CanonicalItemPath (com.evolveum.midpoint.prism.path.CanonicalItemPath)2 XMLGregorianCalendar (javax.xml.datatype.XMLGregorianCalendar)2 ItemDefinition (com.evolveum.midpoint.prism.ItemDefinition)1 PrismObject (com.evolveum.midpoint.prism.PrismObject)1 PrismValue (com.evolveum.midpoint.prism.PrismValue)1 PolyString (com.evolveum.midpoint.prism.polystring.PolyString)1 ObjectQuery (com.evolveum.midpoint.prism.query.ObjectQuery)1 CommonException (com.evolveum.midpoint.util.exception.CommonException)1 SchemaException (com.evolveum.midpoint.util.exception.SchemaException)1 AuditEventRecordType (com.evolveum.midpoint.xml.ns._public.common.audit_3.AuditEventRecordType)1 TaskType (com.evolveum.midpoint.xml.ns._public.common.common_3.TaskType)1