use of com.yahoo.elide.core.type.Type in project elide by yahoo.
the class TableType method resolveJoins.
/**
* Must be called post construction of all the dynamic types to initialize table join fields.
* @param tableTypes A map of table name to type.
*/
public void resolveJoins(Map<String, Type<?>> tableTypes) {
table.getJoins().forEach(join -> {
Type joinTableType = tableTypes.get(join.getTo());
fields.put(join.getName(), new FieldType(join.getName(), joinTableType, buildAnnotations(join)));
});
}
use of com.yahoo.elide.core.type.Type in project elide by yahoo.
the class PermissionExpressionBuilder method buildUserCheckEntityAndAnyFieldExpression.
/**
* Build an expression that strictly evaluates UserCheck's and ignores other checks for an entity.
* expression = (entityRule AND (field1Rule OR field2Rule ... OR fieldNRule))
* <p>
* NOTE: This method returns _NO_ commit checks.
*
* @param resourceClass Resource class
* @param annotationClass Annotation class
* @param scope Request scope
* @param <A> type parameter
* @return User check expression to evaluate
*/
public <A extends Annotation> Expression buildUserCheckEntityAndAnyFieldExpression(final Type<?> resourceClass, final Class<A> annotationClass, Set<String> requestedFields, final RequestScope scope) {
final Function<Check, Expression> leafBuilderFn = (check) -> new CheckExpression(check, null, scope, null, cache);
ParseTree classPermissions = entityDictionary.getPermissionsForClass(resourceClass, annotationClass);
Expression entityExpression = normalizedExpressionFromParseTree(classPermissions, leafBuilderFn);
Expression anyFieldExpression = buildAnyFieldOnlyExpression(new PermissionCondition(annotationClass, resourceClass), leafBuilderFn, requestedFields);
if (entityExpression == null) {
return anyFieldExpression;
}
return new AndExpression(entityExpression, anyFieldExpression);
}
use of com.yahoo.elide.core.type.Type in project elide by yahoo.
the class AbstractPermissionExecutor method checkPermissions.
/**
* First attempts to check user permissions (by looking in the cache and if not present by executing user
* permissions). If user permissions don't short circuit the check, run the provided expression executor.
*
* @param <A> type parameter
* @param resourceClass Resource class
* @param annotationClass Annotation class
* @param fields Set of all field names that is being accessed
* @param expressionSupplier Builds a permission expression.
* @param expressionExecutor Evaluates the expression (post user check evaluation)
*/
protected <A extends Annotation> ExpressionResult checkPermissions(Type<?> resourceClass, Class<A> annotationClass, Set<String> fields, Supplier<Expression> expressionSupplier, Optional<Function<Expression, ExpressionResult>> expressionExecutor) {
// If the user check has already been evaluated before, return the result directly and save the building cost
ImmutableSet<String> immutableFields = fields == null ? null : ImmutableSet.copyOf(fields);
ExpressionResult expressionResult = userPermissionCheckCache.get(Triple.of(annotationClass, resourceClass, immutableFields));
if (expressionResult == PASS) {
return expressionResult;
}
Expression expression = expressionSupplier.get();
if (expressionResult == null) {
expressionResult = executeExpressions(expression, annotationClass, Expression.EvaluationMode.USER_CHECKS_ONLY);
userPermissionCheckCache.put(Triple.of(annotationClass, resourceClass, immutableFields), expressionResult);
if (expressionResult == PASS) {
return expressionResult;
}
}
return expressionExecutor.map(executor -> executor.apply(expression)).orElse(expressionResult);
}
use of com.yahoo.elide.core.type.Type 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.type.Type in project elide by yahoo.
the class JoinPathTest method init.
@BeforeAll
public static void init() {
Set<Type<?>> models = new HashSet<>();
models.add(ClassType.of(PlayerStats.class));
models.add(ClassType.of(CountryView.class));
models.add(ClassType.of(Country.class));
models.add(ClassType.of(SubCountry.class));
models.add(ClassType.of(Player.class));
models.add(ClassType.of(PlayerRanking.class));
models.add(ClassType.of(CountryViewNested.class));
models.add(ClassType.of(PlayerStatsWithView.class));
EntityDictionary dictionary = EntityDictionary.builder().build();
models.stream().forEach(dictionary::bindEntity);
store = new MetaDataStore(dictionary.getScanner(), models, true);
store.populateEntityDictionary(dictionary);
DataSource mockDataSource = mock(DataSource.class);
// The query engine populates the metadata store with actual tables.
new SQLQueryEngine(store, (unused) -> new ConnectionDetails(mockDataSource, SQLDialectFactory.getDefaultDialect()));
}
Aggregations