-
Notifications
You must be signed in to change notification settings - Fork 5.5k
[WIP] Interface for RowExpression translation #13483
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,129 @@ | ||
| package com.facebook.presto.translator; | ||
|
|
||
| import com.facebook.presto.spi.relation.CallExpression; | ||
| import com.facebook.presto.spi.relation.ConstantExpression; | ||
| import com.facebook.presto.spi.relation.InputReferenceExpression; | ||
| import com.facebook.presto.spi.relation.LambdaDefinitionExpression; | ||
| import com.facebook.presto.spi.relation.SpecialFormExpression; | ||
| import com.facebook.presto.spi.relation.VariableReferenceExpression; | ||
| import com.facebook.presto.spi.translator.ExpressionTranslator; | ||
| import com.facebook.presto.spi.translator.TargetExpression; | ||
| import com.facebook.presto.translator.registry.ConstantTypeRegistry; | ||
| import com.facebook.presto.translator.registry.FunctionRegistry; | ||
|
|
||
| import java.util.Map; | ||
|
|
||
| public abstract class AbstractExpressionTranslator<T> | ||
| implements ExpressionTranslator | ||
| { | ||
| private final FunctionRegistry functionRegistry; | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should be protected/ have protected accessors. |
||
| private final ConstantTypeRegistry constantTypeRegistry; | ||
|
|
||
| public AbstractExpressionTranslator(FunctionRegistry functionRegistry, ConstantTypeRegistry constantTypeRegistry) | ||
| { | ||
| this.functionRegistry = functionRegistry; | ||
| this.constantTypeRegistry = constantTypeRegistry; | ||
| } | ||
|
|
||
| @Override | ||
| public TargetExpression<T> translateCallExpression(CallExpression callExpression, Map context) | ||
| { | ||
| return null; | ||
| } | ||
|
|
||
| @Override | ||
| public TargetExpression<T> translateInputReferenceExpression(InputReferenceExpression inputReferenceExpression, Map context) | ||
| { | ||
| return null; | ||
| } | ||
|
|
||
| @Override | ||
| public TargetExpression<T> translateConstantExpression(ConstantExpression constantExpression, Map context) | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Mocked functions, will implement once we get consensus on how this interface should look. |
||
| { | ||
| return null; | ||
| } | ||
|
|
||
| @Override | ||
| public TargetExpression<T> translateLambdaDefinitionExpression(LambdaDefinitionExpression lambdaDefinitionExpression, Map context) | ||
| { | ||
| return null; | ||
| } | ||
|
|
||
| @Override | ||
| public TargetExpression<T> translateVariableReferenceExpression(VariableReferenceExpression variableReferenceExpression, Map context) | ||
| { | ||
| return null; | ||
| } | ||
|
|
||
| @Override | ||
| public TargetExpression<T> translateIf(SpecialFormExpression specialFormExpression, Map context) | ||
| { | ||
| return null; | ||
| } | ||
|
|
||
| @Override | ||
| public TargetExpression<T> translateNullIf(SpecialFormExpression specialFormExpression, Map context) | ||
| { | ||
| return null; | ||
| } | ||
|
|
||
| @Override | ||
| public TargetExpression<T> translateSwitch(SpecialFormExpression specialFormExpression, Map context) | ||
| { | ||
| return null; | ||
| } | ||
|
|
||
| @Override | ||
| public TargetExpression<T> translateWhen(SpecialFormExpression specialFormExpression, Map context) | ||
| { | ||
| return null; | ||
| } | ||
|
|
||
| @Override | ||
| public TargetExpression<T> translateIsNull(SpecialFormExpression specialFormExpression, Map context) | ||
| { | ||
| return null; | ||
| } | ||
|
|
||
| @Override | ||
| public TargetExpression<T> translateCoalesce(SpecialFormExpression specialFormExpression, Map context) | ||
| { | ||
| return null; | ||
| } | ||
|
|
||
| @Override | ||
| public TargetExpression<T> translateIn(SpecialFormExpression specialFormExpression, Map context) | ||
| { | ||
| return null; | ||
| } | ||
|
|
||
| @Override | ||
| public TargetExpression<T> translateAnd(SpecialFormExpression specialFormExpression, Map context) | ||
| { | ||
| return null; | ||
| } | ||
|
|
||
| @Override | ||
| public TargetExpression<T> translateOr(SpecialFormExpression specialFormExpression, Map context) | ||
| { | ||
| return null; | ||
| } | ||
|
|
||
| @Override | ||
| public TargetExpression<T> translateDereference(SpecialFormExpression specialFormExpression, Map context) | ||
| { | ||
| return null; | ||
| } | ||
|
|
||
| @Override | ||
| public TargetExpression<T> translateRowConstructor(SpecialFormExpression specialFormExpression, Map context) | ||
| { | ||
| return null; | ||
| } | ||
|
|
||
| @Override | ||
| public TargetExpression<T> translateBind(SpecialFormExpression specialFormExpression, Map context) | ||
| { | ||
| return null; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| package com.facebook.presto.translator; | ||
|
|
||
| import com.facebook.presto.spi.ColumnHandle; | ||
| import com.facebook.presto.spi.function.FunctionMetadataManager; | ||
| import com.facebook.presto.spi.function.StandardFunctionResolution; | ||
| import com.facebook.presto.spi.relation.DeterminismEvaluator; | ||
| import com.facebook.presto.spi.relation.LogicalRowExpressions; | ||
| import com.facebook.presto.spi.relation.RowExpression; | ||
| import com.facebook.presto.spi.relation.VariableReferenceExpression; | ||
| import com.facebook.presto.spi.translator.ExpressionTranslator; | ||
| import com.facebook.presto.spi.translator.TargetExpression; | ||
|
|
||
| import java.util.Map; | ||
|
|
||
| public class RowExpressionTranslator<T> | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. User uses this class in their ComputePushdown class (see JdbcComputePushdown.java) and calls .translate on it. |
||
| { | ||
| private final RowExpressionTranslatorVisitor<T> visitor; | ||
| private final LogicalRowExpressions logicalRowExpressions; | ||
|
|
||
| public RowExpressionTranslator( | ||
| ExpressionTranslator<T> expressionTranslator, FunctionMetadataManager functionMetadataManager, StandardFunctionResolution functionResolution, DeterminismEvaluator determinismEvaluator) | ||
| { | ||
| this.visitor = new RowExpressionTranslatorVisitor<>(expressionTranslator); | ||
| this.logicalRowExpressions = new LogicalRowExpressions(determinismEvaluator, functionResolution, functionMetadataManager); | ||
| } | ||
|
|
||
| public TargetExpression translate( | ||
| RowExpression expression, | ||
| Map<VariableReferenceExpression, ColumnHandle> assignments) | ||
| { | ||
| return logicalRowExpressions.convertToConjunctiveNormalForm(expression).accept(visitor, assignments); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,90 @@ | ||
| package com.facebook.presto.translator; | ||
|
|
||
| import com.facebook.presto.spi.ColumnHandle; | ||
| import com.facebook.presto.spi.relation.CallExpression; | ||
| import com.facebook.presto.spi.relation.ConstantExpression; | ||
| import com.facebook.presto.spi.relation.InputReferenceExpression; | ||
| import com.facebook.presto.spi.relation.LambdaDefinitionExpression; | ||
| import com.facebook.presto.spi.relation.RowExpressionVisitor; | ||
| import com.facebook.presto.spi.relation.SpecialFormExpression; | ||
| import com.facebook.presto.spi.relation.VariableReferenceExpression; | ||
| import com.facebook.presto.spi.translator.ExpressionTranslator; | ||
| import com.facebook.presto.spi.translator.TargetExpression; | ||
|
|
||
| import java.util.Map; | ||
|
|
||
| import static java.util.Objects.requireNonNull; | ||
|
|
||
| class RowExpressionTranslatorVisitor<T> | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Underlying adapter for RowExpression visitor. This calls functions on the ExpressionTranslator interface. This class allows to hide internals from the user (i.e. they don't have to care about the visitor, only have to implement functions that are pertinent to their use case) |
||
| implements RowExpressionVisitor<TargetExpression<T>, Map<VariableReferenceExpression, ColumnHandle>> | ||
| { | ||
| private final ExpressionTranslator<T> expressionTranslator; | ||
|
|
||
| public RowExpressionTranslatorVisitor(ExpressionTranslator<T> expressionTranslator) | ||
| { | ||
| this.expressionTranslator = requireNonNull(expressionTranslator); | ||
| } | ||
|
|
||
| @Override | ||
| public TargetExpression<T> visitCall(CallExpression call, Map<VariableReferenceExpression, ColumnHandle> context) | ||
| { | ||
| return expressionTranslator.translateCallExpression(call, context); | ||
| } | ||
|
|
||
| @Override | ||
| public TargetExpression<T> visitInputReference(InputReferenceExpression reference, Map<VariableReferenceExpression, ColumnHandle> context) | ||
| { | ||
| return expressionTranslator.translateInputReferenceExpression(reference, context); | ||
| } | ||
|
|
||
| @Override | ||
| public TargetExpression<T> visitConstant(ConstantExpression literal, Map<VariableReferenceExpression, ColumnHandle> context) | ||
| { | ||
| return expressionTranslator.translateConstantExpression(literal, context); | ||
| } | ||
|
|
||
| @Override | ||
| public TargetExpression<T> visitLambda(LambdaDefinitionExpression lambda, Map<VariableReferenceExpression, ColumnHandle> context) | ||
| { | ||
| return expressionTranslator.translateLambdaDefinitionExpression(lambda, context); | ||
| } | ||
|
|
||
| @Override | ||
| public TargetExpression<T> visitVariableReference(VariableReferenceExpression reference, Map<VariableReferenceExpression, ColumnHandle> context) | ||
| { | ||
| return expressionTranslator.translateVariableReferenceExpression(reference, context); | ||
| } | ||
|
|
||
| @Override | ||
| public TargetExpression<T> visitSpecialForm(SpecialFormExpression specialForm, Map<VariableReferenceExpression, ColumnHandle> context) | ||
| { | ||
| switch (specialForm.getForm()) { | ||
| case IF: | ||
| return expressionTranslator.translateIf(specialForm, context); | ||
| case NULL_IF: | ||
| return expressionTranslator.translateNullIf(specialForm, context); | ||
| case SWITCH: | ||
| return expressionTranslator.translateSwitch(specialForm, context); | ||
| case WHEN: | ||
| return expressionTranslator.translateWhen(specialForm, context); | ||
| case IS_NULL: | ||
| return expressionTranslator.translateIsNull(specialForm, context); | ||
| case COALESCE: | ||
| return expressionTranslator.translateCoalesce(specialForm, context); | ||
| case IN: | ||
| return expressionTranslator.translateIn(specialForm, context); | ||
| case AND: | ||
| return expressionTranslator.translateAnd(specialForm, context); | ||
| case OR: | ||
| return expressionTranslator.translateOr(specialForm, context); | ||
| case DEREFERENCE: | ||
| return expressionTranslator.translateDereference(specialForm, context); | ||
| case ROW_CONSTRUCTOR: | ||
| return expressionTranslator.translateRowConstructor(specialForm, context); | ||
| case BIND: | ||
| return expressionTranslator.translateBind(specialForm, context); | ||
| default: | ||
| throw new IllegalStateException("Unexpected value: " + specialForm.getForm()); | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| package com.facebook.presto.translator.registry; | ||
|
|
||
| import com.facebook.presto.spi.type.Type; | ||
| import com.facebook.presto.spi.type.TypeSignature; | ||
| import com.google.common.collect.ImmutableSet; | ||
|
|
||
| import java.util.Arrays; | ||
| import java.util.Set; | ||
|
|
||
| import static com.facebook.presto.translator.registry.ScalarFromAnnotationsParser.removeTypeParameters; | ||
|
|
||
| public class ConstantTypeRegistry | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For registering constant types. May consider combining Constant and Function registries. Lmk if a better way to do this. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We may not need this. |
||
| { | ||
| private final Set<TypeSignature> constantTypes; | ||
|
|
||
| public ConstantTypeRegistry(Type... types) | ||
| { | ||
| ImmutableSet.Builder<TypeSignature> constantTypes = ImmutableSet.builder(); | ||
| Arrays.stream(types).forEach(type -> { | ||
| constantTypes.add(removeTypeParameters(type.getTypeSignature())); | ||
| }); | ||
| this.constantTypes = constantTypes.build(); | ||
| } | ||
|
|
||
| public Set<TypeSignature> getConstantTypes() | ||
| { | ||
| return constantTypes; | ||
| } | ||
|
|
||
| public boolean constantTypesContains(TypeSignature typeSignature) | ||
| { | ||
| return constantTypes.contains(typeSignature); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| package com.facebook.presto.translator.registry; | ||
|
|
||
| import com.facebook.presto.spi.function.FunctionMetadata; | ||
| import com.google.common.collect.ImmutableMap; | ||
|
|
||
| import java.lang.invoke.MethodHandle; | ||
| import java.util.Arrays; | ||
|
|
||
| import static com.facebook.presto.translator.registry.ScalarFromAnnotationsParser.parseFunctionDefinitions; | ||
|
|
||
| public class FunctionRegistry | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Check my example code |
||
| { | ||
| private final ImmutableMap<FunctionMetadata, MethodHandle> translators; | ||
|
|
||
| public FunctionRegistry(Class<?>... classes) | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For registering MethodHandles to their corresponding function metadata so that they can be invoked via reflection.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. AbstractExpressionTranslator will use this class and ConstantTypeRegistry for it's default implementations of translate functions. |
||
| { | ||
| ImmutableMap.Builder<FunctionMetadata, MethodHandle> functions = ImmutableMap.builder(); | ||
| Arrays.stream(classes).forEach(functionDefinition -> { | ||
| functions.putAll(parseFunctionDefinitions(functionDefinition)); | ||
| }); | ||
|
|
||
| this.translators = functions.build(); | ||
| } | ||
|
|
||
| public ImmutableMap<FunctionMetadata, MethodHandle> getTranslators() | ||
| { | ||
| return translators; | ||
| } | ||
|
|
||
| public MethodHandle getTranslatorForFunction(FunctionMetadata function) | ||
| { | ||
| return translators.get(function); | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
User will extend this class when writing their translator. It will be populated with default implementations.