use of com.facebook.presto.spi.relation.LambdaDefinitionExpression in project presto by prestodb.
the class CursorProcessorCompiler method generateMethods.
@Override
public void generateMethods(SqlFunctionProperties sqlFunctionProperties, ClassDefinition classDefinition, CallSiteBinder callSiteBinder, RowExpression filter, List<RowExpression> projections) {
CachedInstanceBinder cachedInstanceBinder = new CachedInstanceBinder(classDefinition, callSiteBinder);
List<RowExpression> rowExpressions = ImmutableList.<RowExpression>builder().addAll(projections).add(filter).build();
Map<LambdaDefinitionExpression, CompiledLambda> compiledLambdaMap = generateMethodsForLambda(classDefinition, callSiteBinder, cachedInstanceBinder, rowExpressions, metadata, sqlFunctionProperties, sessionFunctions, "");
Map<VariableReferenceExpression, CommonSubExpressionFields> cseFields = ImmutableMap.of();
RowExpressionCompiler compiler = new RowExpressionCompiler(classDefinition, callSiteBinder, cachedInstanceBinder, fieldReferenceCompiler(cseFields), metadata, sqlFunctionProperties, sessionFunctions, compiledLambdaMap);
if (isOptimizeCommonSubExpressions) {
Map<Integer, Map<RowExpression, VariableReferenceExpression>> commonSubExpressionsByLevel = collectCSEByLevel(rowExpressions);
if (!commonSubExpressionsByLevel.isEmpty()) {
cseFields = declareCommonSubExpressionFields(classDefinition, commonSubExpressionsByLevel);
compiler = new RowExpressionCompiler(classDefinition, callSiteBinder, cachedInstanceBinder, fieldReferenceCompiler(cseFields), metadata, sqlFunctionProperties, sessionFunctions, compiledLambdaMap);
generateCommonSubExpressionMethods(classDefinition, compiler, commonSubExpressionsByLevel, cseFields);
Map<RowExpression, VariableReferenceExpression> commonSubExpressions = commonSubExpressionsByLevel.values().stream().flatMap(m -> m.entrySet().stream()).collect(toImmutableMap(Map.Entry::getKey, Map.Entry::getValue));
projections = rewriteRowExpressionsWithCSE(projections, commonSubExpressions);
filter = rewriteRowExpressionsWithCSE(ImmutableList.of(filter), commonSubExpressions).get(0);
}
}
generateProcessMethod(classDefinition, projections.size(), cseFields);
generateFilterMethod(classDefinition, compiler, filter);
for (int i = 0; i < projections.size(); i++) {
String methodName = "project_" + i;
generateProjectMethod(classDefinition, compiler, methodName, projections.get(i));
}
MethodDefinition constructorDefinition = classDefinition.declareConstructor(a(PUBLIC));
BytecodeBlock constructorBody = constructorDefinition.getBody();
Variable thisVariable = constructorDefinition.getThis();
constructorBody.comment("super();").append(thisVariable).invokeConstructor(Object.class);
initializeCommonSubExpressionFields(cseFields.values(), thisVariable, constructorBody);
cachedInstanceBinder.generateInitializations(thisVariable, constructorBody);
constructorBody.ret();
}
use of com.facebook.presto.spi.relation.LambdaDefinitionExpression in project presto by prestodb.
the class PageFunctionCompiler method definePageProjectWorkClass.
private ClassDefinition definePageProjectWorkClass(SqlFunctionProperties sqlFunctionProperties, Map<SqlFunctionId, SqlInvokedFunction> sessionFunctions, List<RowExpression> projections, CallSiteBinder callSiteBinder, boolean isOptimizeCommonSubExpression, Optional<String> classNameSuffix) {
ClassDefinition classDefinition = new ClassDefinition(a(PUBLIC, FINAL), generateProjectionWorkClassName(classNameSuffix), type(Object.class), type(Work.class));
FieldDefinition blockBuilderFields = classDefinition.declareField(a(PRIVATE), "blockBuilders", type(List.class, BlockBuilder.class));
FieldDefinition propertiesField = classDefinition.declareField(a(PRIVATE), "properties", SqlFunctionProperties.class);
FieldDefinition pageField = classDefinition.declareField(a(PRIVATE), "page", Page.class);
FieldDefinition selectedPositionsField = classDefinition.declareField(a(PRIVATE), "selectedPositions", SelectedPositions.class);
FieldDefinition nextIndexOrPositionField = classDefinition.declareField(a(PRIVATE), "nextIndexOrPosition", int.class);
FieldDefinition resultField = classDefinition.declareField(a(PRIVATE), "result", List.class);
CachedInstanceBinder cachedInstanceBinder = new CachedInstanceBinder(classDefinition, callSiteBinder);
// process
generateProcessMethod(classDefinition, blockBuilderFields, projections.size(), propertiesField, pageField, selectedPositionsField, nextIndexOrPositionField, resultField);
// getResult
MethodDefinition method = classDefinition.declareMethod(a(PUBLIC), "getResult", type(Object.class), ImmutableList.of());
method.getBody().append(method.getThis().getField(resultField)).ret(Object.class);
Map<LambdaDefinitionExpression, CompiledLambda> compiledLambdaMap = generateMethodsForLambda(classDefinition, callSiteBinder, cachedInstanceBinder, projections, metadata, sqlFunctionProperties, sessionFunctions, "");
// cse
Map<VariableReferenceExpression, CommonSubExpressionFields> cseFields = ImmutableMap.of();
RowExpressionCompiler compiler = new RowExpressionCompiler(classDefinition, callSiteBinder, cachedInstanceBinder, new FieldAndVariableReferenceCompiler(callSiteBinder, cseFields), metadata, sqlFunctionProperties, sessionFunctions, compiledLambdaMap);
if (isOptimizeCommonSubExpression) {
Map<Integer, Map<RowExpression, VariableReferenceExpression>> commonSubExpressionsByLevel = collectCSEByLevel(projections);
if (!commonSubExpressionsByLevel.isEmpty()) {
cseFields = declareCommonSubExpressionFields(classDefinition, commonSubExpressionsByLevel);
compiler = new RowExpressionCompiler(classDefinition, callSiteBinder, cachedInstanceBinder, new FieldAndVariableReferenceCompiler(callSiteBinder, cseFields), metadata, sqlFunctionProperties, sessionFunctions, compiledLambdaMap);
generateCommonSubExpressionMethods(classDefinition, compiler, commonSubExpressionsByLevel, cseFields);
Map<RowExpression, VariableReferenceExpression> commonSubExpressions = commonSubExpressionsByLevel.values().stream().flatMap(m -> m.entrySet().stream()).collect(toImmutableMap(Map.Entry::getKey, Map.Entry::getValue));
projections = projections.stream().map(projection -> rewriteExpressionWithCSE(projection, commonSubExpressions)).collect(toImmutableList());
if (log.isDebugEnabled()) {
log.debug("Extracted %d common sub-expressions", commonSubExpressions.size());
commonSubExpressions.entrySet().forEach(entry -> log.debug("\t%s = %s", entry.getValue(), entry.getKey()));
log.debug("Rewrote %d projections: %s", projections.size(), Joiner.on(", ").join(projections));
}
}
}
// evaluate
generateEvaluateMethod(classDefinition, compiler, projections, blockBuilderFields, cseFields);
// constructor
Parameter blockBuilders = arg("blockBuilders", type(List.class, BlockBuilder.class));
Parameter properties = arg("properties", SqlFunctionProperties.class);
Parameter page = arg("page", Page.class);
Parameter selectedPositions = arg("selectedPositions", SelectedPositions.class);
MethodDefinition constructorDefinition = classDefinition.declareConstructor(a(PUBLIC), blockBuilders, properties, page, selectedPositions);
BytecodeBlock body = constructorDefinition.getBody();
Variable thisVariable = constructorDefinition.getThis();
body.comment("super();").append(thisVariable).invokeConstructor(Object.class).append(thisVariable.setField(blockBuilderFields, invokeStatic(ImmutableList.class, "copyOf", ImmutableList.class, blockBuilders.cast(Collection.class)))).append(thisVariable.setField(propertiesField, properties)).append(thisVariable.setField(pageField, page)).append(thisVariable.setField(selectedPositionsField, selectedPositions)).append(thisVariable.setField(nextIndexOrPositionField, selectedPositions.invoke("getOffset", int.class))).append(thisVariable.setField(resultField, constantNull(Block.class)));
initializeCommonSubExpressionFields(cseFields.values(), thisVariable, body);
cachedInstanceBinder.generateInitializations(thisVariable, body);
body.ret();
return classDefinition;
}
use of com.facebook.presto.spi.relation.LambdaDefinitionExpression in project presto by prestodb.
the class JoinFilterFunctionCompiler method generateMethods.
private void generateMethods(SqlFunctionProperties sqlFunctionProperties, Map<SqlFunctionId, SqlInvokedFunction> sessionFunctions, ClassDefinition classDefinition, CallSiteBinder callSiteBinder, RowExpression filter, int leftBlocksSize) {
CachedInstanceBinder cachedInstanceBinder = new CachedInstanceBinder(classDefinition, callSiteBinder);
FieldDefinition propertiesField = classDefinition.declareField(a(PRIVATE, FINAL), "properties", SqlFunctionProperties.class);
Map<LambdaDefinitionExpression, CompiledLambda> compiledLambdaMap = generateMethodsForLambda(classDefinition, callSiteBinder, cachedInstanceBinder, filter, metadata, sqlFunctionProperties, sessionFunctions);
generateFilterMethod(sqlFunctionProperties, sessionFunctions, classDefinition, callSiteBinder, cachedInstanceBinder, compiledLambdaMap, filter, leftBlocksSize, propertiesField);
generateConstructor(classDefinition, propertiesField, cachedInstanceBinder);
}
use of com.facebook.presto.spi.relation.LambdaDefinitionExpression in project presto by prestodb.
the class BindCodeGenerator method generateExpression.
@Override
public BytecodeNode generateExpression(BytecodeGeneratorContext context, Type returnType, List<RowExpression> arguments, Optional<Variable> outputBlockVariable) {
// Bind expression is used to generate captured lambda.
// It takes the captured values and the uncaptured lambda, and produces captured lambda as the output.
// The uncaptured lambda is just a method, and does not have a stack representation during execution.
// As a result, the bind expression generates the captured lambda in one step.
// outputBlockVariable cannot present because
// 1. bind cannot be in the top level of an expression
// 2. lambda cannot be put into blocks.
checkArgument(!outputBlockVariable.isPresent());
int numCaptures = arguments.size() - 1;
LambdaDefinitionExpression lambda = (LambdaDefinitionExpression) arguments.get(numCaptures);
checkState(compiledLambdaMap.containsKey(lambda), "lambda expressions map does not contain this lambda definition");
CompiledLambda compiledLambda = compiledLambdaMap.get(lambda);
return LambdaBytecodeGenerator.generateLambda(context, arguments.subList(0, numCaptures), compiledLambda, lambdaInterface);
}
use of com.facebook.presto.spi.relation.LambdaDefinitionExpression in project presto by prestodb.
the class RewriteAggregationIfToFilter method canUnwrapIf.
private boolean canUnwrapIf(SpecialFormExpression ifExpression, AggregationIfToFilterRewriteStrategy rewriteStrategy) {
if (rewriteStrategy == FILTER_WITH_IF) {
return false;
}
// Some use cases use IF expression to avoid returning errors when evaluating the true branch. For example, IF(CARDINALITY(array) > 0, array[1])).
// We shouldn't unwrap the IF for those cases.
// But if the condition expression doesn't reference any variables referenced in the true branch, unwrapping the if should not cause exceptions for the true branch.
Set<VariableReferenceExpression> ifConditionReferences = VariablesExtractor.extractUnique(ifExpression.getArguments().get(0));
Set<VariableReferenceExpression> ifResultReferences = VariablesExtractor.extractUnique(ifExpression.getArguments().get(1));
if (ifConditionReferences.stream().noneMatch(ifResultReferences::contains)) {
return true;
}
if (rewriteStrategy != UNWRAP_IF) {
return false;
}
AtomicBoolean result = new AtomicBoolean(true);
ifExpression.getArguments().get(1).accept(new DefaultRowExpressionTraversalVisitor<AtomicBoolean>() {
@Override
public Void visitLambda(LambdaDefinitionExpression lambda, AtomicBoolean result) {
// Unwrapping the IF expression in the aggregate might cause issues if the true branch return errors for rows not matching the filters.
// To be safe, we don't unwrap the IF expressions when the true branch has lambdas.
result.set(false);
return null;
}
@Override
public Void visitCall(CallExpression call, AtomicBoolean result) {
Optional<OperatorType> operatorType = functionAndTypeManager.getFunctionMetadata(call.getFunctionHandle()).getOperatorType();
// For example, array[1] could return out of bound error and a / b could return DIVISION_BY_ZERO error. So we doesn't unwrap the IF expression in these cases.
if (operatorType.isPresent() && (operatorType.get() == OperatorType.DIVIDE || operatorType.get() == OperatorType.SUBSCRIPT)) {
result.set(false);
return null;
}
return super.visitCall(call, result);
}
}, result);
return result.get();
}
Aggregations