Search in sources :

Example 1 with ComparisonExpression

use of io.trino.sql.tree.ComparisonExpression in project trino by trinodb.

the class ImplementIntersectDistinctAsUnion method apply.

@Override
public Result apply(IntersectNode node, Captures captures, Context context) {
    SetOperationNodeTranslator translator = new SetOperationNodeTranslator(context.getSession(), metadata, context.getSymbolAllocator(), context.getIdAllocator());
    SetOperationNodeTranslator.TranslationResult result = translator.makeSetContainmentPlanForDistinct(node);
    // intersect predicate: the row must be present in every source
    Expression predicate = and(result.getCountSymbols().stream().map(symbol -> new ComparisonExpression(GREATER_THAN_OR_EQUAL, symbol.toSymbolReference(), new GenericLiteral("BIGINT", "1"))).collect(toImmutableList()));
    return Result.ofPlanNode(new ProjectNode(context.getIdAllocator().getNextId(), new FilterNode(context.getIdAllocator().getNextId(), result.getPlanNode(), predicate), Assignments.identity(node.getOutputSymbols())));
}
Also used : ComparisonExpression(io.trino.sql.tree.ComparisonExpression) ComparisonExpression(io.trino.sql.tree.ComparisonExpression) Expression(io.trino.sql.tree.Expression) FilterNode(io.trino.sql.planner.plan.FilterNode) ProjectNode(io.trino.sql.planner.plan.ProjectNode) GenericLiteral(io.trino.sql.tree.GenericLiteral)

Example 2 with ComparisonExpression

use of io.trino.sql.tree.ComparisonExpression in project trino by trinodb.

the class ImplementOffset method apply.

@Override
public Result apply(OffsetNode parent, Captures captures, Context context) {
    Symbol rowNumberSymbol = context.getSymbolAllocator().newSymbol("row_number", BIGINT);
    RowNumberNode rowNumberNode = new RowNumberNode(context.getIdAllocator().getNextId(), parent.getSource(), ImmutableList.of(), true, rowNumberSymbol, Optional.empty(), Optional.empty());
    FilterNode filterNode = new FilterNode(context.getIdAllocator().getNextId(), rowNumberNode, new ComparisonExpression(ComparisonExpression.Operator.GREATER_THAN, rowNumberSymbol.toSymbolReference(), new GenericLiteral("BIGINT", Long.toString(parent.getCount()))));
    ProjectNode projectNode = new ProjectNode(context.getIdAllocator().getNextId(), filterNode, Assignments.identity(parent.getOutputSymbols()));
    return Result.ofPlanNode(projectNode);
}
Also used : ComparisonExpression(io.trino.sql.tree.ComparisonExpression) Symbol(io.trino.sql.planner.Symbol) FilterNode(io.trino.sql.planner.plan.FilterNode) RowNumberNode(io.trino.sql.planner.plan.RowNumberNode) ProjectNode(io.trino.sql.planner.plan.ProjectNode) GenericLiteral(io.trino.sql.tree.GenericLiteral)

Example 3 with ComparisonExpression

use of io.trino.sql.tree.ComparisonExpression in project trino by trinodb.

the class EqualityInference method newInstance.

public static EqualityInference newInstance(Metadata metadata, Collection<Expression> expressions) {
    DisjointSet<Expression> equalities = new DisjointSet<>();
    expressions.stream().flatMap(expression -> extractConjuncts(expression).stream()).filter(expression -> isInferenceCandidate(metadata, expression)).forEach(expression -> {
        ComparisonExpression comparison = (ComparisonExpression) expression;
        Expression expression1 = comparison.getLeft();
        Expression expression2 = comparison.getRight();
        equalities.findAndUnion(expression1, expression2);
    });
    Collection<Set<Expression>> equivalentClasses = equalities.getEquivalentClasses();
    // Map every expression to the set of equivalent expressions
    Map<Expression, Set<Expression>> byExpression = new HashMap<>();
    for (Set<Expression> equivalence : equivalentClasses) {
        equivalence.forEach(expression -> byExpression.put(expression, equivalence));
    }
    // For every non-derived expression, extract the sub-expressions and see if they can be rewritten as other expressions. If so,
    // use this new information to update the known equalities.
    Set<Expression> derivedExpressions = new LinkedHashSet<>();
    for (Expression expression : byExpression.keySet()) {
        if (derivedExpressions.contains(expression)) {
            continue;
        }
        SubExpressionExtractor.extract(expression).filter(e -> !e.equals(expression)).forEach(subExpression -> {
            byExpression.getOrDefault(subExpression, ImmutableSet.of()).stream().filter(e -> !e.equals(subExpression)).forEach(equivalentSubExpression -> {
                Expression rewritten = replaceExpression(expression, ImmutableMap.of(subExpression, equivalentSubExpression));
                equalities.findAndUnion(expression, rewritten);
                derivedExpressions.add(rewritten);
            });
        });
    }
    Multimap<Expression, Expression> equalitySets = makeEqualitySets(equalities);
    ImmutableMap.Builder<Expression, Expression> canonicalMappings = ImmutableMap.builder();
    for (Map.Entry<Expression, Expression> entry : equalitySets.entries()) {
        Expression canonical = entry.getKey();
        Expression expression = entry.getValue();
        canonicalMappings.put(expression, canonical);
    }
    return new EqualityInference(equalitySets, canonicalMappings.buildOrThrow(), derivedExpressions);
}
Also used : Arrays(java.util.Arrays) HashMap(java.util.HashMap) Multimap(com.google.common.collect.Multimap) ArrayList(java.util.ArrayList) ImmutableList(com.google.common.collect.ImmutableList) DeterminismEvaluator.isDeterministic(io.trino.sql.planner.DeterminismEvaluator.isDeterministic) Map(java.util.Map) Objects.requireNonNull(java.util.Objects.requireNonNull) DisjointSet(io.trino.util.DisjointSet) LinkedHashSet(java.util.LinkedHashSet) ImmutableSetMultimap(com.google.common.collect.ImmutableSetMultimap) ImmutableSet(com.google.common.collect.ImmutableSet) ImmutableMap(com.google.common.collect.ImmutableMap) Predicate(java.util.function.Predicate) Collection(java.util.Collection) NullabilityAnalyzer.mayReturnNullOnNonNullInput(io.trino.sql.planner.NullabilityAnalyzer.mayReturnNullOnNonNullInput) ToIntFunction(java.util.function.ToIntFunction) Set(java.util.Set) Collectors(java.util.stream.Collectors) ComparisonExpression(io.trino.sql.tree.ComparisonExpression) Objects(java.util.Objects) List(java.util.List) Stream(java.util.stream.Stream) SymbolReference(io.trino.sql.tree.SymbolReference) Metadata(io.trino.metadata.Metadata) ExpressionNodeInliner.replaceExpression(io.trino.sql.planner.ExpressionNodeInliner.replaceExpression) Expression(io.trino.sql.tree.Expression) ExpressionUtils.extractConjuncts(io.trino.sql.ExpressionUtils.extractConjuncts) VisibleForTesting(com.google.common.annotations.VisibleForTesting) Comparator(java.util.Comparator) LinkedHashSet(java.util.LinkedHashSet) DisjointSet(io.trino.util.DisjointSet) LinkedHashSet(java.util.LinkedHashSet) ImmutableSet(com.google.common.collect.ImmutableSet) Set(java.util.Set) HashMap(java.util.HashMap) ImmutableMap(com.google.common.collect.ImmutableMap) ComparisonExpression(io.trino.sql.tree.ComparisonExpression) ComparisonExpression(io.trino.sql.tree.ComparisonExpression) ExpressionNodeInliner.replaceExpression(io.trino.sql.planner.ExpressionNodeInliner.replaceExpression) Expression(io.trino.sql.tree.Expression) DisjointSet(io.trino.util.DisjointSet) HashMap(java.util.HashMap) Map(java.util.Map) ImmutableMap(com.google.common.collect.ImmutableMap)

Example 4 with ComparisonExpression

use of io.trino.sql.tree.ComparisonExpression in project trino by trinodb.

the class EqualityInference method generateEqualitiesPartitionedBy.

/**
 * Dumps the inference equalities as equality expressions that are partitioned by the symbolScope.
 * All stored equalities are returned in a compact set and will be classified into three groups as determined by the symbol scope:
 * <ol>
 * <li>equalities that fit entirely within the symbol scope</li>
 * <li>equalities that fit entirely outside of the symbol scope</li>
 * <li>equalities that straddle the symbol scope</li>
 * </ol>
 * <pre>
 * Example:
 *   Stored Equalities:
 *     a = b = c
 *     d = e = f = g
 *
 *   Symbol Scope:
 *     a, b, d, e
 *
 *   Output EqualityPartition:
 *     Scope Equalities:
 *       a = b
 *       d = e
 *     Complement Scope Equalities
 *       f = g
 *     Scope Straddling Equalities
 *       a = c
 *       d = f
 * </pre>
 */
public EqualityPartition generateEqualitiesPartitionedBy(Set<Symbol> scope) {
    ImmutableSet.Builder<Expression> scopeEqualities = ImmutableSet.builder();
    ImmutableSet.Builder<Expression> scopeComplementEqualities = ImmutableSet.builder();
    ImmutableSet.Builder<Expression> scopeStraddlingEqualities = ImmutableSet.builder();
    for (Collection<Expression> equalitySet : equalitySets.asMap().values()) {
        Set<Expression> scopeExpressions = new LinkedHashSet<>();
        Set<Expression> scopeComplementExpressions = new LinkedHashSet<>();
        Set<Expression> scopeStraddlingExpressions = new LinkedHashSet<>();
        // Try to push each non-derived expression into one side of the scope
        equalitySet.stream().filter(candidate -> !derivedExpressions.contains(candidate)).forEach(candidate -> {
            Expression scopeRewritten = rewrite(candidate, scope::contains, false);
            if (scopeRewritten != null) {
                scopeExpressions.add(scopeRewritten);
            }
            Expression scopeComplementRewritten = rewrite(candidate, expression -> !scope.contains(expression), false);
            if (scopeComplementRewritten != null) {
                scopeComplementExpressions.add(scopeComplementRewritten);
            }
            if (scopeRewritten == null && scopeComplementRewritten == null) {
                scopeStraddlingExpressions.add(candidate);
            }
        });
        // Compile the equality expressions on each side of the scope
        Expression matchingCanonical = getCanonical(scopeExpressions.stream());
        if (scopeExpressions.size() >= 2) {
            scopeExpressions.stream().filter(expression -> !expression.equals(matchingCanonical)).map(expression -> new ComparisonExpression(ComparisonExpression.Operator.EQUAL, matchingCanonical, expression)).forEach(scopeEqualities::add);
        }
        Expression complementCanonical = getCanonical(scopeComplementExpressions.stream());
        if (scopeComplementExpressions.size() >= 2) {
            scopeComplementExpressions.stream().filter(expression -> !expression.equals(complementCanonical)).map(expression -> new ComparisonExpression(ComparisonExpression.Operator.EQUAL, complementCanonical, expression)).forEach(scopeComplementEqualities::add);
        }
        // Compile the scope straddling equality expressions
        List<Expression> connectingExpressions = new ArrayList<>();
        connectingExpressions.add(matchingCanonical);
        connectingExpressions.add(complementCanonical);
        connectingExpressions.addAll(scopeStraddlingExpressions);
        connectingExpressions = connectingExpressions.stream().filter(Objects::nonNull).collect(Collectors.toList());
        Expression connectingCanonical = getCanonical(connectingExpressions.stream());
        if (connectingCanonical != null) {
            connectingExpressions.stream().filter(expression -> !expression.equals(connectingCanonical)).map(expression -> new ComparisonExpression(ComparisonExpression.Operator.EQUAL, connectingCanonical, expression)).forEach(scopeStraddlingEqualities::add);
        }
    }
    return new EqualityPartition(scopeEqualities.build(), scopeComplementEqualities.build(), scopeStraddlingEqualities.build());
}
Also used : LinkedHashSet(java.util.LinkedHashSet) Arrays(java.util.Arrays) HashMap(java.util.HashMap) Multimap(com.google.common.collect.Multimap) ArrayList(java.util.ArrayList) ImmutableList(com.google.common.collect.ImmutableList) DeterminismEvaluator.isDeterministic(io.trino.sql.planner.DeterminismEvaluator.isDeterministic) Map(java.util.Map) Objects.requireNonNull(java.util.Objects.requireNonNull) DisjointSet(io.trino.util.DisjointSet) LinkedHashSet(java.util.LinkedHashSet) ImmutableSetMultimap(com.google.common.collect.ImmutableSetMultimap) ImmutableSet(com.google.common.collect.ImmutableSet) ImmutableMap(com.google.common.collect.ImmutableMap) Predicate(java.util.function.Predicate) Collection(java.util.Collection) NullabilityAnalyzer.mayReturnNullOnNonNullInput(io.trino.sql.planner.NullabilityAnalyzer.mayReturnNullOnNonNullInput) ToIntFunction(java.util.function.ToIntFunction) Set(java.util.Set) Collectors(java.util.stream.Collectors) ComparisonExpression(io.trino.sql.tree.ComparisonExpression) Objects(java.util.Objects) List(java.util.List) Stream(java.util.stream.Stream) SymbolReference(io.trino.sql.tree.SymbolReference) Metadata(io.trino.metadata.Metadata) ExpressionNodeInliner.replaceExpression(io.trino.sql.planner.ExpressionNodeInliner.replaceExpression) Expression(io.trino.sql.tree.Expression) ExpressionUtils.extractConjuncts(io.trino.sql.ExpressionUtils.extractConjuncts) VisibleForTesting(com.google.common.annotations.VisibleForTesting) Comparator(java.util.Comparator) ArrayList(java.util.ArrayList) ComparisonExpression(io.trino.sql.tree.ComparisonExpression) ImmutableSet(com.google.common.collect.ImmutableSet) ComparisonExpression(io.trino.sql.tree.ComparisonExpression) ExpressionNodeInliner.replaceExpression(io.trino.sql.planner.ExpressionNodeInliner.replaceExpression) Expression(io.trino.sql.tree.Expression) Objects(java.util.Objects)

Example 5 with ComparisonExpression

use of io.trino.sql.tree.ComparisonExpression in project trino by trinodb.

the class PushJoinIntoTableScan method getPushableJoinCondition.

private Optional<JoinCondition> getPushableJoinCondition(Expression conjunct, Set<Symbol> leftSymbols, Set<Symbol> rightSymbols, Context context) {
    if (!(conjunct instanceof ComparisonExpression)) {
        return Optional.empty();
    }
    ComparisonExpression comparison = (ComparisonExpression) conjunct;
    if (!(comparison.getLeft() instanceof SymbolReference) || !(comparison.getRight() instanceof SymbolReference)) {
        return Optional.empty();
    }
    Symbol left = Symbol.from(comparison.getLeft());
    Symbol right = Symbol.from(comparison.getRight());
    ComparisonExpression.Operator operator = comparison.getOperator();
    if (!leftSymbols.contains(left)) {
        // lets try with flipped expression
        Symbol tmp = left;
        left = right;
        right = tmp;
        operator = operator.flip();
    }
    if (leftSymbols.contains(left) && rightSymbols.contains(right)) {
        return Optional.of(new JoinCondition(joinConditionOperator(operator), new Variable(left.getName(), context.getSymbolAllocator().getTypes().get(left)), new Variable(right.getName(), context.getSymbolAllocator().getTypes().get(right))));
    }
    return Optional.empty();
}
Also used : ComparisonExpression(io.trino.sql.tree.ComparisonExpression) Variable(io.trino.spi.expression.Variable) SymbolReference(io.trino.sql.tree.SymbolReference) Symbol(io.trino.sql.planner.Symbol) JoinCondition(io.trino.spi.connector.JoinCondition)

Aggregations

ComparisonExpression (io.trino.sql.tree.ComparisonExpression)58 Test (org.testng.annotations.Test)30 ImmutableList (com.google.common.collect.ImmutableList)24 Expression (io.trino.sql.tree.Expression)23 Symbol (io.trino.sql.planner.Symbol)22 SymbolReference (io.trino.sql.tree.SymbolReference)21 ImmutableMap (com.google.common.collect.ImmutableMap)18 LongLiteral (io.trino.sql.tree.LongLiteral)17 BaseRuleTest (io.trino.sql.planner.iterative.rule.test.BaseRuleTest)15 FunctionCall (io.trino.sql.tree.FunctionCall)15 GenericLiteral (io.trino.sql.tree.GenericLiteral)15 QualifiedName (io.trino.sql.tree.QualifiedName)15 Optional (java.util.Optional)15 StringLiteral (io.trino.sql.tree.StringLiteral)14 PlanMatchPattern.values (io.trino.sql.planner.assertions.PlanMatchPattern.values)13 Type (io.trino.spi.type.Type)12 BIGINT (io.trino.spi.type.BigintType.BIGINT)11 FilterNode (io.trino.sql.planner.plan.FilterNode)11 ResolvedFunction (io.trino.metadata.ResolvedFunction)10 GREATER_THAN (io.trino.sql.tree.ComparisonExpression.Operator.GREATER_THAN)10