use of com.facebook.presto.sql.relational.CallExpression 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.CallExpression in project presto by prestodb.
the class LambdaBytecodeGenerator method variableReferenceCompiler.
private static RowExpressionVisitor<Scope, BytecodeNode> variableReferenceCompiler(Map<String, ParameterAndType> parameterMap) {
return new RowExpressionVisitor<Scope, BytecodeNode>() {
@Override
public BytecodeNode visitInputReference(InputReferenceExpression node, Scope scope) {
throw new UnsupportedOperationException();
}
@Override
public BytecodeNode visitCall(CallExpression call, Scope scope) {
throw new UnsupportedOperationException();
}
@Override
public BytecodeNode visitConstant(ConstantExpression literal, Scope scope) {
throw new UnsupportedOperationException();
}
@Override
public BytecodeNode visitLambda(LambdaDefinitionExpression lambda, Scope context) {
throw new UnsupportedOperationException();
}
@Override
public BytecodeNode visitVariableReference(VariableReferenceExpression reference, Scope context) {
ParameterAndType parameterAndType = parameterMap.get(reference.getName());
Parameter parameter = parameterAndType.getParameter();
Class<?> type = parameterAndType.getType();
return new BytecodeBlock().append(parameter).append(unboxPrimitiveIfNecessary(context, type));
}
};
}
use of com.facebook.presto.sql.relational.CallExpression 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());
}
use of com.facebook.presto.sql.relational.CallExpression in project presto by prestodb.
the class CursorProcessorCompiler method fieldReferenceCompiler.
private static RowExpressionVisitor<Scope, BytecodeNode> fieldReferenceCompiler(Variable cursorVariable) {
return new RowExpressionVisitor<Scope, BytecodeNode>() {
@Override
public BytecodeNode visitInputReference(InputReferenceExpression node, Scope scope) {
int field = node.getField();
Type type = node.getType();
Variable wasNullVariable = scope.getVariable("wasNull");
Class<?> javaType = type.getJavaType();
if (!javaType.isPrimitive() && javaType != Slice.class) {
javaType = Object.class;
}
IfStatement ifStatement = new IfStatement();
ifStatement.condition().setDescription(format("cursor.get%s(%d)", type, field)).getVariable(cursorVariable).push(field).invokeInterface(RecordCursor.class, "isNull", boolean.class, int.class);
ifStatement.ifTrue().putVariable(wasNullVariable, true).pushJavaDefault(javaType);
ifStatement.ifFalse().getVariable(cursorVariable).push(field).invokeInterface(RecordCursor.class, "get" + Primitives.wrap(javaType).getSimpleName(), javaType, int.class);
return ifStatement;
}
@Override
public BytecodeNode visitCall(CallExpression call, Scope scope) {
throw new UnsupportedOperationException("not yet implemented");
}
@Override
public BytecodeNode visitConstant(ConstantExpression literal, Scope scope) {
throw new UnsupportedOperationException("not yet implemented");
}
@Override
public BytecodeNode visitLambda(LambdaDefinitionExpression lambda, Scope context) {
throw new UnsupportedOperationException();
}
@Override
public BytecodeNode visitVariableReference(VariableReferenceExpression reference, Scope context) {
throw new UnsupportedOperationException();
}
};
}
use of com.facebook.presto.sql.relational.CallExpression in project presto by prestodb.
the class TestPageProcessorCompiler method testNonDeterministicProject.
@Test
public void testNonDeterministicProject() throws Exception {
Signature lessThan = internalOperator(LESS_THAN, BOOLEAN, ImmutableList.of(BIGINT, BIGINT));
CallExpression random = new CallExpression(new Signature("random", SCALAR, parseTypeSignature(StandardTypes.BIGINT), parseTypeSignature(StandardTypes.BIGINT)), BIGINT, singletonList(new ConstantExpression(10L, BIGINT)));
InputReferenceExpression col0 = new InputReferenceExpression(0, BIGINT);
CallExpression lessThanRandomExpression = new CallExpression(lessThan, BOOLEAN, ImmutableList.of(col0, random));
PageProcessor processor = new ExpressionCompiler(createTestMetadataManager()).compilePageProcessor(new ConstantExpression(TRUE, BOOLEAN), ImmutableList.of(lessThanRandomExpression)).get();
assertFalse(new DeterminismEvaluator(METADATA_MANAGER.getFunctionRegistry()).isDeterministic(lessThanRandomExpression));
Page page = new Page(createLongDictionaryBlock(1, 100));
Page outputPage = processor.processColumnarDictionary(null, page, ImmutableList.of(BOOLEAN));
assertFalse(outputPage.getBlock(0) instanceof DictionaryBlock);
}
Aggregations