Search in sources :

Example 1 with Symbol

use of io.crate.expression.symbol.Symbol in project crate by crate.

the class RelationAnalyzer method analyzeGroupBy.

private List<Symbol> analyzeGroupBy(SelectAnalysis selectAnalysis, List<Expression> groupBy, ExpressionAnalyzer expressionAnalyzer, ExpressionAnalysisContext expressionAnalysisContext) {
    List<Symbol> groupBySymbols = new ArrayList<>(groupBy.size());
    for (Expression expression : groupBy) {
        Symbol symbol = symbolFromExpressionFallbackOnSelectOutput(expression, selectAnalysis, "GROUP BY", expressionAnalyzer, expressionAnalysisContext);
        GroupBySymbolValidator.validate(symbol);
        groupBySymbols.add(symbol);
    }
    return groupBySymbols;
}
Also used : Expression(io.crate.sql.tree.Expression) Symbol(io.crate.expression.symbol.Symbol) ArrayList(java.util.ArrayList)

Example 2 with Symbol

use of io.crate.expression.symbol.Symbol in project crate by crate.

the class RelationAnalyzer method visitQuery.

@Override
protected AnalyzedRelation visitQuery(Query node, StatementAnalysisContext statementContext) {
    AnalyzedRelation childRelation = node.getQueryBody().accept(this, statementContext);
    if (node.getOrderBy().isEmpty() && node.getLimit().isEmpty() && node.getOffset().isEmpty()) {
        return childRelation;
    }
    // In case of Set Operation (UNION, INTERSECT EXCEPT) or VALUES clause,
    // the `node` contains the ORDER BY and/or LIMIT and/or OFFSET and wraps the
    // actual operation (eg: UNION) which is parsed into the `queryBody` of the `node`.
    // Use child relation to process expressions of the "root" Query node
    statementContext.startRelation();
    RelationAnalysisContext relationAnalysisContext = statementContext.currentRelationContext();
    relationAnalysisContext.addSourceRelation(childRelation);
    statementContext.endRelation();
    List<Symbol> childRelationFields = childRelation.outputs();
    var coordinatorTxnCtx = statementContext.transactionContext();
    ExpressionAnalyzer expressionAnalyzer = new ExpressionAnalyzer(coordinatorTxnCtx, nodeCtx, statementContext.paramTyeHints(), new FullQualifiedNameFieldProvider(relationAnalysisContext.sources(), relationAnalysisContext.parentSources(), coordinatorTxnCtx.sessionContext().searchPath().currentSchema()), new SubqueryAnalyzer(this, statementContext));
    ExpressionAnalysisContext expressionAnalysisContext = relationAnalysisContext.expressionAnalysisContext();
    SelectAnalysis selectAnalysis = new SelectAnalysis(childRelationFields.size(), relationAnalysisContext.sources(), expressionAnalyzer, expressionAnalysisContext);
    for (Symbol field : childRelationFields) {
        selectAnalysis.add(Symbols.pathFromSymbol(field), field);
    }
    var normalizer = EvaluatingNormalizer.functionOnlyNormalizer(nodeCtx, f -> expressionAnalysisContext.isEagerNormalizationAllowed() && f.isDeterministic());
    return new QueriedSelectRelation(false, List.of(childRelation), List.of(), selectAnalysis.outputSymbols(), Literal.BOOLEAN_TRUE, List.of(), null, analyzeOrderBy(selectAnalysis, node.getOrderBy(), expressionAnalyzer, expressionAnalysisContext, false, false), longSymbolOrNull(node.getLimit(), expressionAnalyzer, expressionAnalysisContext, normalizer, coordinatorTxnCtx), longSymbolOrNull(node.getOffset(), expressionAnalyzer, expressionAnalysisContext, normalizer, coordinatorTxnCtx));
}
Also used : SelectAnalysis(io.crate.analyze.relations.select.SelectAnalysis) ExpressionAnalysisContext(io.crate.analyze.expressions.ExpressionAnalysisContext) Symbol(io.crate.expression.symbol.Symbol) ExpressionAnalyzer(io.crate.analyze.expressions.ExpressionAnalyzer) QueriedSelectRelation(io.crate.analyze.QueriedSelectRelation) SubqueryAnalyzer(io.crate.analyze.expressions.SubqueryAnalyzer)

Example 3 with Symbol

use of io.crate.expression.symbol.Symbol in project crate by crate.

the class RelationAnalyzer method analyzeHaving.

@Nullable
private Symbol analyzeHaving(Optional<Expression> having, @Nullable List<Symbol> groupBy, ExpressionAnalyzer expressionAnalyzer, ExpressionAnalysisContext expressionAnalysisContext) {
    if (having.isPresent()) {
        if (!expressionAnalysisContext.hasAggregates() && (groupBy == null || groupBy.isEmpty())) {
            throw new IllegalArgumentException("HAVING clause can only be used in GROUP BY or global aggregate queries");
        }
        Symbol symbol = expressionAnalyzer.convert(having.get(), expressionAnalysisContext);
        HavingSymbolValidator.validate(symbol, groupBy);
        return symbol;
    }
    return null;
}
Also used : Symbol(io.crate.expression.symbol.Symbol) Nullable(javax.annotation.Nullable)

Example 4 with Symbol

use of io.crate.expression.symbol.Symbol in project crate by crate.

the class FullQualifiedNameFieldProvider method resolveField.

@Override
public Symbol resolveField(QualifiedName qualifiedName, @Nullable List<String> path, Operation operation, boolean errorOnUnknownObjectKey) {
    List<String> parts = qualifiedName.getParts();
    String columnSchema = null;
    String columnTableName = null;
    ColumnIdent columnIdent = new ColumnIdent(parts.get(parts.size() - 1), path);
    switch(parts.size()) {
        case 1:
            break;
        case 2:
            columnTableName = parts.get(0);
            break;
        case 3:
            columnSchema = parts.get(0);
            columnTableName = parts.get(1);
            break;
        default:
            throw new IllegalArgumentException("Column reference \"%s\" has too many parts. " + "A column reference can have at most 3 parts and must have one of the following formats:  " + "\"<column>\", \"<table>.<column>\" or \"<schema>.<table>.<column>\"");
    }
    boolean schemaMatched = false;
    boolean tableNameMatched = false;
    Symbol lastField = null;
    for (var entry : sources.entrySet()) {
        RelationName relName = entry.getKey();
        String sourceSchema = relName.schema();
        String sourceTableOrAlias = relName.name();
        if (columnSchema != null && !columnSchema.equals(sourceSchema)) {
            continue;
        }
        schemaMatched = true;
        if (columnTableName != null && !sourceTableOrAlias.equals(columnTableName)) {
            continue;
        }
        tableNameMatched = true;
        AnalyzedRelation sourceRelation = entry.getValue();
        Symbol newField = sourceRelation.getField(columnIdent, operation, errorOnUnknownObjectKey);
        if (newField != null) {
            if (lastField != null) {
                if (errorOnUnknownObjectKey == false) {
                    /* ex) CREATE TABLE c1 (obj object as (x int));
                         *     CREATE TABLE c2 (obj object as (y int));
                         *     select obj['x'] from c1, c2;
                         *     --> ambiguous because c2.obj['x'] is another candidate with errorOnUnknownObjectKey = false
                         */
                    return resolveField(qualifiedName, path, operation, true);
                }
                throw new AmbiguousColumnException(columnIdent, newField);
            }
            lastField = newField;
        }
    }
    if (lastField == null) {
        if (!schemaMatched || !tableNameMatched) {
            String schema = columnSchema == null ? defaultSchema : columnSchema;
            raiseUnsupportedFeatureIfInParentScope(columnSchema, columnTableName, schema);
            RelationName relationName = new RelationName(schema, columnTableName);
            throw new RelationUnknown(relationName);
        }
        RelationName relationName = sources.entrySet().iterator().next().getKey();
        throw new ColumnUnknownException(columnIdent.sqlFqn(), relationName);
    }
    return lastField;
}
Also used : ColumnIdent(io.crate.metadata.ColumnIdent) RelationUnknown(io.crate.exceptions.RelationUnknown) ColumnUnknownException(io.crate.exceptions.ColumnUnknownException) Symbol(io.crate.expression.symbol.Symbol) RelationName(io.crate.metadata.RelationName) AmbiguousColumnException(io.crate.exceptions.AmbiguousColumnException)

Example 5 with Symbol

use of io.crate.expression.symbol.Symbol in project crate by crate.

the class WhereClauseAnalyzer method resolvePartitions.

public static PartitionResult resolvePartitions(Symbol query, DocTableInfo tableInfo, CoordinatorTxnCtx coordinatorTxnCtx, NodeContext nodeCtx) {
    assert tableInfo.isPartitioned() : "table must be partitioned in order to resolve partitions";
    assert !tableInfo.partitions().isEmpty() : "table must have at least one partition";
    PartitionReferenceResolver partitionReferenceResolver = preparePartitionResolver(tableInfo.partitionedByColumns());
    EvaluatingNormalizer normalizer = new EvaluatingNormalizer(nodeCtx, RowGranularity.PARTITION, partitionReferenceResolver, null);
    Symbol normalized;
    Map<Symbol, List<Literal>> queryPartitionMap = new HashMap<>();
    for (PartitionName partitionName : tableInfo.partitions()) {
        for (PartitionExpression partitionExpression : partitionReferenceResolver.expressions()) {
            partitionExpression.setNextRow(partitionName);
        }
        normalized = normalizer.normalize(query, coordinatorTxnCtx);
        assert normalized != null : "normalizing a query must not return null";
        if (normalized.equals(query)) {
            // no partition columns inside the where clause
            return new PartitionResult(query, Collections.emptyList());
        }
        boolean canMatch = WhereClause.canMatch(normalized);
        if (canMatch) {
            List<Literal> partitions = queryPartitionMap.get(normalized);
            if (partitions == null) {
                partitions = new ArrayList<>();
                queryPartitionMap.put(normalized, partitions);
            }
            partitions.add(Literal.of(partitionName.asIndexName()));
        }
    }
    if (queryPartitionMap.size() == 1) {
        Map.Entry<Symbol, List<Literal>> entry = Iterables.getOnlyElement(queryPartitionMap.entrySet());
        return new PartitionResult(entry.getKey(), Lists2.map(entry.getValue(), literal -> nullOrString(literal.value())));
    } else if (queryPartitionMap.size() > 0) {
        PartitionResult partitionResult = tieBreakPartitionQueries(normalizer, queryPartitionMap, coordinatorTxnCtx);
        return partitionResult == null ? // the query will then be evaluated correctly within each partition to see whether it matches or not
        new PartitionResult(query, Lists2.map(tableInfo.partitions(), PartitionName::asIndexName)) : partitionResult;
    } else {
        return new PartitionResult(Literal.BOOLEAN_FALSE, Collections.emptyList());
    }
}
Also used : Tuple(io.crate.common.collections.Tuple) ScalarsAndRefsToTrue(io.crate.analyze.ScalarsAndRefsToTrue) HashMap(java.util.HashMap) EvaluatingNormalizer(io.crate.expression.eval.EvaluatingNormalizer) PartitionName(io.crate.metadata.PartitionName) ArrayList(java.util.ArrayList) Map(java.util.Map) StringUtils.nullOrString(io.crate.common.StringUtils.nullOrString) Nullable(javax.annotation.Nullable) DocTableInfo(io.crate.metadata.doc.DocTableInfo) NodeContext(io.crate.metadata.NodeContext) WhereClause(io.crate.analyze.WhereClause) PartitionReferenceResolver(io.crate.metadata.PartitionReferenceResolver) Reference(io.crate.metadata.Reference) Iterables(io.crate.common.collections.Iterables) Lists2(io.crate.common.collections.Lists2) List(java.util.List) RowGranularity(io.crate.metadata.RowGranularity) DocTableRelation(io.crate.analyze.relations.DocTableRelation) Literal(io.crate.expression.symbol.Literal) Symbol(io.crate.expression.symbol.Symbol) AbstractTableRelation(io.crate.analyze.relations.AbstractTableRelation) PartitionExpression(io.crate.expression.reference.partitioned.PartitionExpression) Collections(java.util.Collections) CoordinatorTxnCtx(io.crate.metadata.CoordinatorTxnCtx) EvaluatingNormalizer(io.crate.expression.eval.EvaluatingNormalizer) HashMap(java.util.HashMap) Symbol(io.crate.expression.symbol.Symbol) PartitionName(io.crate.metadata.PartitionName) PartitionExpression(io.crate.expression.reference.partitioned.PartitionExpression) Literal(io.crate.expression.symbol.Literal) ArrayList(java.util.ArrayList) List(java.util.List) PartitionReferenceResolver(io.crate.metadata.PartitionReferenceResolver) HashMap(java.util.HashMap) Map(java.util.Map)

Aggregations

Symbol (io.crate.expression.symbol.Symbol)440 Test (org.junit.Test)243 CrateDummyClusterServiceUnitTest (io.crate.test.integration.CrateDummyClusterServiceUnitTest)170 ArrayList (java.util.ArrayList)77 List (java.util.List)74 Reference (io.crate.metadata.Reference)63 SelectSymbol (io.crate.expression.symbol.SelectSymbol)54 RelationName (io.crate.metadata.RelationName)53 ParameterSymbol (io.crate.expression.symbol.ParameterSymbol)49 Function (io.crate.expression.symbol.Function)46 InputColumn (io.crate.expression.symbol.InputColumn)45 Nullable (javax.annotation.Nullable)39 Row (io.crate.data.Row)38 HashMap (java.util.HashMap)37 Map (java.util.Map)34 AliasSymbol (io.crate.expression.symbol.AliasSymbol)32 ColumnIdent (io.crate.metadata.ColumnIdent)32 DocTableInfo (io.crate.metadata.doc.DocTableInfo)32 Set (java.util.Set)32 ScopedSymbol (io.crate.expression.symbol.ScopedSymbol)31