use of com.facebook.presto.sql.relational.RowExpression in project presto by prestodb.
the class PageProcessorCompiler method generateMethodsForLambdaAndTry.
private PreGeneratedExpressions generateMethodsForLambdaAndTry(ClassDefinition containerClassDefinition, CallSiteBinder callSiteBinder, CachedInstanceBinder cachedInstanceBinder, RowExpression projection, String methodPrefix) {
Set<RowExpression> lambdaAndTryExpressions = ImmutableSet.copyOf(extractLambdaAndTryExpressions(projection));
ImmutableMap.Builder<CallExpression, MethodDefinition> tryMethodMap = ImmutableMap.builder();
ImmutableMap.Builder<LambdaDefinitionExpression, FieldDefinition> lambdaFieldMap = ImmutableMap.builder();
int counter = 0;
for (RowExpression expression : lambdaAndTryExpressions) {
if (expression instanceof CallExpression) {
CallExpression tryExpression = (CallExpression) expression;
verify(!Signatures.TRY.equals(tryExpression.getSignature().getName()));
Parameter session = arg("session", ConnectorSession.class);
List<Parameter> blocks = toBlockParameters(getInputChannels(tryExpression.getArguments()));
Parameter position = arg("position", int.class);
BytecodeExpressionVisitor innerExpressionVisitor = new BytecodeExpressionVisitor(callSiteBinder, cachedInstanceBinder, fieldReferenceCompiler(callSiteBinder), metadata.getFunctionRegistry(), new PreGeneratedExpressions(tryMethodMap.build(), lambdaFieldMap.build()));
List<Parameter> inputParameters = ImmutableList.<Parameter>builder().add(session).addAll(blocks).add(position).build();
MethodDefinition tryMethod = defineTryMethod(innerExpressionVisitor, containerClassDefinition, methodPrefix + "_try_" + counter, inputParameters, Primitives.wrap(tryExpression.getType().getJavaType()), tryExpression, callSiteBinder);
tryMethodMap.put(tryExpression, tryMethod);
} else if (expression instanceof LambdaDefinitionExpression) {
LambdaDefinitionExpression lambdaExpression = (LambdaDefinitionExpression) expression;
PreGeneratedExpressions preGeneratedExpressions = new PreGeneratedExpressions(tryMethodMap.build(), lambdaFieldMap.build());
FieldDefinition methodHandleField = LambdaBytecodeGenerator.preGenerateLambdaExpression(lambdaExpression, methodPrefix + "_lambda_" + counter, containerClassDefinition, preGeneratedExpressions, callSiteBinder, cachedInstanceBinder, metadata.getFunctionRegistry());
lambdaFieldMap.put(lambdaExpression, methodHandleField);
} else {
throw new VerifyException(format("unexpected expression: %s", expression.toString()));
}
counter++;
}
return new PreGeneratedExpressions(tryMethodMap.build(), lambdaFieldMap.build());
}
use of com.facebook.presto.sql.relational.RowExpression in project presto by prestodb.
the class PageProcessorCompiler method generateProcessMethod.
private static void generateProcessMethod(ClassDefinition classDefinition, RowExpression filter, List<RowExpression> projections, List<MethodDefinition> projectionMethods) {
Parameter session = arg("session", ConnectorSession.class);
Parameter page = arg("page", Page.class);
Parameter start = arg("start", int.class);
Parameter end = arg("end", int.class);
Parameter pageBuilder = arg("pageBuilder", PageBuilder.class);
MethodDefinition method = classDefinition.declareMethod(a(PUBLIC), "process", type(int.class), session, page, start, end, pageBuilder);
Scope scope = method.getScope();
BytecodeBlock body = method.getBody();
Variable thisVariable = method.getThis();
// extract blocks
List<Integer> allInputChannels = getInputChannels(concat(projections, ImmutableList.of(filter)));
ImmutableMap.Builder<Integer, Variable> builder = ImmutableMap.builder();
for (int channel : allInputChannels) {
Variable blockVariable = scope.declareVariable("block_" + channel, body, page.invoke("getBlock", Block.class, constantInt(channel)));
builder.put(channel, blockVariable);
}
Map<Integer, Variable> channelBlocks = builder.build();
Map<RowExpression, List<Variable>> expressionInputBlocks = getExpressionInputBlocks(projections, filter, channelBlocks);
// projection body
Variable position = scope.declareVariable(int.class, "position");
BytecodeBlock project = new BytecodeBlock().append(pageBuilder.invoke("declarePosition", void.class));
for (int projectionIndex = 0; projectionIndex < projections.size(); projectionIndex++) {
RowExpression projection = projections.get(projectionIndex);
project.append(invokeProject(thisVariable, session, expressionInputBlocks.get(projection), position, pageBuilder, constantInt(projectionIndex), projectionMethods.get(projectionIndex)));
}
LabelNode done = new LabelNode("done");
// for loop loop body
ForLoop loop = new ForLoop().initialize(position.set(start)).condition(lessThan(position, end)).update(position.set(add(position, constantInt(1)))).body(new BytecodeBlock().append(new IfStatement().condition(pageBuilder.invoke("isFull", boolean.class)).ifTrue(jump(done))).append(new IfStatement().condition(invokeFilter(thisVariable, session, expressionInputBlocks.get(filter), position)).ifTrue(project)));
body.append(loop).visitLabel(done).append(position.ret());
}
use of com.facebook.presto.sql.relational.RowExpression in project presto by prestodb.
the class SwitchCodeGenerator method generateExpression.
@Override
public BytecodeNode generateExpression(Signature signature, BytecodeGeneratorContext generatorContext, Type returnType, List<RowExpression> arguments) {
// TODO: compile as
/*
hashCode = hashCode(<value>)
// all constant expressions before a non-constant
switch (hashCode) {
case ...:
if (<value> == <constant1>) {
...
}
else if (<value> == <constant2>) {
...
}
else if (...) {
}
case ...:
...
}
if (<value> == <non-constant1>) {
...
}
else if (<value> == <non-constant2>) {
...
}
...
// repeat with next sequence of constant expressions
*/
Scope scope = generatorContext.getScope();
// process value, else, and all when clauses
RowExpression value = arguments.get(0);
BytecodeNode valueBytecode = generatorContext.generate(value);
BytecodeNode elseValue;
List<RowExpression> whenClauses;
RowExpression last = arguments.get(arguments.size() - 1);
if (last instanceof CallExpression && ((CallExpression) last).getSignature().getName().equals("WHEN")) {
whenClauses = arguments.subList(1, arguments.size());
elseValue = new BytecodeBlock().append(generatorContext.wasNull().set(constantTrue())).pushJavaDefault(returnType.getJavaType());
} else {
whenClauses = arguments.subList(1, arguments.size() - 1);
elseValue = generatorContext.generate(last);
}
// determine the type of the value and result
Class<?> valueType = value.getType().getJavaType();
// evaluate the value and store it in a variable
LabelNode nullValue = new LabelNode("nullCondition");
Variable tempVariable = scope.createTempVariable(valueType);
BytecodeBlock block = new BytecodeBlock().append(valueBytecode).append(BytecodeUtils.ifWasNullClearPopAndGoto(scope, nullValue, void.class, valueType)).putVariable(tempVariable);
BytecodeNode getTempVariableNode = VariableInstruction.loadVariable(tempVariable);
// build the statements
elseValue = new BytecodeBlock().visitLabel(nullValue).append(elseValue);
// reverse list because current if statement builder doesn't support if/else so we need to build the if statements bottom up
for (RowExpression clause : Lists.reverse(whenClauses)) {
Preconditions.checkArgument(clause instanceof CallExpression && ((CallExpression) clause).getSignature().getName().equals("WHEN"));
RowExpression operand = ((CallExpression) clause).getArguments().get(0);
RowExpression result = ((CallExpression) clause).getArguments().get(1);
// call equals(value, operand)
Signature equalsFunction = generatorContext.getRegistry().resolveOperator(OperatorType.EQUAL, ImmutableList.of(value.getType(), operand.getType()));
// TODO: what if operand is null? It seems that the call will return "null" (which is cleared below)
// and the code only does the right thing because the value in the stack for that scenario is
// Java's default for boolean == false
// This code should probably be checking for wasNull after the call and "failing" the equality
// check if wasNull is true
BytecodeNode equalsCall = generatorContext.generateCall(equalsFunction.getName(), generatorContext.getRegistry().getScalarFunctionImplementation(equalsFunction), ImmutableList.of(generatorContext.generate(operand), getTempVariableNode));
BytecodeBlock condition = new BytecodeBlock().append(equalsCall).append(generatorContext.wasNull().set(constantFalse()));
elseValue = new IfStatement("when").condition(condition).ifTrue(generatorContext.generate(result)).ifFalse(elseValue);
}
return block.append(elseValue);
}
use of com.facebook.presto.sql.relational.RowExpression in project presto by prestodb.
the class PageProcessorCompiler method getExpressionInputBlocks.
private static Map<RowExpression, List<Variable>> getExpressionInputBlocks(List<RowExpression> projections, RowExpression filter, Map<Integer, Variable> channelBlock) {
Map<RowExpression, List<Variable>> inputBlocksBuilder = new HashMap<>();
for (RowExpression projection : projections) {
List<Variable> inputBlocks = getInputChannels(projection).stream().map(channelBlock::get).collect(toList());
List<Variable> existingVariables = inputBlocksBuilder.get(projection);
// Constant expressions or expressions that are reused, should reference the same input blocks
checkState(existingVariables == null || existingVariables.equals(inputBlocks), "malformed RowExpression");
inputBlocksBuilder.put(projection, inputBlocks);
}
List<Variable> filterBlocks = getInputChannels(filter).stream().map(channelBlock::get).collect(toList());
inputBlocksBuilder.put(filter, filterBlocks);
return inputBlocksBuilder;
}
use of com.facebook.presto.sql.relational.RowExpression in project presto by prestodb.
the class CursorProcessorCompiler method generateMethodsForLambdaAndTry.
private PreGeneratedExpressions generateMethodsForLambdaAndTry(ClassDefinition containerClassDefinition, CallSiteBinder callSiteBinder, CachedInstanceBinder cachedInstanceBinder, RowExpression projection, String methodPrefix) {
Set<RowExpression> lambdaAndTryExpressions = ImmutableSet.copyOf(extractLambdaAndTryExpressions(projection));
ImmutableMap.Builder<CallExpression, MethodDefinition> tryMethodMap = ImmutableMap.builder();
ImmutableMap.Builder<LambdaDefinitionExpression, FieldDefinition> lambdaFieldMap = ImmutableMap.builder();
int counter = 0;
for (RowExpression expression : lambdaAndTryExpressions) {
if (expression instanceof CallExpression) {
CallExpression tryExpression = (CallExpression) expression;
verify(!Signatures.TRY.equals(tryExpression.getSignature().getName()));
Parameter session = arg("session", ConnectorSession.class);
Parameter cursor = arg("cursor", RecordCursor.class);
List<Parameter> inputParameters = ImmutableList.<Parameter>builder().add(session).add(cursor).build();
BytecodeExpressionVisitor innerExpressionVisitor = new BytecodeExpressionVisitor(callSiteBinder, cachedInstanceBinder, fieldReferenceCompiler(cursor), metadata.getFunctionRegistry(), new PreGeneratedExpressions(tryMethodMap.build(), lambdaFieldMap.build()));
MethodDefinition tryMethod = defineTryMethod(innerExpressionVisitor, containerClassDefinition, methodPrefix + "_try_" + counter, inputParameters, Primitives.wrap(tryExpression.getType().getJavaType()), tryExpression, callSiteBinder);
tryMethodMap.put(tryExpression, tryMethod);
} else if (expression instanceof LambdaDefinitionExpression) {
LambdaDefinitionExpression lambdaExpression = (LambdaDefinitionExpression) expression;
String fieldName = methodPrefix + "_lambda_" + counter;
PreGeneratedExpressions preGeneratedExpressions = new PreGeneratedExpressions(tryMethodMap.build(), lambdaFieldMap.build());
FieldDefinition methodHandleField = LambdaBytecodeGenerator.preGenerateLambdaExpression(lambdaExpression, fieldName, containerClassDefinition, preGeneratedExpressions, callSiteBinder, cachedInstanceBinder, metadata.getFunctionRegistry());
lambdaFieldMap.put(lambdaExpression, methodHandleField);
} else {
throw new VerifyException(format("unexpected expression: %s", expression.toString()));
}
counter++;
}
return new PreGeneratedExpressions(tryMethodMap.build(), lambdaFieldMap.build());
}
Aggregations