use of com.yahoo.elide.datastores.jpql.porting.Query in project elide by yahoo.
the class RootCollectionPageTotalsQueryBuilder method build.
/**
* Constructs a query that returns the count of a root collection.
*
* Constructs a query like:
*
* SELECT COUNT(DISTINCT Author)
* FROM Author AS Author
*
* @return the constructed query
*/
@Override
public Query build() {
Type<?> entityClass = entityProjection.getType();
String entityName = entityClass.getCanonicalName();
String entityAlias = getTypeAlias(entityClass);
Collection<FilterPredicate> predicates;
String filterClause;
String joinClause;
FilterExpression filterExpression = entityProjection.getFilterExpression();
if (filterExpression != null) {
PredicateExtractionVisitor extractor = new PredicateExtractionVisitor();
predicates = filterExpression.accept(extractor);
// Build the WHERE clause
filterClause = WHERE + new FilterTranslator(dictionary).apply(filterExpression, USE_ALIAS);
// Build the JOIN clause
joinClause = getJoinClauseFromFilters(filterExpression, true);
} else {
predicates = new HashSet<>();
filterClause = "";
joinClause = "";
}
Query query = session.createQuery("SELECT COUNT(DISTINCT " + entityAlias + ") " + FROM + entityName + AS + entityAlias + SPACE + joinClause + SPACE + filterClause);
supplyFilterQueryParameters(query, predicates);
return query;
}
use of com.yahoo.elide.datastores.jpql.porting.Query in project elide by yahoo.
the class JPQLTransaction method loadObjects.
@Override
public <T> DataStoreIterable<T> loadObjects(EntityProjection projection, RequestScope scope) {
Pagination pagination = projection.getPagination();
final Query query = new RootCollectionFetchQueryBuilder(projection, scope.getDictionary(), sessionWrapper).build();
Iterable<T> results = new TimedFunction<Iterable<T>>(() -> {
return isScrollEnabled ? query.scroll() : query.list();
}, "Query Hash: " + query.hashCode()).get();
final boolean hasResults;
if (results instanceof Collection) {
hasResults = !((Collection) results).isEmpty();
} else if (results instanceof Iterator) {
hasResults = ((Iterator) results).hasNext();
} else {
hasResults = results.iterator().hasNext();
}
if (pagination != null) {
// Issue #1429
if (pagination.returnPageTotals() && (hasResults || pagination.getLimit() == 0)) {
pagination.setPageTotals(getTotalRecords(projection, scope.getDictionary()));
}
}
return new DataStoreIterableBuilder<T>(addSingleElement(results)).build();
}
use of com.yahoo.elide.datastores.jpql.porting.Query 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.datastores.jpql.porting.Query in project elide by yahoo.
the class SubCollectionFetchQueryBuilder method build.
/**
* Constructs a query that returns the members of a relationship.
*
* @return the constructed query or null if the collection proxy does not require any
* sorting, pagination, or filtering.
*/
@Override
public Query build() {
if (entityProjection.getFilterExpression() == null && entityProjection.getPagination() == null && (entityProjection.getSorting() == null || entityProjection.getSorting().isDefaultInstance())) {
return null;
}
String childAlias = getTypeAlias(relationship.getChildType());
String parentAlias = getTypeAlias(relationship.getParentType()) + "__fetch";
String parentName = relationship.getParentType().getCanonicalName();
String relationshipName = relationship.getRelationshipName();
FilterExpression filterExpression = entityProjection.getFilterExpression();
Query query;
if (filterExpression != null) {
PredicateExtractionVisitor extractor = new PredicateExtractionVisitor();
Collection<FilterPredicate> predicates = filterExpression.accept(extractor);
String filterClause = new FilterTranslator(dictionary).apply(filterExpression, USE_ALIAS);
String joinClause = getJoinClauseFromFilters(filterExpression) + getJoinClauseFromSort(entityProjection.getSorting()) + extractToOneMergeJoins(relationship.getChildType(), childAlias);
// SELECT parent_children from Parent parent JOIN parent.children parent_children
query = session.createQuery(SELECT + childAlias + FROM + parentName + SPACE + parentAlias + JOIN + parentAlias + PERIOD + relationshipName + SPACE + childAlias + joinClause + WHERE + filterClause + " AND " + parentAlias + "=:" + parentAlias + SPACE + getSortClause(entityProjection.getSorting()));
supplyFilterQueryParameters(query, predicates);
} else {
query = session.createQuery(SELECT + childAlias + FROM + parentName + SPACE + parentAlias + JOIN + parentAlias + PERIOD + relationshipName + SPACE + childAlias + getJoinClauseFromSort(entityProjection.getSorting()) + extractToOneMergeJoins(relationship.getChildType(), childAlias) + " WHERE " + parentAlias + "=:" + parentAlias + getSortClause(entityProjection.getSorting()));
}
query.setParameter(parentAlias, relationship.getParent());
addPaginationToQuery(query);
return query;
}
use of com.yahoo.elide.datastores.jpql.porting.Query in project elide by yahoo.
the class SubCollectionPageTotalsQueryBuilder method build.
/**
* Constructs a query that returns the count of the members of a relationship.
*
* For a relationship like author#3.books, constructs a query like:
*
* SELECT COUNT(DISTINCT Author_books)
* FROM Author AS Author JOIN Author.books AS Author_books
* WHERE Author.id = :author_books_id;
*
* Rather than query relationship directly (FROM Book), this query starts at the relationship
* owner to support scenarios where there is no inverse relationship from the relationship back to
* the owner.
*
* @return the constructed query
*/
@Override
public Query build() {
Type<?> parentType = dictionary.lookupEntityClass(relationship.getParentType());
Type<?> idType = dictionary.getIdType(parentType);
Object idVal = CoerceUtil.coerce(dictionary.getId(relationship.getParent()), idType);
String idField = dictionary.getIdFieldName(parentType);
// Construct a predicate that selects an individual element of the relationship's parent (Author.id = 3).
FilterPredicate idExpression = new InPredicate(new PathElement(parentType, idType, idField), idVal);
Collection<FilterPredicate> predicates = new ArrayList<>();
String joinClause = "";
String filterClause = "";
String relationshipName = relationship.getRelationshipName();
// Relationship alias is Author_books
String parentAlias = getTypeAlias(parentType);
String relationshipAlias = appendAlias(parentAlias, relationshipName);
FilterExpression filterExpression = entityProjection.getFilterExpression();
if (filterExpression != null) {
// Copy and scope the filter expression for the join clause
ExpressionScopingVisitor visitor = new ExpressionScopingVisitor(new PathElement(parentType, relationship.getChildType(), relationship.getRelationshipName()));
FilterExpression scoped = filterExpression.accept(visitor);
// For each filter predicate, prepend the predicate with the parent:
// books.title = 'Foobar' becomes author.books.title = 'Foobar'
PredicateExtractionVisitor extractor = new PredicateExtractionVisitor(new ArrayList<>());
predicates = scoped.accept(extractor);
predicates.add(idExpression);
// Join together the provided filter expression with the expression which selects the collection owner.
FilterExpression joinedExpression = new AndFilterExpression(scoped, idExpression);
// Build the JOIN clause from the filter predicate
joinClause = getJoinClauseFromFilters(joinedExpression, true);
// Build the WHERE clause
filterClause = new FilterTranslator(dictionary).apply(joinedExpression, USE_ALIAS);
} else {
// If there is no filter, we still need to explicitly JOIN book and authors.
joinClause = JOIN + parentAlias + PERIOD + relationshipName + SPACE + relationshipAlias + SPACE;
filterClause = new FilterTranslator(dictionary).apply(idExpression, USE_ALIAS);
predicates.add(idExpression);
}
Query query = session.createQuery("SELECT COUNT(DISTINCT " + relationshipAlias + ") " + FROM + parentType.getCanonicalName() + AS + parentAlias + SPACE + joinClause + WHERE + filterClause);
// Fill in the query parameters
supplyFilterQueryParameters(query, predicates);
return query;
}
Aggregations