Search in sources :

Example 1 with RootHibernateQuery

use of com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery in project midpoint by Evolveum.

the class QueryInterpreter2 method interpret.

public RootHibernateQuery interpret(ObjectQuery query, @NotNull Class<? extends Containerable> type, Collection<SelectorOptions<GetOperationOptions>> options, @NotNull PrismContext prismContext, boolean countingObjects, @NotNull Session session) throws QueryException {
    boolean distinct = GetOperationOptions.isDistinct(SelectorOptions.findRootOptions(options));
    LOGGER.trace("Interpreting query for type '{}' (counting={}, distinct={}), query:\n{}", type, countingObjects, distinct, query);
    InterpretationContext context = new InterpretationContext(this, type, prismContext, session);
    interpretQueryFilter(context, query);
    String rootAlias = context.getHibernateQuery().getPrimaryEntityAlias();
    ResultStyle resultStyle = getResultStyle(context);
    if (countingObjects) {
        interpretPagingAndSorting(context, query, true);
        RootHibernateQuery hibernateQuery = context.getHibernateQuery();
        hibernateQuery.addProjectionElement(new CountProjectionElement(resultStyle.getIdentifiers(rootAlias), distinct));
        return hibernateQuery;
    }
    /*
		   Some databases don't support DISTINCT on BLOBs. In these cases we have to create query like:
		   select
		     u.oid, u.fullObject, u.stringsCount, ..., u.booleansCount
		   from
		     RUser u
		   where
		     u.oid in (select distinct u.oid from RUser u where ...)
		 */
    boolean distinctBlobCapable = !repoConfiguration.isUsingOracle() && !repoConfiguration.isUsingSQLServer();
    RootHibernateQuery hibernateQuery = context.getHibernateQuery();
    hibernateQuery.setDistinct(distinct);
    hibernateQuery.addProjectionElementsFor(resultStyle.getIdentifiers(rootAlias));
    if (distinct && !distinctBlobCapable) {
        String subqueryText = "\n" + hibernateQuery.getAsHqlText(2, true);
        InterpretationContext wrapperContext = new InterpretationContext(this, type, prismContext, session);
        interpretPagingAndSorting(wrapperContext, query, false);
        RootHibernateQuery wrapperQuery = wrapperContext.getHibernateQuery();
        String wrappedRootAlias = wrapperQuery.getPrimaryEntityAlias();
        wrapperQuery.setResultTransformer(resultStyle.getResultTransformer());
        wrapperQuery.addProjectionElementsFor(resultStyle.getIdentifiers(wrappedRootAlias));
        wrapperQuery.addProjectionElementsFor(resultStyle.getContentAttributes(wrappedRootAlias));
        wrapperQuery.getConditions().add(wrapperQuery.createIn(wrapperQuery.getPrimaryEntityAlias() + ".oid", subqueryText));
        wrapperQuery.addParametersFrom(hibernateQuery.getParameters());
        return wrapperQuery;
    } else {
        interpretPagingAndSorting(context, query, false);
        hibernateQuery.setResultTransformer(resultStyle.getResultTransformer());
        hibernateQuery.addProjectionElementsFor(resultStyle.getContentAttributes(rootAlias));
        if (distinct) {
            // SQL requires this
            hibernateQuery.addProjectionElementsFor(getOrderingAttributes(context));
        }
        return hibernateQuery;
    }
}
Also used : CountProjectionElement(com.evolveum.midpoint.repo.sql.query2.hqm.CountProjectionElement) RootHibernateQuery(com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery) ResultStyle(com.evolveum.midpoint.repo.sql.util.ResultStyle) PolyString(com.evolveum.midpoint.prism.polystring.PolyString) RPolyString(com.evolveum.midpoint.repo.sql.data.common.embedded.RPolyString)

Example 2 with RootHibernateQuery

use of com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery in project midpoint by Evolveum.

the class QueryInterpreter2 method addOrdering.

private void addOrdering(InterpretationContext context, ObjectOrdering ordering) throws QueryException {
    ItemPath orderByPath = ordering.getOrderBy();
    // TODO if we'd like to have order-by extension properties, we'd need to provide itemDefinition for them
    ProperDataSearchResult<JpaDataNodeDefinition> result = context.getItemPathResolver().findProperDataDefinition(context.getRootEntityDefinition(), orderByPath, null, JpaDataNodeDefinition.class, context.getPrismContext());
    if (result == null) {
        LOGGER.error("Unknown path '" + orderByPath + "', couldn't find definition for it, " + "list will not be ordered by it.");
        return;
    }
    JpaDataNodeDefinition targetDefinition = result.getLinkDefinition().getTargetDefinition();
    if (targetDefinition instanceof JpaAnyContainerDefinition) {
        throw new QueryException("Sorting based on extension item or attribute is not supported yet: " + orderByPath);
    } else if (targetDefinition instanceof JpaReferenceDefinition) {
        throw new QueryException("Sorting based on reference is not supported: " + orderByPath);
    } else if (result.getLinkDefinition().isMultivalued()) {
        throw new QueryException("Sorting based on multi-valued item is not supported: " + orderByPath);
    } else if (targetDefinition instanceof JpaEntityDefinition) {
        throw new QueryException("Sorting based on entity is not supported: " + orderByPath);
    } else if (!(targetDefinition instanceof JpaPropertyDefinition)) {
        throw new IllegalStateException("Unknown item definition type: " + result.getClass());
    }
    JpaEntityDefinition baseEntityDefinition = result.getEntityDefinition();
    JpaPropertyDefinition orderByDefinition = (JpaPropertyDefinition) targetDefinition;
    String hqlPropertyPath = context.getItemPathResolver().resolveItemPath(orderByPath, null, context.getPrimaryEntityAlias(), baseEntityDefinition, true).getHqlPath();
    if (RPolyString.class.equals(orderByDefinition.getJpaClass())) {
        hqlPropertyPath += ".orig";
    }
    RootHibernateQuery hibernateQuery = context.getHibernateQuery();
    if (ordering.getDirection() != null) {
        switch(ordering.getDirection()) {
            case ASCENDING:
                hibernateQuery.addOrdering(hqlPropertyPath, OrderDirection.ASCENDING);
                break;
            case DESCENDING:
                hibernateQuery.addOrdering(hqlPropertyPath, OrderDirection.DESCENDING);
                break;
        }
    } else {
        hibernateQuery.addOrdering(hqlPropertyPath, OrderDirection.ASCENDING);
    }
}
Also used : QueryException(com.evolveum.midpoint.repo.sql.query.QueryException) RootHibernateQuery(com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery) PolyString(com.evolveum.midpoint.prism.polystring.PolyString) RPolyString(com.evolveum.midpoint.repo.sql.data.common.embedded.RPolyString) ItemPath(com.evolveum.midpoint.prism.path.ItemPath)

Example 3 with RootHibernateQuery

use of com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery in project midpoint by Evolveum.

the class ReferenceRestriction method interpretInternal.

@Override
public Condition interpretInternal() throws QueryException {
    String hqlPath = hqlDataInstance.getHqlPath();
    LOGGER.trace("interpretInternal starting with hqlPath = {}", hqlPath);
    RootHibernateQuery hibernateQuery = context.getHibernateQuery();
    List<PrismReferenceValue> values = filter.getValues();
    if (CollectionUtils.isEmpty(values)) {
        return hibernateQuery.createIsNull(hqlDataInstance.getHqlPath());
    }
    Set<String> oids = new HashSet<>();
    Set<QName> relations = new HashSet<>();
    Set<QName> targetTypes = new HashSet<>();
    for (PrismReferenceValue value : values) {
        if (value.getOid() == null) {
            throw new QueryException("Null OID is not allowed in the reference query. Use empty reference list if needed.");
        }
        oids.add(value.getOid());
        if (value.getRelation() == null) {
            relations.add(SchemaConstants.ORG_DEFAULT);
        } else {
            // we intentionally don't normalize relations namespaces, to be able to do namespace-insensitive searches
            // so the caller is responsible to unify namespaces if he needs to optimize queries (use IN instead of OR)
            relations.add(value.getRelation());
        }
        targetTypes.add(qualifyTypeName(value.getTargetType()));
    }
    if (relations.size() > 1 || targetTypes.size() > 1) {
        // we must use 'OR' clause
        OrCondition rootOr = hibernateQuery.createOr();
        values.forEach(prv -> rootOr.add(createRefCondition(hibernateQuery, Collections.singleton(prv.getOid()), prv.getRelation(), prv.getTargetType())));
        return rootOr;
    } else {
        return createRefCondition(hibernateQuery, oids, MiscUtil.extractSingleton(relations), MiscUtil.extractSingleton(targetTypes));
    }
}
Also used : QueryException(com.evolveum.midpoint.repo.sql.query.QueryException) PrismReferenceValue(com.evolveum.midpoint.prism.PrismReferenceValue) RootHibernateQuery(com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery) QName(javax.xml.namespace.QName) RUtil.qnameToString(com.evolveum.midpoint.repo.sql.util.RUtil.qnameToString) OrCondition(com.evolveum.midpoint.repo.sql.query2.hqm.condition.OrCondition)

Example 4 with RootHibernateQuery

use of com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery in project midpoint by Evolveum.

the class Matcher method basicMatch.

protected Condition basicMatch(RootHibernateQuery hibernateQuery, ItemRestrictionOperation operation, String propertyPath, Object value, boolean ignoreCase) throws QueryException {
    Validate.notNull(hibernateQuery, "hibernateQuery");
    if (ignoreCase && !(value instanceof String)) {
        LOGGER.warn("Ignoring ignoreCase setting for non-string value of {}", value);
        ignoreCase = false;
    }
    Condition condition;
    switch(operation) {
        case EQ:
            if (value == null) {
                condition = hibernateQuery.createIsNull(propertyPath);
            } else {
                condition = hibernateQuery.createEq(propertyPath, value, ignoreCase);
            }
            break;
        case GT:
        case GE:
        case LT:
        case LE:
            condition = hibernateQuery.createSimpleComparisonCondition(propertyPath, value, operation.symbol(), ignoreCase);
            break;
        case NOT_NULL:
            condition = hibernateQuery.createIsNotNull(propertyPath);
            break;
        case NULL:
            condition = hibernateQuery.createIsNull(propertyPath);
            break;
        case STARTS_WITH:
            condition = hibernateQuery.createLike(propertyPath, (String) value, MatchMode.START, ignoreCase);
            break;
        case ENDS_WITH:
            condition = hibernateQuery.createLike(propertyPath, (String) value, MatchMode.END, ignoreCase);
            break;
        case SUBSTRING:
            condition = hibernateQuery.createLike(propertyPath, (String) value, MatchMode.ANYWHERE, ignoreCase);
            break;
        default:
            throw new QueryException("Unknown operation '" + operation + "'.");
    }
    return condition;
}
Also used : Condition(com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition) QueryException(com.evolveum.midpoint.repo.sql.query.QueryException)

Example 5 with RootHibernateQuery

use of com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery in project midpoint by Evolveum.

the class PolyStringMatcher method match.

@Override
public Condition match(RootHibernateQuery hibernateQuery, ItemRestrictionOperation operation, String propertyName, PolyString value, String matcher) throws QueryException {
    boolean ignoreCase = STRICT_IGNORE_CASE.equals(matcher) || ORIG_IGNORE_CASE.equals(matcher) || NORM_IGNORE_CASE.equals(matcher);
    if (StringUtils.isEmpty(matcher) || DEFAULT.equals(matcher) || STRICT.equals(matcher) || STRICT_IGNORE_CASE.equals(matcher)) {
        AndCondition conjunction = hibernateQuery.createAnd();
        conjunction.add(createOrigMatch(hibernateQuery, operation, propertyName, value, ignoreCase));
        conjunction.add(createNormMatch(hibernateQuery, operation, propertyName, value, ignoreCase));
        return conjunction;
    } else if (ORIG.equals(matcher) || ORIG_IGNORE_CASE.equals(matcher)) {
        return createOrigMatch(hibernateQuery, operation, propertyName, value, ignoreCase);
    } else if (NORM.equals(matcher) || NORM_IGNORE_CASE.equals(matcher)) {
        return createNormMatch(hibernateQuery, operation, propertyName, value, ignoreCase);
    } else {
        throw new QueryException("Unknown matcher '" + matcher + "'.");
    }
}
Also used : QueryException(com.evolveum.midpoint.repo.sql.query.QueryException) AndCondition(com.evolveum.midpoint.repo.sql.query2.hqm.condition.AndCondition)

Aggregations

RootHibernateQuery (com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery)13 QueryException (com.evolveum.midpoint.repo.sql.query.QueryException)7 Condition (com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition)6 AndCondition (com.evolveum.midpoint.repo.sql.query2.hqm.condition.AndCondition)5 PolyString (com.evolveum.midpoint.prism.polystring.PolyString)4 RPolyString (com.evolveum.midpoint.repo.sql.data.common.embedded.RPolyString)3 QName (javax.xml.namespace.QName)3 QueryInterpreter2 (com.evolveum.midpoint.repo.sql.query2.QueryInterpreter2)2 JoinSpecification (com.evolveum.midpoint.repo.sql.query2.hqm.JoinSpecification)2 OrCondition (com.evolveum.midpoint.repo.sql.query2.hqm.condition.OrCondition)2 HqlDataInstance (com.evolveum.midpoint.repo.sql.query2.resolution.HqlDataInstance)2 RUtil.qnameToString (com.evolveum.midpoint.repo.sql.util.RUtil.qnameToString)2 PrismReferenceValue (com.evolveum.midpoint.prism.PrismReferenceValue)1 ItemPath (com.evolveum.midpoint.prism.path.ItemPath)1 AllFilter (com.evolveum.midpoint.prism.query.AllFilter)1 ComparativeFilter (com.evolveum.midpoint.prism.query.ComparativeFilter)1 EqualFilter (com.evolveum.midpoint.prism.query.EqualFilter)1 ObjectPagingAfterOid (com.evolveum.midpoint.repo.sql.ObjectPagingAfterOid)1 RObject (com.evolveum.midpoint.repo.sql.data.common.RObject)1 RObjectType (com.evolveum.midpoint.repo.sql.data.common.other.RObjectType)1