use of io.prestosql.sql.tree.InPredicate in project hetu-core by openlookeng.
the class TestEqualityInference method testExpressionsThatMayReturnNullOnNonNullInput.
@Test
public void testExpressionsThatMayReturnNullOnNonNullInput() {
List<Expression> candidates = ImmutableList.of(// try_cast
new Cast(nameReference("b"), "BIGINT", true), new FunctionCallBuilder(metadata).setName(QualifiedName.of(TryFunction.NAME)).addArgument(new FunctionType(ImmutableList.of(), VARCHAR), new LambdaExpression(ImmutableList.of(), nameReference("b"))).build(), new NullIfExpression(nameReference("b"), number(1)), new IfExpression(nameReference("b"), number(1), new NullLiteral()), new DereferenceExpression(nameReference("b"), identifier("x")), new InPredicate(nameReference("b"), new InListExpression(ImmutableList.of(new NullLiteral()))), new SearchedCaseExpression(ImmutableList.of(new WhenClause(new IsNotNullPredicate(nameReference("b")), new NullLiteral())), Optional.empty()), new SimpleCaseExpression(nameReference("b"), ImmutableList.of(new WhenClause(number(1), new NullLiteral())), Optional.empty()), new SubscriptExpression(new ArrayConstructor(ImmutableList.of(new NullLiteral())), nameReference("b")));
for (Expression candidate : candidates) {
EqualityInference.Builder builder = new EqualityInference.Builder();
builder.extractInferenceCandidates(equals(nameReference("b"), nameReference("x")));
builder.extractInferenceCandidates(equals(nameReference("a"), candidate));
EqualityInference inference = builder.build();
List<Expression> equalities = inference.generateEqualitiesPartitionedBy(matchesSymbols("b")).getScopeStraddlingEqualities();
assertEquals(equalities.size(), 1);
assertTrue(equalities.get(0).equals(equals(nameReference("x"), nameReference("b"))) || equalities.get(0).equals(equals(nameReference("b"), nameReference("x"))));
}
}
use of io.prestosql.sql.tree.InPredicate in project hetu-core by openlookeng.
the class HeuristicIndexUtils method extractPartitions.
/**
* Given one of these expressions types:
* - partition=1
* - partition=1 or partition=2
* - partition in (1,2)
* - partition=1 or partition in (2)
*
* extract the partitions as a list of key=value pairs
* @param expression
* @return
*/
public static List<String> extractPartitions(Expression expression) {
if (expression instanceof ComparisonExpression) {
ComparisonExpression exp = (ComparisonExpression) expression;
if (exp.getOperator() == ComparisonExpression.Operator.EQUAL) {
return Collections.singletonList(parsePartitionName(exp.getLeft().toString()) + "=" + parsePartitionValue(exp.getRight().toString()));
}
} else if (expression instanceof LogicalBinaryExpression) {
LogicalBinaryExpression exp = (LogicalBinaryExpression) expression;
if (exp.getOperator() == LogicalBinaryExpression.Operator.OR) {
Expression left = exp.getLeft();
Expression right = exp.getRight();
return Stream.concat(extractPartitions(left).stream(), extractPartitions(right).stream()).collect(Collectors.toList());
}
} else if (expression instanceof InPredicate) {
Expression valueList = ((InPredicate) expression).getValueList();
if (valueList instanceof InListExpression) {
InListExpression inListExpression = (InListExpression) valueList;
List<String> res = new LinkedList<>();
for (Expression expr : inListExpression.getValues()) {
res.add(parsePartitionName(((InPredicate) expression).getValue().toString()) + "=" + parsePartitionValue(expr.toString()));
}
if (res.size() > 0) {
return res;
}
}
}
throw new ParsingException("Unsupported WHERE expression. Only in-predicate/equality-expressions are supported " + "e.g. partition=1 or partition=2/partition in (1,2)");
}
use of io.prestosql.sql.tree.InPredicate in project hetu-core by openlookeng.
the class RelationPlanner method visitJoin.
@Override
protected RelationPlan visitJoin(Join node, Void context) {
// TODO: translate the RIGHT join into a mirrored LEFT join when we refactor (@martint)
RelationPlan leftPlan = process(node.getLeft(), context);
Optional<Unnest> unnest = getUnnest(node.getRight());
if (unnest.isPresent()) {
if (node.getType() != Join.Type.CROSS && node.getType() != Join.Type.IMPLICIT) {
throw notSupportedException(unnest.get(), "UNNEST on other than the right side of CROSS JOIN");
}
return planCrossJoinUnnest(leftPlan, node, unnest.get());
}
Optional<Lateral> lateral = getLateral(node.getRight());
if (lateral.isPresent()) {
return planLateralJoin(node, leftPlan, lateral.get());
}
RelationPlan rightPlan = process(node.getRight(), context);
if (node.getCriteria().isPresent() && node.getCriteria().get() instanceof JoinUsing) {
return planJoinUsing(node, leftPlan, rightPlan);
}
PlanBuilder leftPlanBuilder = initializePlanBuilder(leftPlan);
PlanBuilder rightPlanBuilder = initializePlanBuilder(rightPlan);
// NOTE: symbols must be in the same order as the outputDescriptor
List<Symbol> outputSymbols = ImmutableList.<Symbol>builder().addAll(leftPlan.getFieldMappings()).addAll(rightPlan.getFieldMappings()).build();
ImmutableList.Builder<JoinNode.EquiJoinClause> equiClauses = ImmutableList.builder();
List<Expression> complexJoinExpressions = new ArrayList<>();
List<Expression> postInnerJoinConditions = new ArrayList<>();
if (node.getType() != Join.Type.CROSS && node.getType() != Join.Type.IMPLICIT) {
Expression criteria = analysis.getJoinCriteria(node);
RelationType left = analysis.getOutputDescriptor(node.getLeft());
RelationType right = analysis.getOutputDescriptor(node.getRight());
List<Expression> leftComparisonExpressions = new ArrayList<>();
List<Expression> rightComparisonExpressions = new ArrayList<>();
List<ComparisonExpression.Operator> joinConditionComparisonOperators = new ArrayList<>();
for (Expression conjunct : ExpressionUtils.extractConjuncts(criteria)) {
conjunct = ExpressionUtils.normalize(conjunct);
if (!isEqualComparisonExpression(conjunct) && node.getType() != INNER) {
complexJoinExpressions.add(conjunct);
continue;
}
Set<QualifiedName> dependencies = SymbolsExtractor.extractNames(conjunct, analysis.getColumnReferences());
if (dependencies.stream().allMatch(left::canResolve) || dependencies.stream().allMatch(right::canResolve)) {
// If the conjunct can be evaluated entirely with the inputs on either side of the join, add
// it to the list complex expressions and let the optimizers figure out how to push it down later.
complexJoinExpressions.add(conjunct);
} else if (conjunct instanceof ComparisonExpression) {
Expression firstExpression = ((ComparisonExpression) conjunct).getLeft();
Expression secondExpression = ((ComparisonExpression) conjunct).getRight();
ComparisonExpression.Operator comparisonOperator = ((ComparisonExpression) conjunct).getOperator();
Set<QualifiedName> firstDependencies = SymbolsExtractor.extractNames(firstExpression, analysis.getColumnReferences());
Set<QualifiedName> secondDependencies = SymbolsExtractor.extractNames(secondExpression, analysis.getColumnReferences());
if (firstDependencies.stream().allMatch(left::canResolve) && secondDependencies.stream().allMatch(right::canResolve)) {
leftComparisonExpressions.add(firstExpression);
rightComparisonExpressions.add(secondExpression);
joinConditionComparisonOperators.add(comparisonOperator);
} else if (firstDependencies.stream().allMatch(right::canResolve) && secondDependencies.stream().allMatch(left::canResolve)) {
leftComparisonExpressions.add(secondExpression);
rightComparisonExpressions.add(firstExpression);
joinConditionComparisonOperators.add(comparisonOperator.flip());
} else {
// the case when we mix symbols from both left and right join side on either side of condition.
complexJoinExpressions.add(conjunct);
}
} else {
complexJoinExpressions.add(conjunct);
}
}
leftPlanBuilder = subqueryPlanner.handleSubqueries(leftPlanBuilder, leftComparisonExpressions, node);
rightPlanBuilder = subqueryPlanner.handleSubqueries(rightPlanBuilder, rightComparisonExpressions, node);
// Add projections for join criteria
leftPlanBuilder = leftPlanBuilder.appendProjections(leftComparisonExpressions, planSymbolAllocator, idAllocator);
rightPlanBuilder = rightPlanBuilder.appendProjections(rightComparisonExpressions, planSymbolAllocator, idAllocator);
for (int i = 0; i < leftComparisonExpressions.size(); i++) {
if (joinConditionComparisonOperators.get(i) == ComparisonExpression.Operator.EQUAL) {
Symbol leftSymbol = leftPlanBuilder.translate(leftComparisonExpressions.get(i));
Symbol rightSymbol = rightPlanBuilder.translate(rightComparisonExpressions.get(i));
equiClauses.add(new JoinNode.EquiJoinClause(leftSymbol, rightSymbol));
} else {
Expression leftExpression = leftPlanBuilder.rewrite(leftComparisonExpressions.get(i));
Expression rightExpression = rightPlanBuilder.rewrite(rightComparisonExpressions.get(i));
postInnerJoinConditions.add(new ComparisonExpression(joinConditionComparisonOperators.get(i), leftExpression, rightExpression));
}
}
}
PlanNode root = new JoinNode(idAllocator.getNextId(), JoinNodeUtils.typeConvert(node.getType()), leftPlanBuilder.getRoot(), rightPlanBuilder.getRoot(), equiClauses.build(), ImmutableList.<Symbol>builder().addAll(leftPlanBuilder.getRoot().getOutputSymbols()).addAll(rightPlanBuilder.getRoot().getOutputSymbols()).build(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), ImmutableMap.of());
if (node.getType() != INNER) {
for (Expression complexExpression : complexJoinExpressions) {
Set<InPredicate> inPredicates = subqueryPlanner.collectInPredicateSubqueries(complexExpression, node);
if (!inPredicates.isEmpty()) {
InPredicate inPredicate = Iterables.getLast(inPredicates);
throw notSupportedException(inPredicate, "IN with subquery predicate in join condition");
}
}
// subqueries can be applied only to one side of join - left side is selected in arbitrary way
leftPlanBuilder = subqueryPlanner.handleUncorrelatedSubqueries(leftPlanBuilder, complexJoinExpressions, node);
}
RelationPlan intermediateRootRelationPlan = new RelationPlan(root, analysis.getScope(node), outputSymbols);
TranslationMap translationMap = new TranslationMap(intermediateRootRelationPlan, analysis, lambdaDeclarationToSymbolMap);
translationMap.setFieldMappings(outputSymbols);
translationMap.putExpressionMappingsFrom(leftPlanBuilder.getTranslations());
translationMap.putExpressionMappingsFrom(rightPlanBuilder.getTranslations());
if (node.getType() != INNER && !complexJoinExpressions.isEmpty()) {
Expression joinedFilterCondition = ExpressionUtils.and(complexJoinExpressions);
Expression rewrittenFilterCondition = translationMap.rewrite(joinedFilterCondition);
root = new JoinNode(idAllocator.getNextId(), JoinNodeUtils.typeConvert(node.getType()), leftPlanBuilder.getRoot(), rightPlanBuilder.getRoot(), equiClauses.build(), ImmutableList.<Symbol>builder().addAll(leftPlanBuilder.getRoot().getOutputSymbols()).addAll(rightPlanBuilder.getRoot().getOutputSymbols()).build(), Optional.of(castToRowExpression(rewrittenFilterCondition)), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), ImmutableMap.of());
}
if (node.getType() == INNER) {
// rewrite all the other conditions using output symbols from left + right plan node.
PlanBuilder rootPlanBuilder = new PlanBuilder(translationMap, root);
rootPlanBuilder = subqueryPlanner.handleSubqueries(rootPlanBuilder, complexJoinExpressions, node);
for (Expression expression : complexJoinExpressions) {
postInnerJoinConditions.add(rootPlanBuilder.rewrite(expression));
}
root = rootPlanBuilder.getRoot();
Expression postInnerJoinCriteria;
if (!postInnerJoinConditions.isEmpty()) {
postInnerJoinCriteria = ExpressionUtils.and(postInnerJoinConditions);
root = new FilterNode(idAllocator.getNextId(), root, castToRowExpression(postInnerJoinCriteria));
}
}
return new RelationPlan(root, analysis.getScope(node), outputSymbols);
}
use of io.prestosql.sql.tree.InPredicate in project hetu-core by openlookeng.
the class SubqueryPlanner method appendInPredicateApplyNode.
private PlanBuilder appendInPredicateApplyNode(PlanBuilder inputSubPlan, InPredicate inPredicate, boolean correlationAllowed, Node node) {
PlanBuilder subPlan = inputSubPlan;
if (subPlan.canTranslate(inPredicate)) {
// given subquery is already appended
return subPlan;
}
subPlan = handleSubqueries(subPlan, inPredicate.getValue(), node);
subPlan = subPlan.appendProjections(ImmutableList.of(inPredicate.getValue()), planSymbolAllocator, idAllocator);
checkState(inPredicate.getValueList() instanceof SubqueryExpression);
SubqueryExpression valueListSubquery = (SubqueryExpression) inPredicate.getValueList();
SubqueryExpression uncoercedValueListSubquery = uncoercedSubquery(valueListSubquery);
PlanBuilder subqueryPlan = createPlanBuilder(uncoercedValueListSubquery);
subqueryPlan = subqueryPlan.appendProjections(ImmutableList.of(valueListSubquery), planSymbolAllocator, idAllocator);
SymbolReference valueList = toSymbolReference(subqueryPlan.translate(valueListSubquery));
Symbol rewrittenValue = subPlan.translate(inPredicate.getValue());
InPredicate inPredicateSubqueryExpression = new InPredicate(toSymbolReference(rewrittenValue), valueList);
Symbol inPredicateSubquerySymbol = planSymbolAllocator.newSymbol(inPredicateSubqueryExpression, BOOLEAN);
subPlan.getTranslations().put(inPredicate, inPredicateSubquerySymbol);
return appendApplyNode(subPlan, inPredicate, subqueryPlan.getRoot(), Assignments.of(inPredicateSubquerySymbol, castToRowExpression(inPredicateSubqueryExpression)), correlationAllowed);
}
use of io.prestosql.sql.tree.InPredicate in project hetu-core by openlookeng.
the class ExpressionDomainTranslator method extractDisjuncts.
private List<Expression> extractDisjuncts(Type type, Ranges ranges, SymbolReference reference) {
List<Expression> disjuncts = new ArrayList<>();
List<Expression> singleValues = new ArrayList<>();
List<Range> orderedRanges = ranges.getOrderedRanges();
SortedRangeSet sortedRangeSet = SortedRangeSet.copyOf(type, orderedRanges);
SortedRangeSet complement = sortedRangeSet.complement();
List<Range> singleValueExclusionsList = complement.getOrderedRanges().stream().filter(Range::isSingleValue).collect(toList());
List<Range> originalUnionSingleValues = SortedRangeSet.copyOf(type, singleValueExclusionsList).union(sortedRangeSet).getOrderedRanges();
PeekingIterator<Range> singleValueExclusions = peekingIterator(singleValueExclusionsList.iterator());
for (Range range : originalUnionSingleValues) {
if (range.isSingleValue()) {
singleValues.add(literalEncoder.toExpression(range.getSingleValue(), type));
continue;
}
// attempt to optimize ranges that can be coalesced as long as single value points are excluded
List<Expression> singleValuesInRange = new ArrayList<>();
while (singleValueExclusions.hasNext() && range.contains(singleValueExclusions.peek())) {
singleValuesInRange.add(literalEncoder.toExpression(singleValueExclusions.next().getSingleValue(), type));
}
if (!singleValuesInRange.isEmpty()) {
disjuncts.add(combineRangeWithExcludedPoints(type, reference, range, singleValuesInRange));
continue;
}
disjuncts.add(processRange(type, range, reference));
}
// Add back all of the possible single values either as an equality or an IN predicate
if (singleValues.size() == 1) {
disjuncts.add(new ComparisonExpression(EQUAL, reference, getOnlyElement(singleValues)));
} else if (singleValues.size() > 1) {
disjuncts.add(new InPredicate(reference, new InListExpression(singleValues)));
}
return disjuncts;
}
Aggregations