Object optimizedExpression = ExpressionInterpreter.expressionOptimizer(expression, metadata, session).optimize(NoOpSymbolResolver.INSTANCE);
if (!(optimizedExpression instanceof Expression) && optimizedExpression instanceof Boolean) {
// If the JoinOn clause evaluates to a boolean expression, simulate a cross join by adding the relevant redundant expression
if (optimizedExpression.equals(Boolean.TRUE)) {
optimizedExpression = new ComparisonExpression(ComparisonExpression.Type.EQUAL, new LongLiteral("0"), new LongLiteral("0"));
}
else {
optimizedExpression = new ComparisonExpression(ComparisonExpression.Type.EQUAL, new LongLiteral("0"), new LongLiteral("1"));
}
}
if (!(optimizedExpression instanceof Expression)) {
throw new SemanticException(TYPE_MISMATCH, node, "Join clause must be a boolean expression");
}
ImmutableList.Builder<EquiJoinClause> clauses = ImmutableList.builder();
for (Expression conjunct : ExpressionUtils.extractConjuncts((Expression) optimizedExpression)) {
if (!(conjunct instanceof ComparisonExpression)) {
throw new SemanticException(NOT_SUPPORTED, node, "Non-equi joins not supported: %s", conjunct);
}
ComparisonExpression comparison = (ComparisonExpression) conjunct;
if (comparison.getType() != ComparisonExpression.Type.EQUAL) {
throw new SemanticException(NOT_SUPPORTED, node, "Non-equi joins not supported: %s", conjunct);
}
Set<QualifiedName> firstDependencies = DependencyExtractor.extract(comparison.getLeft());
Set<QualifiedName> secondDependencies = DependencyExtractor.extract(comparison.getRight());
Expression leftExpression;
Expression rightExpression;
if (Iterables.all(firstDependencies, left.canResolvePredicate()) && Iterables.all(secondDependencies, right.canResolvePredicate())) {
leftExpression = comparison.getLeft();
rightExpression = comparison.getRight();
}
else if (Iterables.all(firstDependencies, right.canResolvePredicate()) && Iterables.all(secondDependencies, left.canResolvePredicate())) {
leftExpression = comparison.getRight();
rightExpression = comparison.getLeft();
}
else {
// must have a complex expression that involves both tuples on one side of the comparison expression (e.g., coalesce(left.x, right.x) = 1)
throw new SemanticException(NOT_SUPPORTED, node, "Non-equi joins not supported: %s", conjunct);
}