use of com.evolveum.midpoint.repo.sqlbase.QueryException in project midpoint by Evolveum.
the class QueryInterpreter method interpret.
public RootHibernateQuery interpret(ObjectQuery query, @NotNull Class<? extends Containerable> type, Collection<SelectorOptions<GetOperationOptions>> options, @NotNull PrismContext prismContext, @NotNull RelationRegistry relationRegistry, boolean countingObjects, @NotNull Session session) throws QueryException {
boolean distinctRequested = GetOperationOptions.isDistinct(SelectorOptions.findRootOptions(options));
LOGGER.trace("Interpreting query for type '{}' (counting={}, distinctRequested={}), query:\n{}", type, countingObjects, distinctRequested, query);
InterpretationContext context = new InterpretationContext(this, type, prismContext, relationRegistry, extItemDictionary, session);
interpretQueryFilter(context, query);
String rootAlias = context.getHibernateQuery().getPrimaryEntityAlias();
ResultStyle resultStyle = getResultStyle(context);
if (countingObjects) {
interpretPagingAndSorting(context, query, true);
RootHibernateQuery hibernateQuery = context.getHibernateQuery();
boolean distinct = distinctRequested && !hibernateQuery.isDistinctNotNecessary();
hibernateQuery.addProjectionElement(new CountProjectionElement(resultStyle.getCountString(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();
boolean distinct = distinctRequested && !hibernateQuery.isDistinctNotNecessary();
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, relationRegistry, extItemDictionary, session);
try {
interpretPagingAndSorting(wrapperContext, query, false);
} catch (QueryException e) {
// This fixes cases like MID-6561 and brings in needed joins and wheres
// to the outer query, but we don't want to burden all queries with it.
LOGGER.debug("Potentially recoverable '{}'.\n" + "Trying once more after wrapper context interprets the query.", e.toString());
interpretQueryFilter(wrapperContext, query);
interpretPagingAndSorting(wrapperContext, query, false);
}
RootHibernateQuery wrapperQuery = wrapperContext.getHibernateQuery();
if (repoConfiguration.isUsingSQLServer() && resultStyle.getIdentifiers("").size() > 1) {
// using 'where exists' clause
// FIXME refactor this ugly code
// to distinguish from the same alias in inner query
String wrappedRootAlias = "_" + wrapperQuery.getPrimaryEntityAlias();
wrapperQuery.setPrimaryEntityAlias(wrappedRootAlias);
wrapperQuery.setResultTransformer(resultStyle.getResultTransformer());
wrapperQuery.addProjectionElementsFor(resultStyle.getIdentifiers(wrappedRootAlias));
wrapperQuery.addProjectionElementsFor(resultStyle.getContentAttributes(wrappedRootAlias));
StringBuilder linkingCondition = new StringBuilder();
for (String id : resultStyle.getIdentifiers(wrappedRootAlias)) {
linkingCondition.append(" and ").append(id).append(" = ").append(id.substring(1));
}
wrapperQuery.getConditions().add(wrapperQuery.createExists(subqueryText, linkingCondition.toString()));
} else {
// using 'in' clause (multi-column only for Oracle)
String wrappedRootAlias = wrapperQuery.getPrimaryEntityAlias();
wrapperQuery.setResultTransformer(resultStyle.getResultTransformer());
wrapperQuery.addProjectionElementsFor(resultStyle.getIdentifiers(wrappedRootAlias));
wrapperQuery.addProjectionElementsFor(resultStyle.getContentAttributes(wrappedRootAlias));
List<String> inVariablesList = resultStyle.getIdentifiers(wrapperQuery.getPrimaryEntityAlias());
String inVariablesString = inVariablesList.size() != 1 ? "(" + StringUtils.join(inVariablesList, ", ") + ")" : inVariablesList.get(0);
wrapperQuery.getConditions().add(wrapperQuery.createIn(inVariablesString, 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.sqlbase.QueryException in project midpoint by Evolveum.
the class QueryInterpreter 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<?> 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.sqlbase.QueryException in project midpoint by Evolveum.
the class ItemPathResolver method findRestrictedEntityDefinition.
/**
* Given existing entity definition and a request for narrowing it, tries to find refined definition.
*/
public JpaEntityDefinition findRestrictedEntityDefinition(JpaEntityDefinition baseEntityDefinition, QName specificTypeName) throws QueryException {
QueryDefinitionRegistry registry = QueryDefinitionRegistry.getInstance();
JpaEntityDefinition specificEntityDefinition = registry.findEntityDefinition(specificTypeName);
if (!baseEntityDefinition.isAssignableFrom(specificEntityDefinition)) {
throw new QueryException("Entity " + baseEntityDefinition + " cannot be restricted to " + specificEntityDefinition);
}
return specificEntityDefinition;
}
use of com.evolveum.midpoint.repo.sqlbase.QueryException in project midpoint by Evolveum.
the class ExistsRestriction method interpret.
@Override
public Condition interpret() throws QueryException {
HqlDataInstance dataInstance = getItemPathResolver().resolveItemPath(filter.getFullPath(), filter.getDefinition(), getBaseHqlEntity(), false);
boolean isAll = filter.getFilter() == null || filter.getFilter() instanceof AllFilter;
JpaDataNodeDefinition jpaDefinition = dataInstance.getJpaDefinition();
if (!isAll) {
if (!(jpaDefinition instanceof JpaEntityDefinition)) {
// partially checked already (for non-null-ness)
throw new QueryException("ExistsRestriction with non-empty subfilter points to non-entity node: " + jpaDefinition);
}
setHqlDataInstance(dataInstance);
QueryInterpreter interpreter = context.getInterpreter();
return interpreter.interpretFilter(context, filter.getFilter(), this);
} else if (jpaDefinition instanceof JpaPropertyDefinition && (((JpaPropertyDefinition) jpaDefinition).isCount())) {
RootHibernateQuery hibernateQuery = context.getHibernateQuery();
return hibernateQuery.createSimpleComparisonCondition(dataInstance.getHqlPath(), 0, ">");
} else {
// TODO support exists also for other properties (single valued or multi valued)
throw new UnsupportedOperationException("Exists filter with 'all' subfilter is currently not supported");
}
}
use of com.evolveum.midpoint.repo.sqlbase.QueryException in project midpoint by Evolveum.
the class QueryModelMapping method relationResolver.
/**
* Returns {@link ItemRelationResolver} for the first component of the provided {@link ItemPath}
* or throws if the resolver is not found.
* Relation resolver helps with traversal over all-but-last components of item paths.
* ItemPath is used instead of QName to encapsulate corner cases like parent segment.
*
* @param <TQ> type of target entity path
* @param <TR> row type related to the target entity path {@link TQ}
* @throws QueryException if the resolver for the item is not found
*/
@NotNull
public final <TQ extends FlexibleRelationalPathBase<TR>, TR> ItemRelationResolver<Q, R, TQ, TR> relationResolver(ItemPath path) throws QueryException {
QName itemName = ItemPath.isParent(path.first()) ? PrismConstants.T_PARENT : ItemPath.isObjectReference(path.first()) ? PrismConstants.T_OBJECT_REFERENCE : path.firstName();
ItemRelationResolver<Q, R, TQ, TR> resolver = getRelationResolver(itemName);
if (resolver == null) {
throw new QueryException("Missing relation resolver for '" + itemName + "' in mapping " + getClass().getSimpleName());
}
return resolver;
}
Aggregations