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())));
}
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);
}
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);
}
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());
}
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();
}
Aggregations