Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,9 @@ private Expression simplifyExpression(Session session, Expression predicate, Typ
// TODO reuse io.trino.sql.planner.iterative.rule.SimplifyExpressions.rewrite

Map<NodeRef<Expression>, Type> expressionTypes = getExpressionTypes(plannerContext, session, predicate, types);
ExpressionInterpreter interpreter = new ExpressionInterpreter(predicate, plannerContext, session, expressionTypes);
Object value = interpreter.optimize(NoOpSymbolResolver.INSTANCE);
// TODO - Use the same instance of ExpressionInterpreter create per planning once StatsRule has context
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

create a github issue for this and reference it here and other TODOs

ExpressionInterpreter interpreter = new ExpressionInterpreter(plannerContext, session);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should an instance get reused here?

Object value = interpreter.optimize(predicate, expressionTypes, NoOpSymbolResolver.INSTANCE);

if (value == null) {
// Expression evaluates to SQL null, which in Filter is equivalent to false. This assumes the expression is a top-level expression (eg. not in NOT).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,9 @@ protected SymbolStatsEstimate visitLiteral(Literal node, Void context)
protected SymbolStatsEstimate visitFunctionCall(FunctionCall node, Void context)
{
Map<NodeRef<Expression>, Type> expressionTypes = getExpressionTypes(plannerContext, session, node, types);
ExpressionInterpreter interpreter = new ExpressionInterpreter(node, plannerContext, session, expressionTypes);
Object value = interpreter.optimize(NoOpSymbolResolver.INSTANCE);
// TODO - Use the same instance of ExpressionInterpreter create per planning once StatsRule has context
ExpressionInterpreter interpreter = new ExpressionInterpreter(plannerContext, session);
Object value = interpreter.optimize(node, expressionTypes, NoOpSymbolResolver.INSTANCE);

if (value == null || value instanceof NullLiteral) {
return nullStatsEstimate();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -304,8 +304,8 @@ public static boolean isEffectivelyLiteral(PlannerContext plannerContext, Sessio
private static boolean constantExpressionEvaluatesSuccessfully(PlannerContext plannerContext, Session session, Expression constantExpression)
{
Map<NodeRef<Expression>, Type> types = getExpressionTypes(plannerContext, session, constantExpression, TypeProvider.empty());
ExpressionInterpreter interpreter = new ExpressionInterpreter(constantExpression, plannerContext, session, types);
Object literalValue = interpreter.optimize(NoOpSymbolResolver.INSTANCE);
ExpressionInterpreter interpreter = new ExpressionInterpreter(plannerContext, session);
Object literalValue = interpreter.optimize(constantExpression, types, NoOpSymbolResolver.INSTANCE);
return !(literalValue instanceof Expression);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2094,9 +2094,9 @@ protected Scope visitSampledRelation(SampledRelation relation, Optional<Scope> s
throw semanticException(TYPE_MISMATCH, samplePercentage, "Sample percentage should be a numeric expression");
}

ExpressionInterpreter samplePercentageEval = new ExpressionInterpreter(samplePercentage, plannerContext, session, expressionTypes);
ExpressionInterpreter samplePercentageEval = new ExpressionInterpreter(plannerContext, session);

Object samplePercentageObject = samplePercentageEval.optimize(symbol -> {
Object samplePercentageObject = samplePercentageEval.optimize(samplePercentage, expressionTypes, symbol -> {
throw semanticException(EXPRESSION_NOT_CONSTANT, samplePercentage, "Sample percentage cannot contain column references");
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,12 @@ private static boolean isBetween(Range range)
* 2) An Expression fragment which represents the part of the original Expression that will need to be re-evaluated
* after filtering with the TupleDomain.
*/
public static ExtractionResult getExtractionResult(PlannerContext plannerContext, Session session, Expression predicate, TypeProvider types)
public static ExtractionResult getExtractionResult(
PlannerContext plannerContext,
Session session,
Expression predicate,
TypeProvider types,
ExpressionInterpreter expressionInterpreter)
{
// This is a limited type analyzer for the simple expressions used in this method
TypeAnalyzer typeAnalyzer = new TypeAnalyzer(
Expand All @@ -316,7 +321,7 @@ public static ExtractionResult getExtractionResult(PlannerContext plannerContext
new TablePropertyManager(),
new AnalyzePropertyManager(),
new TableProceduresPropertyManager()));
return new Visitor(plannerContext, session, types, typeAnalyzer).process(predicate, false);
return new Visitor(plannerContext, session, types, typeAnalyzer, expressionInterpreter).process(predicate, false);
}

private static class Visitor
Expand All @@ -326,16 +331,23 @@ private static class Visitor
private final LiteralEncoder literalEncoder;
private final Session session;
private final TypeProvider types;
private final ExpressionInterpreter expressionInterpreter;
private final InterpretedFunctionInvoker functionInvoker;
private final TypeAnalyzer typeAnalyzer;
private final TypeCoercion typeCoercion;

private Visitor(PlannerContext plannerContext, Session session, TypeProvider types, TypeAnalyzer typeAnalyzer)
private Visitor(
PlannerContext plannerContext,
Session session,
TypeProvider types,
TypeAnalyzer typeAnalyzer,
ExpressionInterpreter expressionInterpreter)
{
this.plannerContext = requireNonNull(plannerContext, "plannerContext is null");
this.literalEncoder = new LiteralEncoder(plannerContext);
this.session = requireNonNull(session, "session is null");
this.types = requireNonNull(types, "types is null");
this.expressionInterpreter = requireNonNull(expressionInterpreter, "expressionInterpreter is null");
this.functionInvoker = new InterpretedFunctionInvoker(plannerContext.getFunctionManager());
this.typeAnalyzer = requireNonNull(typeAnalyzer, "typeAnalyzer is null");
this.typeCoercion = new TypeCoercion(plannerContext.getTypeManager()::getType);
Expand Down Expand Up @@ -539,8 +551,8 @@ protected ExtractionResult visitComparisonExpression(ComparisonExpression node,
private Optional<NormalizedSimpleComparison> toNormalizedSimpleComparison(ComparisonExpression comparison)
{
Map<NodeRef<Expression>, Type> expressionTypes = analyzeExpression(comparison);
Object left = new ExpressionInterpreter(comparison.getLeft(), plannerContext, session, expressionTypes).optimize(NoOpSymbolResolver.INSTANCE);
Object right = new ExpressionInterpreter(comparison.getRight(), plannerContext, session, expressionTypes).optimize(NoOpSymbolResolver.INSTANCE);
Object left = expressionInterpreter.optimize(comparison.getLeft(), expressionTypes, NoOpSymbolResolver.INSTANCE);
Object right = expressionInterpreter.optimize(comparison.getRight(), expressionTypes, NoOpSymbolResolver.INSTANCE);

Type leftType = expressionTypes.get(NodeRef.of(comparison.getLeft()));
Type rightType = expressionTypes.get(NodeRef.of(comparison.getRight()));
Expand Down Expand Up @@ -908,8 +920,7 @@ private Optional<ExtractionResult> processSimpleInPredicate(InPredicate node, Bo
List<Expression> excludedExpressions = new ArrayList<>();

for (Expression expression : valueList.getValues()) {
Object value = new ExpressionInterpreter(expression, plannerContext, session, expressionTypes)
.optimize(NoOpSymbolResolver.INSTANCE);
Object value = expressionInterpreter.optimize(expression, expressionTypes, NoOpSymbolResolver.INSTANCE);
if (value == null || value instanceof NullLiteral) {
if (!complement) {
// in case of IN, NULL on the right results with NULL comparison result (effectively false in predicate context), so can be ignored, as the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,29 +109,45 @@ public EffectivePredicateExtractor(DomainTranslator domainTranslator, PlannerCon
this.useTableProperties = useTableProperties;
}

public Expression extract(Session session, PlanNode node, TypeProvider types, TypeAnalyzer typeAnalyzer)
public Expression extract(Session session, PlanNode node, TypeProvider types, TypeAnalyzer typeAnalyzer, ExpressionInterpreter expressionInterpreter)
{
return node.accept(new Visitor(domainTranslator, plannerContext, session, types, typeAnalyzer, useTableProperties), null);
return node.accept(
new Visitor(
domainTranslator,
plannerContext.getMetadata(),
session,
types,
expressionInterpreter,
typeAnalyzer,
useTableProperties),
null);
}

private static class Visitor
extends PlanVisitor<Expression, Void>
{
private final DomainTranslator domainTranslator;
private final PlannerContext plannerContext;
private final Metadata metadata;
private final Session session;
private final TypeProvider types;
private final ExpressionInterpreter expressionInterpreter;
private final TypeAnalyzer typeAnalyzer;
private final boolean useTableProperties;

public Visitor(DomainTranslator domainTranslator, PlannerContext plannerContext, Session session, TypeProvider types, TypeAnalyzer typeAnalyzer, boolean useTableProperties)
public Visitor(
DomainTranslator domainTranslator,
Metadata metadata,
Session session,
TypeProvider types,
ExpressionInterpreter expressionInterpreter,
TypeAnalyzer typeAnalyzer,
boolean useTableProperties)
{
this.domainTranslator = requireNonNull(domainTranslator, "domainTranslator is null");
this.plannerContext = requireNonNull(plannerContext, "plannerContext is null");
this.metadata = plannerContext.getMetadata();
this.metadata = requireNonNull(metadata, "metadata is null");
this.session = requireNonNull(session, "session is null");
this.types = requireNonNull(types, "types is null");
this.expressionInterpreter = requireNonNull(expressionInterpreter, "expressionInterpreter is null");
this.typeAnalyzer = requireNonNull(typeAnalyzer, "typeAnalyzer is null");
this.useTableProperties = useTableProperties;
}
Expand Down Expand Up @@ -386,8 +402,7 @@ public Expression visitValues(ValuesNode node, Void context)
nonDeterministic[i] = true;
}
else {
ExpressionInterpreter interpreter = new ExpressionInterpreter(value, plannerContext, session, expressionTypes);
Object item = interpreter.optimize(NoOpSymbolResolver.INSTANCE);
Object item = expressionInterpreter.optimize(value, expressionTypes, NoOpSymbolResolver.INSTANCE);
if (item instanceof Expression) {
return TRUE_LITERAL;
}
Expand All @@ -413,8 +428,7 @@ public Expression visitValues(ValuesNode node, Void context)
if (!DeterminismEvaluator.isDeterministic(row, metadata)) {
return TRUE_LITERAL;
}
ExpressionInterpreter interpreter = new ExpressionInterpreter(row, plannerContext, session, expressionTypes);
Object evaluated = interpreter.optimize(NoOpSymbolResolver.INSTANCE);
Object evaluated = expressionInterpreter.optimize(row, expressionTypes, NoOpSymbolResolver.INSTANCE);
if (evaluated instanceof Expression) {
return TRUE_LITERAL;
}
Expand Down
Loading