Search in sources :

Example 31 with ColumnProjection

use of com.yahoo.elide.datastores.aggregation.query.ColumnProjection in project elide by yahoo.

the class ExpressionParser method buildJoin.

private JoinReference buildJoin(Queryable source, String referenceName, Map<String, Argument> callingColumnArgs, Map<String, Argument> fixedArguments) {
    Queryable root = source.getRoot();
    Type<?> tableClass = dictionary.getEntityClass(root.getName(), root.getVersion());
    JoinPath joinPath = new JoinPath(tableClass, metaDataStore, referenceName);
    Path.PathElement lastElement = joinPath.lastElement().get();
    Queryable joinSource = metaDataStore.getTable(lastElement.getType());
    String fieldName = lastElement.getFieldName();
    Reference reference;
    if (fieldName.startsWith("$")) {
        reference = PhysicalReference.builder().source(joinSource).name(fieldName.substring(1)).build();
    } else {
        ColumnProjection referencedColumn = joinSource.getColumnProjection(fieldName);
        ColumnProjection newColumn = referencedColumn.withArguments(mergedArgumentMap(referencedColumn.getArguments(), callingColumnArgs, fixedArguments));
        reference = LogicalReference.builder().source(joinSource).column(newColumn).references(buildReferenceForColumn(joinSource, newColumn)).build();
    }
    return JoinReference.builder().path(joinPath).source(source).reference(reference).build();
}
Also used : Path(com.yahoo.elide.core.Path) JoinPath(com.yahoo.elide.datastores.aggregation.core.JoinPath) JoinPath(com.yahoo.elide.datastores.aggregation.core.JoinPath) Queryable(com.yahoo.elide.datastores.aggregation.query.Queryable) ColumnProjection(com.yahoo.elide.datastores.aggregation.query.ColumnProjection) Argument.getArgumentMapFromString(com.yahoo.elide.core.request.Argument.getArgumentMapFromString)

Example 32 with ColumnProjection

use of com.yahoo.elide.datastores.aggregation.query.ColumnProjection in project elide by yahoo.

the class ExpressionParser method parse.

/**
 * Parses the column or join expression and returns the list of discovered references.
 * @param source The source table where the column or join expression lives.
 * @param expression The expression to parse.
 * @param callingColumnArgs Arguments available with calling column.
 * @return A list of discovered references.
 */
public List<Reference> parse(Queryable source, String expression, Map<String, Argument> callingColumnArgs) {
    List<String> referenceNames = resolveFormulaReferences(expression);
    List<Reference> results = new ArrayList<>();
    Map<String, Argument> fixedArguments = new HashMap<>();
    for (String referenceName : referenceNames) {
        // Change `sql from='joinName' column='columnName[a1:v1][a2:v2]'` to `joinName.columnName`
        if (referenceName.startsWith(SQL_HELPER_PREFIX)) {
            try {
                Template template = handlebars.compileInline(toFormulaReference(referenceName));
                referenceName = template.apply(Collections.emptyMap());
                int argsIndex = referenceName.indexOf('[');
                if (argsIndex >= 0) {
                    fixedArguments = getArgumentMapFromString(referenceName.substring(argsIndex));
                    referenceName = referenceName.substring(0, argsIndex);
                }
            } catch (IOException e) {
                throw new IllegalStateException(e.getMessage());
            }
        }
        // ignore $$column.expr
        if (referenceName.equals(COLUMN_EXPR)) {
            continue;
        }
        if (referenceName.startsWith(COLUMN_ARGS_PREFIX)) {
            results.add(ColumnArgReference.builder().argName(referenceName.substring(COLUMN_ARGS_PREFIX.length())).build());
        } else if (referenceName.startsWith(TABLE_ARGS_PREFIX)) {
            results.add(TableArgReference.builder().argName(referenceName.substring(TABLE_ARGS_PREFIX.length())).build());
        } else if (referenceName.startsWith("$")) {
            results.add(PhysicalReference.builder().source(source).name(referenceName.substring(1)).build());
        } else if (referenceName.contains(".")) {
            results.add(buildJoin(source, referenceName, callingColumnArgs, fixedArguments));
        } else {
            ColumnProjection referencedColumn = source.getColumnProjection(referenceName);
            Preconditions.checkNotNull(referencedColumn, String.format("Couldn't find column: '%s' for table: '%s'", referenceName, source.getName()));
            ColumnProjection newColumn = referencedColumn.withArguments(mergedArgumentMap(referencedColumn.getArguments(), callingColumnArgs, fixedArguments));
            List<Reference> references = buildReferenceForColumn(source, newColumn);
            results.add(LogicalReference.builder().source(source).column(newColumn).references(references).build());
        }
    }
    return results;
}
Also used : Argument(com.yahoo.elide.core.request.Argument) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) Argument.getArgumentMapFromString(com.yahoo.elide.core.request.Argument.getArgumentMapFromString) IOException(java.io.IOException) Template(com.github.jknack.handlebars.Template) ColumnProjection(com.yahoo.elide.datastores.aggregation.query.ColumnProjection) ArrayList(java.util.ArrayList) List(java.util.List)

Example 33 with ColumnProjection

use of com.yahoo.elide.datastores.aggregation.query.ColumnProjection in project elide by yahoo.

the class QueryPlanTranslator method addHiddenProjections.

public static Query.QueryBuilder addHiddenProjections(MetaDataStore metaDataStore, Query.QueryBuilder builder, Query query) {
    Set<ColumnProjection> directReferencedColumns = Streams.concat(query.getColumnProjections().stream(), query.getFilterProjections(query.getWhereFilter(), ColumnProjection.class).stream()).collect(Collectors.toSet());
    ExpressionParser parser = new ExpressionParser(metaDataStore);
    Set<ColumnProjection> indirectReferenceColumns = new HashSet<>();
    directReferencedColumns.forEach(column -> {
        parser.parse(query.getSource(), column).stream().map(reference -> reference.accept(new ReferenceExtractor<LogicalReference>(LogicalReference.class, metaDataStore, ReferenceExtractor.Mode.SAME_QUERY))).flatMap(Set::stream).map(LogicalReference::getColumn).forEach(indirectReferenceColumns::add);
    });
    Streams.concat(directReferencedColumns.stream(), indirectReferenceColumns.stream()).forEach(column -> {
        if (query.getColumnProjection(column.getAlias(), column.getArguments()) == null) {
            builder.column(column.withProjected(false));
        }
    });
    return builder;
}
Also used : ReferenceExtractor(com.yahoo.elide.datastores.aggregation.queryengines.sql.expression.ReferenceExtractor) Queryable(com.yahoo.elide.datastores.aggregation.query.Queryable) Set(java.util.Set) QueryPlan(com.yahoo.elide.datastores.aggregation.query.QueryPlan) Streams(com.google.common.collect.Streams) Collectors(java.util.stream.Collectors) HashSet(java.util.HashSet) Query(com.yahoo.elide.datastores.aggregation.query.Query) LogicalReference(com.yahoo.elide.datastores.aggregation.queryengines.sql.expression.LogicalReference) AndFilterExpression(com.yahoo.elide.core.filter.expression.AndFilterExpression) ColumnProjection(com.yahoo.elide.datastores.aggregation.query.ColumnProjection) MetaDataStore(com.yahoo.elide.datastores.aggregation.metadata.MetaDataStore) DefaultQueryPlanMerger(com.yahoo.elide.datastores.aggregation.query.DefaultQueryPlanMerger) FilterExpression(com.yahoo.elide.core.filter.expression.FilterExpression) QueryPlanMerger(com.yahoo.elide.datastores.aggregation.query.QueryPlanMerger) ExpressionParser(com.yahoo.elide.datastores.aggregation.queryengines.sql.expression.ExpressionParser) QueryVisitor(com.yahoo.elide.datastores.aggregation.query.QueryVisitor) Set(java.util.Set) HashSet(java.util.HashSet) ColumnProjection(com.yahoo.elide.datastores.aggregation.query.ColumnProjection) ExpressionParser(com.yahoo.elide.datastores.aggregation.queryengines.sql.expression.ExpressionParser) LogicalReference(com.yahoo.elide.datastores.aggregation.queryengines.sql.expression.LogicalReference) HashSet(java.util.HashSet)

Example 34 with ColumnProjection

use of com.yahoo.elide.datastores.aggregation.query.ColumnProjection 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));
}
Also used : LinkedHashSet(java.util.LinkedHashSet) PredicateExtractionVisitor(com.yahoo.elide.core.filter.expression.PredicateExtractionVisitor) FilterPredicate(com.yahoo.elide.core.filter.predicates.FilterPredicate) Path(com.yahoo.elide.core.Path) Function(java.util.function.Function) Argument(com.yahoo.elide.core.request.Argument) SQLDialect(com.yahoo.elide.datastores.aggregation.queryengines.sql.dialects.SQLDialect) Map(java.util.Map) ColumnProjection(com.yahoo.elide.datastores.aggregation.query.ColumnProjection) FilterTranslator(com.yahoo.elide.datastores.jpql.filter.FilterTranslator) FilterExpression(com.yahoo.elide.core.filter.expression.FilterExpression) LinkedHashSet(java.util.LinkedHashSet) QueryVisitor(com.yahoo.elide.datastores.aggregation.query.QueryVisitor) TableContext(com.yahoo.elide.datastores.aggregation.metadata.TableContext) JoinExpressionExtractor(com.yahoo.elide.datastores.aggregation.queryengines.sql.expression.JoinExpressionExtractor) Sorting(com.yahoo.elide.core.request.Sorting) Queryable(com.yahoo.elide.datastores.aggregation.query.Queryable) FromSubquery(com.yahoo.elide.datastores.aggregation.queryengines.sql.annotation.FromSubquery) ColumnContext(com.yahoo.elide.datastores.aggregation.metadata.ColumnContext) Collection(java.util.Collection) ValueType(com.yahoo.elide.datastores.aggregation.metadata.enums.ValueType) Set(java.util.Set) FromTable(com.yahoo.elide.datastores.aggregation.queryengines.sql.annotation.FromTable) Collectors(java.util.stream.Collectors) EntityDictionary(com.yahoo.elide.core.dictionary.EntityDictionary) Query(com.yahoo.elide.datastores.aggregation.query.Query) List(java.util.List) BadRequestException(com.yahoo.elide.core.exceptions.BadRequestException) Stream(java.util.stream.Stream) Pagination(com.yahoo.elide.core.request.Pagination) Type(com.yahoo.elide.core.type.Type) MetaDataStore(com.yahoo.elide.datastores.aggregation.metadata.MetaDataStore) ExpressionParser(com.yahoo.elide.datastores.aggregation.queryengines.sql.expression.ExpressionParser) Reference(com.yahoo.elide.datastores.aggregation.queryengines.sql.expression.Reference) Path(com.yahoo.elide.core.Path) Pagination(com.yahoo.elide.core.request.Pagination) ColumnProjection(com.yahoo.elide.datastores.aggregation.query.ColumnProjection)

Example 35 with ColumnProjection

use of com.yahoo.elide.datastores.aggregation.query.ColumnProjection in project elide by yahoo.

the class SQLColumnProjection method nest.

@Override
default Pair<ColumnProjection, Set<ColumnProjection>> nest(Queryable source, MetaDataStore store, boolean joinInOuter) {
    List<Reference> references = new ExpressionParser(store).parse(source, getExpression());
    boolean requiresJoin = requiresJoin(references);
    String columnId = source.isRoot() ? getName() : getAlias();
    boolean inProjection = source.getColumnProjection(columnId, getArguments(), true) != null;
    ColumnProjection outerProjection;
    Set<ColumnProjection> innerProjections;
    if (requiresJoin && joinInOuter) {
        String outerProjectionExpression = toPhysicalReferences(source, store);
        outerProjection = withExpression(outerProjectionExpression, inProjection);
        innerProjections = extractPhysicalReferences(source, references, store);
    } else {
        outerProjection = withExpression("{{$" + this.getSafeAlias() + "}}", isProjected());
        innerProjections = new LinkedHashSet<>(Arrays.asList(this));
    }
    return Pair.of(outerProjection, innerProjections);
}
Also used : JoinReference(com.yahoo.elide.datastores.aggregation.queryengines.sql.expression.JoinReference) PhysicalReference(com.yahoo.elide.datastores.aggregation.queryengines.sql.expression.PhysicalReference) Reference(com.yahoo.elide.datastores.aggregation.queryengines.sql.expression.Reference) ColumnArgReference(com.yahoo.elide.datastores.aggregation.queryengines.sql.expression.ColumnArgReference) ColumnProjection(com.yahoo.elide.datastores.aggregation.query.ColumnProjection) ExpressionParser(com.yahoo.elide.datastores.aggregation.queryengines.sql.expression.ExpressionParser)

Aggregations

ColumnProjection (com.yahoo.elide.datastores.aggregation.query.ColumnProjection)36 Test (org.junit.jupiter.api.Test)22 SQLTable (com.yahoo.elide.datastores.aggregation.queryengines.sql.metadata.SQLTable)13 Argument (com.yahoo.elide.core.request.Argument)7 Queryable (com.yahoo.elide.datastores.aggregation.query.Queryable)6 Query (com.yahoo.elide.datastores.aggregation.query.Query)5 Argument.getArgumentMapFromString (com.yahoo.elide.core.request.Argument.getArgumentMapFromString)4 ValueType (com.yahoo.elide.datastores.aggregation.metadata.enums.ValueType)4 Column (com.yahoo.elide.datastores.aggregation.metadata.models.Column)4 ExpressionParser (com.yahoo.elide.datastores.aggregation.queryengines.sql.expression.ExpressionParser)4 List (java.util.List)4 Set (java.util.Set)4 Collectors (java.util.stream.Collectors)4 Path (com.yahoo.elide.core.Path)3 FilterExpression (com.yahoo.elide.core.filter.expression.FilterExpression)3 MetaDataStore (com.yahoo.elide.datastores.aggregation.metadata.MetaDataStore)3 Reference (com.yahoo.elide.datastores.aggregation.queryengines.sql.expression.Reference)3 HashMap (java.util.HashMap)3 HandlebarsException (com.github.jknack.handlebars.HandlebarsException)2 EntityDictionary (com.yahoo.elide.core.dictionary.EntityDictionary)2