use of com.yahoo.elide.core.Path in project elide by yahoo.
the class FilterTranslator method apply.
/**
* Transforms a filter predicate into a JPQL query fragment.
* @param filterPredicate The predicate to transform.
* @param aliasGenerator Function which supplies a HQL fragment which represents the column in the predicate.
* @return The hql query fragment.
*/
protected String apply(FilterPredicate filterPredicate, Function<Path, String> aliasGenerator) {
Function<Path, String> removeThisFromAlias = (path) -> {
String fieldPath = aliasGenerator.apply(path);
// JPQL doesn't support 'this', but it does support aliases.
return fieldPath.replaceAll("\\.this", "");
};
Path.PathElement last = filterPredicate.getPath().lastElement().get();
Operator op = filterPredicate.getOperator();
JPQLPredicateGenerator generator = predicateOverrides.get(Triple.of(op, last.getType(), last.getFieldName()));
if (generator == null) {
generator = operatorGenerators.get(op);
}
if (generator == null) {
throw new BadRequestException("Operator not implemented: " + filterPredicate.getOperator());
}
return generator.generate(filterPredicate, removeThisFromAlias);
}
use of com.yahoo.elide.core.Path in project elide by yahoo.
the class HasMemberJPQLGenerator method getOuterQueryIdField.
private String getOuterQueryIdField(Path path, Function<Path, String> aliasGenerator) {
Path.PathElement firstElement = path.getPathElements().get(0);
Type<?> modelType = firstElement.getType();
String idField = dictionary.getIdFieldName(modelType);
Type<?> idFieldType = dictionary.getIdType(modelType);
Path idPath = new Path(Arrays.asList(new Path.PathElement(modelType, idFieldType, idField)));
return aliasGenerator.apply(idPath);
}
use of com.yahoo.elide.core.Path in project elide by yahoo.
the class QueryTranslator method visitQuery.
@Override
public NativeQuery.NativeQueryBuilder visitQuery(Query query) {
NativeQuery.NativeQueryBuilder builder = query.getSource().accept(this);
if (query.isNested()) {
NativeQuery innerQuery = builder.build();
builder = NativeQuery.builder().fromClause(getFromClause("(" + innerQuery + ")", applyQuotes(query.getSource().getAlias()), dialect));
}
Set<String> joinExpressions = new LinkedHashSet<>();
builder.projectionClause(constructProjectionWithReference(query));
// Handles join for all type of column projects - dimensions, metrics and time dimention
joinExpressions.addAll(extractJoinExpressions(query));
Set<ColumnProjection> groupByDimensions = query.getAllDimensionProjections().stream().map(SQLColumnProjection.class::cast).filter(SQLColumnProjection::isProjected).collect(Collectors.toCollection(LinkedHashSet::new));
if (!groupByDimensions.isEmpty()) {
if (!query.getMetricProjections().isEmpty()) {
builder.groupByClause("GROUP BY " + groupByDimensions.stream().map(SQLColumnProjection.class::cast).map((column) -> column.toSQL(query, metaDataStore)).collect(Collectors.joining(", ")));
}
}
if (query.getWhereFilter() != null) {
builder.whereClause("WHERE " + translateFilterExpression(query.getWhereFilter(), path -> generatePredicatePathReference(path, query)));
joinExpressions.addAll(extractJoinExpressions(query, query.getWhereFilter()));
}
if (query.getHavingFilter() != null) {
builder.havingClause("HAVING " + translateFilterExpression(query.getHavingFilter(), (path) -> constructHavingClauseWithReference(path, query)));
joinExpressions.addAll(extractJoinExpressions(query, query.getHavingFilter()));
}
if (query.getSorting() != null) {
Map<Path, Sorting.SortOrder> sortClauses = query.getSorting().getSortingPaths();
builder.orderByClause(extractOrderBy(sortClauses, query));
joinExpressions.addAll(extractJoinExpressions(query, sortClauses));
}
Pagination pagination = query.getPagination();
if (pagination != null) {
builder.offsetLimitClause(dialect.generateOffsetLimitClause(pagination.getOffset(), pagination.getLimit()));
}
return builder.joinClause(String.join(" ", joinExpressions));
}
use of com.yahoo.elide.core.Path in project elide by yahoo.
the class ReferenceExtractor method visitJoinReference.
@Override
public Set<T> visitJoinReference(JoinReference reference) {
if (referenceType.equals(JoinReference.class)) {
references.add((T) reference);
}
JoinPath path = reference.getPath();
int pathLimit = (mode == Mode.SAME_QUERY) ? 1 : path.getPathElements().size() - 1;
for (int idx = 0; idx < pathLimit; idx++) {
Path.PathElement pathElement = path.getPathElements().get(idx);
String fieldName = pathElement.getFieldName();
Type<?> parentClass = pathElement.getType();
SQLTable table = metaDataStore.getTable(parentClass);
SQLJoin join = table.getJoin(fieldName);
if (visitedJoins.contains(join)) {
continue;
}
visitedJoins.add(join);
parser.parse(table, join.getJoinExpression()).stream().forEach(ref -> ref.accept(this));
}
if (mode != Mode.SAME_QUERY) {
return reference.getReference().accept(this);
}
return references;
}
use of com.yahoo.elide.core.Path 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