Search in sources :

Example 26 with AndFilterExpression

use of com.yahoo.elide.core.filter.expression.AndFilterExpression 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)

Example 27 with AndFilterExpression

use of com.yahoo.elide.core.filter.expression.AndFilterExpression in project elide by yahoo.

the class AbstractHQLQueryBuilderTest method testFilterJoinClause.

@Test
public void testFilterJoinClause() {
    List<Path.PathElement> chapterTitlePath = Arrays.asList(new Path.PathElement(Author.class, Book.class, BOOKS), new Path.PathElement(Book.class, Chapter.class, "chapters"), new Path.PathElement(Chapter.class, String.class, TITLE));
    FilterPredicate titlePredicate = new InPredicate(new Path(chapterTitlePath), ABC, DEF);
    FilterPredicate titlePredicateDuplicate = new InPredicate(new Path(chapterTitlePath), ABC, DEF);
    List<Path.PathElement> publisherNamePath = Arrays.asList(new Path.PathElement(Author.class, Book.class, BOOKS), new Path.PathElement(Book.class, Publisher.class, PUBLISHER), new Path.PathElement(Publisher.class, String.class, NAME));
    FilterPredicate publisherNamePredicate = new InPredicate(new Path(publisherNamePath), "Pub1");
    OrFilterExpression orExpression = new OrFilterExpression(titlePredicate, publisherNamePredicate);
    AndFilterExpression andExpression = new AndFilterExpression(orExpression, titlePredicateDuplicate);
    String actual = getJoinClauseFromFilters(andExpression);
    String expected = " LEFT JOIN example_Author.books example_Author_books  " + "LEFT JOIN example_Author_books.chapters example_Author_books_chapters   " + "LEFT JOIN example_Author_books.publisher example_Author_books_publisher  ";
    assertEquals(expected, actual);
}
Also used : Path(com.yahoo.elide.core.Path) OrFilterExpression(com.yahoo.elide.core.filter.expression.OrFilterExpression) Chapter(example.Chapter) ArgumentMatchers.anyString(org.mockito.ArgumentMatchers.anyString) Publisher(example.Publisher) InPredicate(com.yahoo.elide.core.filter.predicates.InPredicate) Book(example.Book) Author(example.Author) FilterPredicate(com.yahoo.elide.core.filter.predicates.FilterPredicate) AndFilterExpression(com.yahoo.elide.core.filter.expression.AndFilterExpression) Test(org.junit.jupiter.api.Test)

Example 28 with AndFilterExpression

use of com.yahoo.elide.core.filter.expression.AndFilterExpression in project elide by yahoo.

the class JPQLTransaction method loadObject.

/**
 * load a single record with id and filter.
 *
 * @param projection The projection to query
 * @param id id of the query object
 * @param scope Request scope associated with specific request
 */
@Override
public <T> T loadObject(EntityProjection projection, Serializable id, RequestScope scope) {
    Type<?> entityClass = projection.getType();
    FilterExpression filterExpression = projection.getFilterExpression();
    EntityDictionary dictionary = scope.getDictionary();
    Type<?> idType = dictionary.getIdType(entityClass);
    String idField = dictionary.getIdFieldName(entityClass);
    // Construct a predicate that selects an individual element of the relationship's parent (Author.id = 3).
    FilterPredicate idExpression;
    Path.PathElement idPath = new Path.PathElement(entityClass, idType, idField);
    if (id != null) {
        idExpression = new InPredicate(idPath, id);
    } else {
        idExpression = new FalsePredicate(idPath);
    }
    FilterExpression joinedExpression = (filterExpression != null) ? new AndFilterExpression(filterExpression, idExpression) : idExpression;
    projection = projection.copyOf().filterExpression(joinedExpression).build();
    Query query = new RootCollectionFetchQueryBuilder(projection, dictionary, sessionWrapper).build();
    T loaded = new TimedFunction<T>(() -> query.uniqueResult(), "Query Hash: " + query.hashCode()).get();
    if (loaded != null) {
        singleElementLoads.add(loaded);
    }
    return loaded;
}
Also used : Path(com.yahoo.elide.core.Path) Query(com.yahoo.elide.datastores.jpql.porting.Query) InPredicate(com.yahoo.elide.core.filter.predicates.InPredicate) FilterPredicate(com.yahoo.elide.core.filter.predicates.FilterPredicate) FilterExpression(com.yahoo.elide.core.filter.expression.FilterExpression) AndFilterExpression(com.yahoo.elide.core.filter.expression.AndFilterExpression) RootCollectionFetchQueryBuilder(com.yahoo.elide.datastores.jpql.query.RootCollectionFetchQueryBuilder) EntityDictionary(com.yahoo.elide.core.dictionary.EntityDictionary) AndFilterExpression(com.yahoo.elide.core.filter.expression.AndFilterExpression) FalsePredicate(com.yahoo.elide.core.filter.predicates.FalsePredicate)

Example 29 with AndFilterExpression

use of com.yahoo.elide.core.filter.expression.AndFilterExpression in project elide by yahoo.

the class SplitFilterExpressionVisitorTest method testVisitNotExpression.

@Test
public void testVisitNotExpression() {
    NotFilterExpression notExpression = new NotFilterExpression(new AndFilterExpression(WHERE_PREDICATE, HAVING_PREDICATE));
    assertNull(splitFilterExpressionVisitor.visitNotExpression(notExpression).getWhereExpression());
    assertEquals("(playerStats.overallRating NOT [foo] OR playerStats.highScore LE [99])", splitFilterExpressionVisitor.visitNotExpression(notExpression).getHavingExpression().toString());
}
Also used : NotFilterExpression(com.yahoo.elide.core.filter.expression.NotFilterExpression) AndFilterExpression(com.yahoo.elide.core.filter.expression.AndFilterExpression) Test(org.junit.jupiter.api.Test)

Example 30 with AndFilterExpression

use of com.yahoo.elide.core.filter.expression.AndFilterExpression in project elide by yahoo.

the class VerifyFieldAccessFilterExpressionVisitorTest method testAccept.

@Test
public void testAccept() throws Exception {
    Path p1Path = new Path(Arrays.asList(new PathElement(Book.class, Author.class, AUTHORS), new PathElement(Author.class, String.class, NAME)));
    FilterPredicate p1 = new InPredicate(p1Path, "foo", "bar");
    Path p2Path = new Path(Arrays.asList(new PathElement(Book.class, String.class, NAME)));
    FilterPredicate p2 = new InPredicate(p2Path, "blah");
    Path p3Path = new Path(Arrays.asList(new PathElement(Book.class, String.class, GENRE)));
    FilterPredicate p3 = new InPredicate(p3Path, SCIFI);
    // P4 is a duplicate of P3
    Path p4Path = new Path(Arrays.asList(new PathElement(Book.class, String.class, GENRE)));
    FilterPredicate p4 = new InPredicate(p4Path, SCIFI);
    OrFilterExpression or = new OrFilterExpression(p2, p3);
    AndFilterExpression and1 = new AndFilterExpression(or, p1);
    AndFilterExpression and2 = new AndFilterExpression(and1, p4);
    NotFilterExpression not = new NotFilterExpression(and2);
    Book book = new Book();
    Author author = new Author();
    book.setAuthors(Collections.singleton(author));
    author.setBooks(Collections.singleton(book));
    PersistentResource<Book> resource = new PersistentResource<>(book, "", scope);
    VerifyFieldAccessFilterExpressionVisitor visitor = new VerifyFieldAccessFilterExpressionVisitor(resource);
    // unrestricted fields
    assertTrue(not.accept(visitor));
    assertTrue(and1.accept(visitor));
    assertTrue(and2.accept(visitor));
    assertTrue(or.accept(visitor));
    assertTrue(p1.accept(visitor));
    assertTrue(p2.accept(visitor));
    assertTrue(p3.accept(visitor));
    assertTrue(p4.accept(visitor));
    PermissionExecutor permissionExecutor = scope.getPermissionExecutor();
    verify(permissionExecutor, times(17)).evaluateFilterJoinUserChecks(any(), any());
    verify(permissionExecutor, times(5)).checkSpecificFieldPermissions(resource, null, ReadPermission.class, NAME);
    verify(permissionExecutor, times(21)).checkUserPermissions(any(), any(), isA(String.class));
    verify(permissionExecutor, never()).handleFilterJoinReject(any(), any(), any());
}
Also used : Path(com.yahoo.elide.core.Path) PersistentResource(com.yahoo.elide.core.PersistentResource) OrFilterExpression(com.yahoo.elide.core.filter.expression.OrFilterExpression) PermissionExecutor(com.yahoo.elide.core.security.PermissionExecutor) InPredicate(com.yahoo.elide.core.filter.predicates.InPredicate) NotFilterExpression(com.yahoo.elide.core.filter.expression.NotFilterExpression) PathElement(com.yahoo.elide.core.Path.PathElement) Book(example.Book) Author(example.Author) FilterPredicate(com.yahoo.elide.core.filter.predicates.FilterPredicate) AndFilterExpression(com.yahoo.elide.core.filter.expression.AndFilterExpression) Test(org.junit.jupiter.api.Test)

Aggregations

AndFilterExpression (com.yahoo.elide.core.filter.expression.AndFilterExpression)34 FilterExpression (com.yahoo.elide.core.filter.expression.FilterExpression)22 OrFilterExpression (com.yahoo.elide.core.filter.expression.OrFilterExpression)21 FilterPredicate (com.yahoo.elide.core.filter.predicates.FilterPredicate)20 Test (org.junit.jupiter.api.Test)17 Path (com.yahoo.elide.core.Path)15 NotFilterExpression (com.yahoo.elide.core.filter.expression.NotFilterExpression)10 InPredicate (com.yahoo.elide.core.filter.predicates.InPredicate)10 SQLUnitTest (com.yahoo.elide.datastores.aggregation.framework.SQLUnitTest)7 Query (com.yahoo.elide.datastores.aggregation.query.Query)7 SQLTable (com.yahoo.elide.datastores.aggregation.queryengines.sql.metadata.SQLTable)7 Book (example.Book)6 Author (example.Author)5 PathElement (com.yahoo.elide.core.Path.PathElement)4 EntityDictionary (com.yahoo.elide.core.dictionary.EntityDictionary)4 Date (java.util.Date)4 DataStoreIterable (com.yahoo.elide.core.datastore.DataStoreIterable)3 RelationshipType (com.yahoo.elide.core.dictionary.RelationshipType)3 Type (com.yahoo.elide.core.type.Type)3 Day (com.yahoo.elide.datastores.aggregation.timegrains.Day)3