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;
}
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);
}
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;
}
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());
}
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());
}
Aggregations