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;
}
}
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);
}
}
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));
}
}
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;
}
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 + "'.");
}
}
Aggregations