use of com.yahoo.elide.core.filter.expression.PredicateExtractionVisitor in project elide by yahoo.
the class RootCollectionFetchQueryBuilder method build.
/**
* Constructs a query that fetches a root collection.
*
* @return the constructed query
*/
@Override
public Query build() {
Type<?> entityClass = this.entityProjection.getType();
String entityName = entityClass.getCanonicalName();
String entityAlias = getTypeAlias(entityClass);
Query query;
FilterExpression filterExpression = entityProjection.getFilterExpression();
if (filterExpression != null) {
PredicateExtractionVisitor extractor = new PredicateExtractionVisitor();
Collection<FilterPredicate> predicates = filterExpression.accept(extractor);
// Build the WHERE clause
String filterClause = WHERE + new FilterTranslator(dictionary).apply(filterExpression, USE_ALIAS);
// Build the JOIN clause
String joinClause = getJoinClauseFromFilters(filterExpression) + getJoinClauseFromSort(entityProjection.getSorting()) + extractToOneMergeJoins(entityClass, entityAlias);
boolean requiresDistinct = entityProjection.getPagination() != null && containsOneToMany(filterExpression);
boolean sortOverRelationship = entityProjection.getSorting() != null && entityProjection.getSorting().getSortingPaths().keySet().stream().anyMatch(path -> path.getPathElements().size() > 1);
if (requiresDistinct && sortOverRelationship) {
// SQL does not support distinct and order by on columns which are not selected
throw new InvalidValueException("Combination of pagination, sorting over relationship and" + " filtering over toMany relationships unsupported");
}
query = session.createQuery(SELECT + (requiresDistinct ? DISTINCT : "") + entityAlias + FROM + entityName + AS + entityAlias + SPACE + joinClause + SPACE + filterClause + SPACE + getSortClause(entityProjection.getSorting()));
// Fill in the query parameters
supplyFilterQueryParameters(query, predicates);
} else {
query = session.createQuery(SELECT + entityAlias + FROM + entityName + AS + entityAlias + SPACE + getJoinClauseFromSort(entityProjection.getSorting()) + extractToOneMergeJoins(entityClass, entityAlias) + SPACE + getSortClause(entityProjection.getSorting()));
}
addPaginationToQuery(query);
return query;
}
use of com.yahoo.elide.core.filter.expression.PredicateExtractionVisitor in project elide by yahoo.
the class FilterPredicateTest method parse.
private Map<String, Set<FilterPredicate>> parse(MultivaluedMap<String, String> queryParams) {
PredicateExtractionVisitor visitor = new PredicateExtractionVisitor();
Map<String, FilterExpression> expressionMap;
try {
expressionMap = strategy.parseTypedExpression("/book", queryParams, NO_VERSION);
} catch (ParseException e) {
throw new BadRequestException(e.getMessage());
}
Map<String, Set<FilterPredicate>> returnMap = new HashMap<>();
for (Map.Entry<String, FilterExpression> entry : expressionMap.entrySet()) {
String typeName = entry.getKey();
FilterExpression expression = entry.getValue();
if (!returnMap.containsKey(typeName)) {
returnMap.put(typeName, new HashSet<>());
}
returnMap.get(typeName).addAll(expression.accept(visitor));
}
return returnMap;
}
use of com.yahoo.elide.core.filter.expression.PredicateExtractionVisitor in project elide by yahoo.
the class SQLQueryEngine method supplyFilterQueryParameters.
/**
* Given a Prepared Statement, replaces any parameters with their values from client query.
*
* @param query The client query
* @param stmt Customized Prepared Statement
* @param dialect the SQL dialect
*/
private void supplyFilterQueryParameters(Query query, NamedParamPreparedStatement stmt, SQLDialect dialect) {
Collection<FilterPredicate> predicates = new ArrayList<>();
if (query.getWhereFilter() != null) {
predicates.addAll(query.getWhereFilter().accept(new PredicateExtractionVisitor()));
}
if (query.getHavingFilter() != null) {
predicates.addAll(query.getHavingFilter().accept(new PredicateExtractionVisitor()));
}
for (FilterPredicate filterPredicate : predicates) {
Column column = metaDataStore.getColumn(filterPredicate.getEntityType(), filterPredicate.getField());
if (filterPredicate.getOperator().isParameterized()) {
boolean shouldEscape = filterPredicate.isMatchingOperator();
filterPredicate.getParameters().forEach(param -> {
try {
Object value = param.getValue();
value = convertForJdbc(filterPredicate.getEntityType(), column, value, dialect);
stmt.setObject(param.getName(), shouldEscape ? param.escapeMatching() : value);
} catch (SQLException e) {
throw new IllegalStateException(e);
}
});
}
}
}
use of com.yahoo.elide.core.filter.expression.PredicateExtractionVisitor in project elide by yahoo.
the class EntityProjectionTranslator method addHavingMetrics.
/**
* Adds to the list of queried metrics any metric in the HAVING filter that has not been explicitly requested
* by the client.
*/
private void addHavingMetrics() {
if (havingFilter == null) {
return;
}
// Flatten the HAVING filter expression into a list of predicates...
havingFilter.accept(new PredicateExtractionVisitor()).forEach(filterPredicate -> {
String fieldName = filterPredicate.getField();
// If the predicate field is a metric
if (queriedTable.getMetric(fieldName) != null) {
// If the query doesn't contain this metric.
if (metrics.stream().noneMatch((metric -> metric.getName().equals(fieldName)))) {
// Construct a new projection and add it to the query.
MetricProjection havingMetric = engine.constructMetricProjection(queriedTable.getMetric(fieldName), fieldName, new HashMap<>());
metrics.add(havingMetric);
}
}
});
}
use of com.yahoo.elide.core.filter.expression.PredicateExtractionVisitor in project elide by yahoo.
the class AbstractHQLQueryBuilder method getJoinClauseFromFilters.
/**
* Extracts all the HQL JOIN clauses from given filter expression.
* @param filterExpression the filter expression to extract a join clause from
* @param skipFetches JOIN but don't FETCH JOIN a relationship.
* @return an HQL join clause
*/
protected String getJoinClauseFromFilters(FilterExpression filterExpression, boolean skipFetches) {
PredicateExtractionVisitor visitor = new PredicateExtractionVisitor(new ArrayList<>());
Collection<FilterPredicate> predicates = filterExpression.accept(visitor);
return predicates.stream().map(predicate -> extractJoinClause(predicate.getPath(), skipFetches)).collect(Collectors.joining(SPACE));
}
Aggregations