use of com.facebook.presto.spi.relation.SpecialFormExpression in project presto by prestodb.
the class PageFunctionCompiler method compileProjectionInternal.
private Supplier<PageProjection> compileProjectionInternal(SqlFunctionProperties sqlFunctionProperties, Map<SqlFunctionId, SqlInvokedFunction> sessionFunctions, List<RowExpression> projections, boolean isOptimizeCommonSubExpression, Optional<String> classNameSuffix) {
requireNonNull(projections, "projections is null");
checkArgument(!projections.isEmpty() && projections.stream().allMatch(projection -> projection instanceof CallExpression || projection instanceof SpecialFormExpression));
PageFieldsToInputParametersRewriter.Result result = rewritePageFieldsToInputParameters(projections);
List<RowExpression> rewrittenExpression = result.getRewrittenExpressions();
CallSiteBinder callSiteBinder = new CallSiteBinder();
// generate Work
ClassDefinition pageProjectionWorkDefinition = definePageProjectWorkClass(sqlFunctionProperties, sessionFunctions, rewrittenExpression, callSiteBinder, isOptimizeCommonSubExpression, classNameSuffix);
Class<? extends Work> pageProjectionWorkClass;
try {
pageProjectionWorkClass = defineClass(pageProjectionWorkDefinition, Work.class, callSiteBinder.getBindings(), getClass().getClassLoader());
} catch (PrestoException prestoException) {
throw prestoException;
} catch (Exception e) {
throw new PrestoException(COMPILER_ERROR, e);
}
return () -> new GeneratedPageProjection(rewrittenExpression, rewrittenExpression.stream().allMatch(determinismEvaluator::isDeterministic), result.getInputChannels(), constructorMethodHandle(pageProjectionWorkClass, List.class, SqlFunctionProperties.class, Page.class, SelectedPositions.class));
}
use of com.facebook.presto.spi.relation.SpecialFormExpression in project presto by prestodb.
the class LambdaBytecodeGenerator method variableReferenceCompiler.
private static RowExpressionVisitor<BytecodeNode, Scope> variableReferenceCompiler(Map<String, ParameterAndType> parameterMap) {
return new RowExpressionVisitor<BytecodeNode, Scope>() {
@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));
}
@Override
public BytecodeNode visitSpecialForm(SpecialFormExpression specialForm, Scope context) {
throw new UnsupportedOperationException();
}
};
}
use of com.facebook.presto.spi.relation.SpecialFormExpression in project presto by prestodb.
the class SwitchCodeGenerator method generateExpression.
@Override
public BytecodeNode generateExpression(BytecodeGeneratorContext generatorContext, Type returnType, List<RowExpression> arguments, Optional<Variable> outputBlockVariable) {
Scope scope = generatorContext.getScope();
BytecodeNode elseValue;
List<RowExpression> whenClauses;
RowExpression last = arguments.get(arguments.size() - 1);
if (last instanceof SpecialFormExpression && ((SpecialFormExpression) last).getForm().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, Optional.empty());
}
// determine the type of the value and result
RowExpression value = arguments.get(0);
Class<?> valueType = value.getType().getJavaType();
// We generate SearchedCase as CASE TRUE WHEN p1 THEN v1 WHEN p2 THEN p2...
boolean searchedCase = (value instanceof ConstantExpression && ((ConstantExpression) value).getType() == BOOLEAN && ((ConstantExpression) value).getValue() == Boolean.TRUE);
// evaluate the value and store it in a variable
LabelNode elseLabel = new LabelNode("else");
LabelNode endLabel = new LabelNode("end");
BytecodeBlock block = new BytecodeBlock();
Optional<BytecodeNode> getTempVariableNode;
if (!searchedCase) {
BytecodeNode valueBytecode = generatorContext.generate(value, Optional.empty());
Variable tempVariable = scope.createTempVariable(valueType);
block.append(valueBytecode).append(BytecodeUtils.ifWasNullClearPopAndGoto(scope, elseLabel, void.class, valueType)).putVariable(tempVariable);
getTempVariableNode = Optional.of(VariableInstruction.loadVariable(tempVariable));
} else {
getTempVariableNode = Optional.empty();
}
Variable wasNull = generatorContext.wasNull();
block.putVariable(wasNull, false);
Map<RowExpression, LabelNode> resultLabels = new HashMap<>();
// We already know the P1 .. Pn are all boolean just call them and search for true (false/null don't matter).
for (RowExpression clause : whenClauses) {
checkArgument(clause instanceof SpecialFormExpression && ((SpecialFormExpression) clause).getForm().equals(WHEN));
RowExpression operand = ((SpecialFormExpression) clause).getArguments().get(0);
BytecodeNode operandBytecode;
if (searchedCase) {
operandBytecode = generatorContext.generate(operand, Optional.empty());
} else {
// call equals(value, operandBytecode)
FunctionHandle equalsFunction = generatorContext.getFunctionManager().resolveOperator(EQUAL, fromTypes(value.getType(), operand.getType()));
operandBytecode = generatorContext.generateCall(EQUAL.name(), generatorContext.getFunctionManager().getJavaScalarFunctionImplementation(equalsFunction), ImmutableList.of(generatorContext.generate(operand, Optional.empty()), getTempVariableNode.get()));
}
block.append(operandBytecode);
IfStatement ifWasNull = new IfStatement().condition(wasNull);
ifWasNull.ifTrue().putVariable(wasNull, false).pop(// pop the result of the predicate eval
Boolean.class);
// Here the TOS is the result of the predicate.
RowExpression result = ((SpecialFormExpression) clause).getArguments().get(1);
LabelNode target = resultLabels.get(result);
if (target == null) {
target = new LabelNode(RESULT_LABEL_PREFIX + resultLabels.size());
resultLabels.put(result, target);
}
ifWasNull.ifFalse().ifTrueGoto(target);
block.append(ifWasNull);
}
// Here we evaluate the else result.
block.visitLabel(elseLabel).append(elseValue).gotoLabel(endLabel);
// Now generate the result expression code.
for (Map.Entry<RowExpression, LabelNode> resultLabel : resultLabels.entrySet()) {
block.visitLabel(resultLabel.getValue()).append(generatorContext.generate(resultLabel.getKey(), Optional.empty())).gotoLabel(endLabel);
}
block.visitLabel(endLabel);
outputBlockVariable.ifPresent(output -> block.append(generateWrite(generatorContext, returnType, output)));
return block;
}
use of com.facebook.presto.spi.relation.SpecialFormExpression in project presto by prestodb.
the class SubfieldExtractor method toSubfield.
private static Optional<Subfield> toSubfield(RowExpression expression, StandardFunctionResolution functionResolution, ExpressionOptimizer expressionOptimizer, ConnectorSession connectorSession) {
List<Subfield.PathElement> elements = new ArrayList<>();
while (true) {
if (expression instanceof VariableReferenceExpression) {
Collections.reverse(elements);
return Optional.of(new Subfield(((VariableReferenceExpression) expression).getName(), unmodifiableList(elements)));
}
if (expression instanceof SpecialFormExpression && ((SpecialFormExpression) expression).getForm() == DEREFERENCE) {
SpecialFormExpression dereferenceExpression = (SpecialFormExpression) expression;
RowExpression base = dereferenceExpression.getArguments().get(0);
RowType baseType = (RowType) base.getType();
RowExpression indexExpression = expressionOptimizer.optimize(dereferenceExpression.getArguments().get(1), ExpressionOptimizer.Level.OPTIMIZED, connectorSession);
if (indexExpression instanceof ConstantExpression) {
Object index = ((ConstantExpression) indexExpression).getValue();
if (index instanceof Number) {
Optional<String> fieldName = baseType.getFields().get(((Number) index).intValue()).getName();
if (fieldName.isPresent()) {
elements.add(new Subfield.NestedField(fieldName.get()));
expression = base;
continue;
}
}
}
return Optional.empty();
}
if (expression instanceof CallExpression && functionResolution.isSubscriptFunction(((CallExpression) expression).getFunctionHandle())) {
List<RowExpression> arguments = ((CallExpression) expression).getArguments();
RowExpression indexExpression = expressionOptimizer.optimize(arguments.get(1), ExpressionOptimizer.Level.OPTIMIZED, connectorSession);
if (indexExpression instanceof ConstantExpression) {
Object index = ((ConstantExpression) indexExpression).getValue();
if (index instanceof Number) {
elements.add(new Subfield.LongSubscript(((Number) index).longValue()));
expression = arguments.get(0);
continue;
}
if (isVarcharType(indexExpression.getType())) {
elements.add(new Subfield.StringSubscript(((Slice) index).toStringUtf8()));
expression = arguments.get(0);
continue;
}
}
return Optional.empty();
}
return Optional.empty();
}
}
use of com.facebook.presto.spi.relation.SpecialFormExpression in project presto by prestodb.
the class TestRowExpressionFormatter method testSpecialForm.
@Test
public void testSpecialForm() {
RowExpression specialFormExpression;
// or and and
specialFormExpression = new SpecialFormExpression(OR, BOOLEAN, createCallExpression(NOT_EQUAL), createCallExpression(IS_DISTINCT_FROM));
assertEquals(format(specialFormExpression), "((c_bigint) <> (BIGINT'5')) OR ((c_bigint) IS DISTINCT FROM (BIGINT'5'))");
specialFormExpression = new SpecialFormExpression(AND, BOOLEAN, createCallExpression(EQUAL), createCallExpression(GREATER_THAN));
assertEquals(format(specialFormExpression), "((c_bigint) = (BIGINT'5')) AND ((c_bigint) > (BIGINT'5'))");
// other
specialFormExpression = new SpecialFormExpression(IS_NULL, BOOLEAN, createCallExpression(ADD));
assertEquals(format(specialFormExpression), "IS_NULL((c_bigint) + (BIGINT'5'))");
}
Aggregations