private Expression simplifyExpression(Expression input) { IdentityHashMap<Expression, Type> expressionTypes = getExpressionTypes(session, metadata, sqlParser, types, input); ExpressionInterpreter interpreter = ExpressionInterpreter.expressionOptimizer(input, metadata, session, expressionTypes); return LiteralInterpreter.toExpression( interpreter.optimize(NoOpSymbolResolver.INSTANCE), expressionTypes.get(input)); }
/** Evaluates an expression's response to binding the specified input symbols to NULL */ private Object nullInputEvaluator(final Collection<Symbol> nullSymbols, Expression expression) { return ExpressionInterpreter.expressionOptimizer(expression, metadata, session) .optimize( new SymbolResolver() { @Override public Object getValue(Symbol symbol) { return nullSymbols.contains(symbol) ? null : new QualifiedNameReference(symbol.toQualifiedName()); } }); }
@Override public ActualProperties visitProject(ProjectNode node, List<ActualProperties> inputProperties) { ActualProperties properties = Iterables.getOnlyElement(inputProperties); Map<Symbol, Symbol> identities = computeIdentityTranslations(node.getAssignments()); ActualProperties translatedProperties = properties.translate(column -> Optional.ofNullable(identities.get(column))); // Extract additional constants Map<Symbol, NullableValue> constants = new HashMap<>(); for (Map.Entry<Symbol, Expression> assignment : node.getAssignments().entrySet()) { Expression expression = assignment.getValue(); IdentityHashMap<Expression, Type> expressionTypes = getExpressionTypes( session, metadata, parser, types, expression, emptyList() /* parameters already replaced */); Type type = requireNonNull(expressionTypes.get(expression)); ExpressionInterpreter optimizer = ExpressionInterpreter.expressionOptimizer( expression, metadata, session, expressionTypes); // TODO: // We want to use a symbol resolver that looks up in the constants from the input subplan // to take advantage of constant-folding for complex expressions // However, that currently causes errors when those expressions operate on arrays or row // types // ("ROW comparison not supported for fields with null elements", etc) Object value = optimizer.optimize(NoOpSymbolResolver.INSTANCE); if (value instanceof SymbolReference) { Symbol symbol = Symbol.from((SymbolReference) value); NullableValue existingConstantValue = constants.get(symbol); if (existingConstantValue != null) { constants.put(assignment.getKey(), new NullableValue(type, value)); } } else if (!(value instanceof Expression)) { constants.put(assignment.getKey(), new NullableValue(type, value)); } } constants.putAll(translatedProperties.getConstants()); return ActualProperties.builderFrom(translatedProperties).constants(constants).build(); }