Search in sources :

Example 1 with Query

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;
}
Also used : Query(com.yahoo.elide.datastores.jpql.porting.Query) PredicateExtractionVisitor(com.yahoo.elide.core.filter.expression.PredicateExtractionVisitor) FilterPredicate(com.yahoo.elide.core.filter.predicates.FilterPredicate) FilterExpression(com.yahoo.elide.core.filter.expression.FilterExpression) FilterTranslator(com.yahoo.elide.datastores.jpql.filter.FilterTranslator)

Example 2 with 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();
}
Also used : Pagination(com.yahoo.elide.core.request.Pagination) Query(com.yahoo.elide.datastores.jpql.porting.Query) DataStoreIterable(com.yahoo.elide.core.datastore.DataStoreIterable) Iterator(java.util.Iterator) Collection(java.util.Collection) RootCollectionFetchQueryBuilder(com.yahoo.elide.datastores.jpql.query.RootCollectionFetchQueryBuilder)

Example 3 with Query

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;
}
Also used : PredicateExtractionVisitor(com.yahoo.elide.core.filter.expression.PredicateExtractionVisitor) FilterPredicate(com.yahoo.elide.core.filter.predicates.FilterPredicate) InvalidValueException(com.yahoo.elide.core.exceptions.InvalidValueException) Type(com.yahoo.elide.core.type.Type) Collection(java.util.Collection) TypeHelper.getTypeAlias(com.yahoo.elide.core.utils.TypeHelper.getTypeAlias) EntityProjection(com.yahoo.elide.core.request.EntityProjection) Session(com.yahoo.elide.datastores.jpql.porting.Session) FilterTranslator(com.yahoo.elide.datastores.jpql.filter.FilterTranslator) FilterExpression(com.yahoo.elide.core.filter.expression.FilterExpression) EntityDictionary(com.yahoo.elide.core.dictionary.EntityDictionary) Query(com.yahoo.elide.datastores.jpql.porting.Query) InvalidValueException(com.yahoo.elide.core.exceptions.InvalidValueException) Query(com.yahoo.elide.datastores.jpql.porting.Query) PredicateExtractionVisitor(com.yahoo.elide.core.filter.expression.PredicateExtractionVisitor) FilterPredicate(com.yahoo.elide.core.filter.predicates.FilterPredicate) FilterExpression(com.yahoo.elide.core.filter.expression.FilterExpression) FilterTranslator(com.yahoo.elide.datastores.jpql.filter.FilterTranslator)

Example 4 with 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;
}
Also used : Query(com.yahoo.elide.datastores.jpql.porting.Query) PredicateExtractionVisitor(com.yahoo.elide.core.filter.expression.PredicateExtractionVisitor) FilterPredicate(com.yahoo.elide.core.filter.predicates.FilterPredicate) FilterExpression(com.yahoo.elide.core.filter.expression.FilterExpression) FilterTranslator(com.yahoo.elide.datastores.jpql.filter.FilterTranslator)

Example 5 with 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;
}
Also used : Query(com.yahoo.elide.datastores.jpql.porting.Query) ArrayList(java.util.ArrayList) ExpressionScopingVisitor(com.yahoo.elide.core.filter.expression.ExpressionScopingVisitor) InPredicate(com.yahoo.elide.core.filter.predicates.InPredicate) PathElement(com.yahoo.elide.core.Path.PathElement) PredicateExtractionVisitor(com.yahoo.elide.core.filter.expression.PredicateExtractionVisitor) FilterPredicate(com.yahoo.elide.core.filter.predicates.FilterPredicate) AndFilterExpression(com.yahoo.elide.core.filter.expression.AndFilterExpression) FilterExpression(com.yahoo.elide.core.filter.expression.FilterExpression) FilterTranslator(com.yahoo.elide.datastores.jpql.filter.FilterTranslator) AndFilterExpression(com.yahoo.elide.core.filter.expression.AndFilterExpression)

Aggregations

Query (com.yahoo.elide.datastores.jpql.porting.Query)10 FilterExpression (com.yahoo.elide.core.filter.expression.FilterExpression)6 FilterPredicate (com.yahoo.elide.core.filter.predicates.FilterPredicate)6 PredicateExtractionVisitor (com.yahoo.elide.core.filter.expression.PredicateExtractionVisitor)4 FilterTranslator (com.yahoo.elide.datastores.jpql.filter.FilterTranslator)4 EntityDictionary (com.yahoo.elide.core.dictionary.EntityDictionary)3 AndFilterExpression (com.yahoo.elide.core.filter.expression.AndFilterExpression)3 InPredicate (com.yahoo.elide.core.filter.predicates.InPredicate)3 Collection (java.util.Collection)3 Path (com.yahoo.elide.core.Path)2 DataStoreIterable (com.yahoo.elide.core.datastore.DataStoreIterable)2 Pagination (com.yahoo.elide.core.request.Pagination)2 RootCollectionFetchQueryBuilder (com.yahoo.elide.datastores.jpql.query.RootCollectionFetchQueryBuilder)2 Test (org.junit.jupiter.api.Test)2 PathElement (com.yahoo.elide.core.Path.PathElement)1 DataStoreIterableBuilder (com.yahoo.elide.core.datastore.DataStoreIterableBuilder)1 InvalidValueException (com.yahoo.elide.core.exceptions.InvalidValueException)1 ExpressionScopingVisitor (com.yahoo.elide.core.filter.expression.ExpressionScopingVisitor)1 FalsePredicate (com.yahoo.elide.core.filter.predicates.FalsePredicate)1 InfixPredicate (com.yahoo.elide.core.filter.predicates.InfixPredicate)1