Search in sources :

Example 1 with FunctionHandle

use of com.facebook.presto.spi.function.FunctionHandle in project presto by prestodb.

the class SubfieldExtractor method toRowExpression.

private RowExpression toRowExpression(Subfield subfield, List<Type> types) {
    List<Subfield.PathElement> path = subfield.getPath();
    if (path.isEmpty()) {
        return new VariableReferenceExpression(Optional.empty(), subfield.getRootName(), types.get(0));
    }
    RowExpression base = toRowExpression(new Subfield(subfield.getRootName(), path.subList(0, path.size() - 1)), types.subList(0, types.size() - 1));
    Type baseType = types.get(types.size() - 2);
    Subfield.PathElement pathElement = path.get(path.size() - 1);
    if (pathElement instanceof Subfield.LongSubscript) {
        Type indexType = baseType instanceof MapType ? ((MapType) baseType).getKeyType() : BIGINT;
        FunctionHandle functionHandle = functionResolution.subscriptFunction(baseType, indexType);
        ConstantExpression index = new ConstantExpression(base.getSourceLocation(), ((Subfield.LongSubscript) pathElement).getIndex(), indexType);
        return new CallExpression(base.getSourceLocation(), SUBSCRIPT.name(), functionHandle, types.get(types.size() - 1), ImmutableList.of(base, index));
    }
    if (pathElement instanceof Subfield.StringSubscript) {
        Type indexType = ((MapType) baseType).getKeyType();
        FunctionHandle functionHandle = functionResolution.subscriptFunction(baseType, indexType);
        ConstantExpression index = new ConstantExpression(base.getSourceLocation(), Slices.utf8Slice(((Subfield.StringSubscript) pathElement).getIndex()), indexType);
        return new CallExpression(base.getSourceLocation(), SUBSCRIPT.name(), functionHandle, types.get(types.size() - 1), ImmutableList.of(base, index));
    }
    if (pathElement instanceof Subfield.NestedField) {
        Subfield.NestedField nestedField = (Subfield.NestedField) pathElement;
        return new SpecialFormExpression(base.getSourceLocation(), DEREFERENCE, types.get(types.size() - 1), base, new ConstantExpression(base.getSourceLocation(), getFieldIndex((RowType) baseType, nestedField.getName()), INTEGER));
    }
    verify(false, "Unexpected path element: " + pathElement);
    return null;
}
Also used : ConstantExpression(com.facebook.presto.spi.relation.ConstantExpression) RowExpression(com.facebook.presto.spi.relation.RowExpression) MapType(com.facebook.presto.common.type.MapType) MapType(com.facebook.presto.common.type.MapType) Varchars.isVarcharType(com.facebook.presto.common.type.Varchars.isVarcharType) ArrayType(com.facebook.presto.common.type.ArrayType) Type(com.facebook.presto.common.type.Type) RowType(com.facebook.presto.common.type.RowType) VariableReferenceExpression(com.facebook.presto.spi.relation.VariableReferenceExpression) FunctionHandle(com.facebook.presto.spi.function.FunctionHandle) CallExpression(com.facebook.presto.spi.relation.CallExpression) SpecialFormExpression(com.facebook.presto.spi.relation.SpecialFormExpression) Subfield(com.facebook.presto.common.Subfield)

Example 2 with FunctionHandle

use of com.facebook.presto.spi.function.FunctionHandle in project presto by prestodb.

the class AggregatedOrcPageSource method getNextPage.

@Override
public Page getNextPage() {
    if (completed) {
        return null;
    }
    long start = System.nanoTime();
    Block[] blocks = new Block[columnHandles.size()];
    for (int fieldId = 0; fieldId < blocks.length; fieldId++) {
        HiveColumnHandle columnHandle = columnHandles.get(fieldId);
        Aggregation aggregation = columnHandle.getPartialAggregation().get();
        int columnIndex = columnHandle.getHiveColumnIndex();
        Type type = typeManager.getType(columnHandle.getTypeSignature());
        BlockBuilder blockBuilder = type.createBlockBuilder(null, batchSize, 0);
        FunctionHandle functionHandle = aggregation.getFunctionHandle();
        if (functionResolution.isCountFunction(functionHandle)) {
            if (aggregation.getArguments().isEmpty()) {
                blockBuilder = blockBuilder.writeLong(footer.getNumberOfRows());
            } else {
                writeNonNullCount(columnIndex, blockBuilder);
            }
            completedBytes += INTEGER.getFixedSize();
        } else if (functionResolution.isMaxFunction(functionHandle)) {
            writeMinMax(columnIndex, type, columnHandle.getHiveType(), blockBuilder, false);
        } else if (functionResolution.isMinFunction(functionHandle)) {
            writeMinMax(columnIndex, type, columnHandle.getHiveType(), blockBuilder, true);
        } else {
            throw new UnsupportedOperationException(aggregation.getFunctionHandle().toString() + " is not supported");
        }
        blocks[fieldId] = blockBuilder.build();
    }
    completed = true;
    readTimeNanos += System.nanoTime() - start;
    return new Page(batchSize, blocks);
}
Also used : Aggregation(com.facebook.presto.spi.plan.AggregationNode.Aggregation) HiveType(com.facebook.presto.hive.HiveType) FixedWidthType(com.facebook.presto.common.type.FixedWidthType) OrcType(com.facebook.presto.orc.metadata.OrcType) Type(com.facebook.presto.common.type.Type) Block(com.facebook.presto.common.block.Block) Page(com.facebook.presto.common.Page) FunctionHandle(com.facebook.presto.spi.function.FunctionHandle) HiveColumnHandle(com.facebook.presto.hive.HiveColumnHandle) BlockBuilder(com.facebook.presto.common.block.BlockBuilder)

Example 3 with FunctionHandle

use of com.facebook.presto.spi.function.FunctionHandle in project presto by prestodb.

the class InCodeGenerator method generateExpression.

@Override
public BytecodeNode generateExpression(BytecodeGeneratorContext generatorContext, Type returnType, List<RowExpression> arguments, Optional<Variable> outputBlockVariable) {
    List<RowExpression> values = arguments.subList(1, arguments.size());
    // empty IN statements are not allowed by the standard, and not possible here
    // the implementation assumes this condition is always met
    checkArgument(values.size() > 0, "values must not be empty");
    Type type = arguments.get(0).getType();
    Class<?> javaType = type.getJavaType();
    SwitchGenerationCase switchGenerationCase = checkSwitchGenerationCase(type, values);
    FunctionHandle hashCodeHandle = generatorContext.getFunctionManager().resolveOperator(HASH_CODE, fromTypes(type));
    MethodHandle hashCodeFunction = generatorContext.getFunctionManager().getJavaScalarFunctionImplementation(hashCodeHandle).getMethodHandle();
    FunctionHandle isIndeterminateHandle = generatorContext.getFunctionManager().resolveOperator(INDETERMINATE, fromTypes(type));
    JavaScalarFunctionImplementation isIndeterminateFunction = generatorContext.getFunctionManager().getJavaScalarFunctionImplementation(isIndeterminateHandle);
    ImmutableListMultimap.Builder<Integer, BytecodeNode> hashBucketsBuilder = ImmutableListMultimap.builder();
    ImmutableList.Builder<BytecodeNode> defaultBucket = ImmutableList.builder();
    ImmutableSet.Builder<Object> constantValuesBuilder = ImmutableSet.builder();
    for (RowExpression testValue : values) {
        BytecodeNode testBytecode = generatorContext.generate(testValue, Optional.empty());
        if (isDeterminateConstant(testValue, isIndeterminateFunction.getMethodHandle())) {
            ConstantExpression constant = (ConstantExpression) testValue;
            Object object = constant.getValue();
            switch(switchGenerationCase) {
                case DIRECT_SWITCH:
                case SET_CONTAINS:
                    constantValuesBuilder.add(object);
                    break;
                case HASH_SWITCH:
                    try {
                        int hashCode = toIntExact(Long.hashCode((Long) hashCodeFunction.invoke(object)));
                        hashBucketsBuilder.put(hashCode, testBytecode);
                    } catch (Throwable throwable) {
                        throw new IllegalArgumentException("Error processing IN statement: error calculating hash code for " + object, throwable);
                    }
                    break;
                default:
                    throw new IllegalArgumentException("Not supported switch generation case: " + switchGenerationCase);
            }
        } else {
            defaultBucket.add(testBytecode);
        }
    }
    ImmutableListMultimap<Integer, BytecodeNode> hashBuckets = hashBucketsBuilder.build();
    ImmutableSet<Object> constantValues = constantValuesBuilder.build();
    LabelNode end = new LabelNode("end");
    LabelNode match = new LabelNode("match");
    LabelNode noMatch = new LabelNode("noMatch");
    LabelNode defaultLabel = new LabelNode("default");
    Scope scope = generatorContext.getScope();
    Variable value = scope.createTempVariable(javaType);
    BytecodeNode switchBlock;
    Variable expression = scope.createTempVariable(int.class);
    SwitchBuilder switchBuilder = new SwitchBuilder().expression(expression);
    switch(switchGenerationCase) {
        case DIRECT_SWITCH:
            // For these types, it's safe to not use presto HASH_CODE and EQUAL operator.
            for (Object constantValue : constantValues) {
                switchBuilder.addCase(toIntExact((Long) constantValue), jump(match));
            }
            switchBuilder.defaultCase(jump(defaultLabel));
            switchBlock = new BytecodeBlock().comment("lookupSwitch(<stackValue>))").append(new IfStatement().condition(invokeStatic(InCodeGenerator.class, "isInteger", boolean.class, value)).ifFalse(new BytecodeBlock().gotoLabel(defaultLabel))).append(expression.set(value.cast(int.class))).append(switchBuilder.build());
            break;
        case HASH_SWITCH:
            for (Map.Entry<Integer, Collection<BytecodeNode>> bucket : hashBuckets.asMap().entrySet()) {
                Collection<BytecodeNode> testValues = bucket.getValue();
                BytecodeBlock caseBlock = buildInCase(generatorContext, scope, type, match, defaultLabel, value, testValues, false, isIndeterminateFunction);
                switchBuilder.addCase(bucket.getKey(), caseBlock);
            }
            switchBuilder.defaultCase(jump(defaultLabel));
            Binding hashCodeBinding = generatorContext.getCallSiteBinder().bind(hashCodeFunction);
            switchBlock = new BytecodeBlock().comment("lookupSwitch(hashCode(<stackValue>))").getVariable(value).append(invoke(hashCodeBinding, HASH_CODE.name())).invokeStatic(Long.class, "hashCode", int.class, long.class).putVariable(expression).append(switchBuilder.build());
            break;
        case SET_CONTAINS:
            Set<?> constantValuesSet = toFastutilHashSet(constantValues, type, functionAndTypeManager);
            Binding constant = generatorContext.getCallSiteBinder().bind(constantValuesSet, constantValuesSet.getClass());
            switchBlock = new BytecodeBlock().comment("inListSet.contains(<stackValue>)").append(new IfStatement().condition(new BytecodeBlock().comment("value").getVariable(value).comment("set").append(loadConstant(constant)).invokeStatic(FastutilSetHelper.class, "in", boolean.class, javaType.isPrimitive() ? javaType : Object.class, constantValuesSet.getClass())).ifTrue(jump(match)));
            break;
        default:
            throw new IllegalArgumentException("Not supported switch generation case: " + switchGenerationCase);
    }
    BytecodeBlock defaultCaseBlock = buildInCase(generatorContext, scope, type, match, noMatch, value, defaultBucket.build(), true, isIndeterminateFunction).setDescription("default");
    BytecodeBlock block = new BytecodeBlock().comment("IN").append(generatorContext.generate(arguments.get(0), Optional.empty())).append(ifWasNullPopAndGoto(scope, end, boolean.class, javaType)).putVariable(value).append(switchBlock).visitLabel(defaultLabel).append(defaultCaseBlock);
    BytecodeBlock matchBlock = new BytecodeBlock().setDescription("match").visitLabel(match).append(generatorContext.wasNull().set(constantFalse())).push(true).gotoLabel(end);
    block.append(matchBlock);
    BytecodeBlock noMatchBlock = new BytecodeBlock().setDescription("noMatch").visitLabel(noMatch).push(false).gotoLabel(end);
    block.append(noMatchBlock);
    block.visitLabel(end);
    outputBlockVariable.ifPresent(output -> block.append(generateWrite(generatorContext, returnType, output)));
    return block;
}
Also used : LabelNode(com.facebook.presto.bytecode.instruction.LabelNode) JavaScalarFunctionImplementation(com.facebook.presto.spi.function.JavaScalarFunctionImplementation) Variable(com.facebook.presto.bytecode.Variable) ImmutableList(com.google.common.collect.ImmutableList) ConstantExpression(com.facebook.presto.spi.relation.ConstantExpression) IfStatement(com.facebook.presto.bytecode.control.IfStatement) ImmutableSet(com.google.common.collect.ImmutableSet) ImmutableListMultimap(com.google.common.collect.ImmutableListMultimap) BytecodeNode(com.facebook.presto.bytecode.BytecodeNode) FunctionHandle(com.facebook.presto.spi.function.FunctionHandle) Binding(com.facebook.presto.bytecode.Binding) BytecodeBlock(com.facebook.presto.bytecode.BytecodeBlock) RowExpression(com.facebook.presto.spi.relation.RowExpression) IntegerType(com.facebook.presto.common.type.IntegerType) Type(com.facebook.presto.common.type.Type) BigintType(com.facebook.presto.common.type.BigintType) DateType(com.facebook.presto.common.type.DateType) Scope(com.facebook.presto.bytecode.Scope) SwitchBuilder(com.facebook.presto.bytecode.control.SwitchStatement.SwitchBuilder) Collection(java.util.Collection) Map(java.util.Map) MethodHandle(java.lang.invoke.MethodHandle)

Example 4 with FunctionHandle

use of com.facebook.presto.spi.function.FunctionHandle in project presto by prestodb.

the class InCodeGenerator method buildInCase.

private static BytecodeBlock buildInCase(BytecodeGeneratorContext generatorContext, Scope scope, Type type, LabelNode matchLabel, LabelNode noMatchLabel, Variable value, Collection<BytecodeNode> testValues, boolean checkForNulls, JavaScalarFunctionImplementation isIndeterminateFunction) {
    // caseWasNull is set to true the first time a null in `testValues` is encountered
    Variable caseWasNull = null;
    if (checkForNulls) {
        caseWasNull = scope.createTempVariable(boolean.class);
    }
    BytecodeBlock caseBlock = new BytecodeBlock();
    if (checkForNulls) {
        caseBlock.putVariable(caseWasNull, false);
    }
    LabelNode elseLabel = new LabelNode("else");
    BytecodeBlock elseBlock = new BytecodeBlock().visitLabel(elseLabel);
    Variable wasNull = generatorContext.wasNull();
    if (checkForNulls) {
        // That is incorrect. Doing an explicit check for indeterminate is required to correctly return NULL.
        if (testValues.isEmpty()) {
            elseBlock.append(new BytecodeBlock().append(generatorContext.generateCall(INDETERMINATE.name(), isIndeterminateFunction, ImmutableList.of(value))).putVariable(wasNull));
        } else {
            elseBlock.append(wasNull.set(caseWasNull));
        }
    }
    elseBlock.gotoLabel(noMatchLabel);
    FunctionHandle equalsHandle = generatorContext.getFunctionManager().resolveOperator(EQUAL, fromTypes(type, type));
    JavaScalarFunctionImplementation equalsFunction = generatorContext.getFunctionManager().getJavaScalarFunctionImplementation(equalsHandle);
    BytecodeNode elseNode = elseBlock;
    for (BytecodeNode testNode : testValues) {
        LabelNode testLabel = new LabelNode("test");
        IfStatement test = new IfStatement();
        BytecodeNode equalsCall = generatorContext.generateCall(EQUAL.name(), equalsFunction, ImmutableList.of(value, testNode));
        test.condition().visitLabel(testLabel).append(equalsCall);
        if (checkForNulls) {
            IfStatement wasNullCheck = new IfStatement("if wasNull, set caseWasNull to true, clear wasNull, pop boolean, and goto next test value");
            wasNullCheck.condition(wasNull);
            wasNullCheck.ifTrue(new BytecodeBlock().append(caseWasNull.set(constantTrue())).append(wasNull.set(constantFalse())).pop(boolean.class).gotoLabel(elseLabel));
            test.condition().append(wasNullCheck);
        }
        test.ifTrue().gotoLabel(matchLabel);
        test.ifFalse(elseNode);
        elseNode = test;
        elseLabel = testLabel;
    }
    caseBlock.append(elseNode);
    return caseBlock;
}
Also used : LabelNode(com.facebook.presto.bytecode.instruction.LabelNode) JavaScalarFunctionImplementation(com.facebook.presto.spi.function.JavaScalarFunctionImplementation) IfStatement(com.facebook.presto.bytecode.control.IfStatement) Variable(com.facebook.presto.bytecode.Variable) BytecodeBlock(com.facebook.presto.bytecode.BytecodeBlock) BytecodeNode(com.facebook.presto.bytecode.BytecodeNode) FunctionHandle(com.facebook.presto.spi.function.FunctionHandle)

Example 5 with FunctionHandle

use of com.facebook.presto.spi.function.FunctionHandle in project presto by prestodb.

the class NullIfCodeGenerator method generateExpression.

@Override
public BytecodeNode generateExpression(BytecodeGeneratorContext generatorContext, Type returnType, List<RowExpression> arguments, Optional<Variable> outputBlockVariable) {
    Scope scope = generatorContext.getScope();
    RowExpression first = arguments.get(0);
    RowExpression second = arguments.get(1);
    LabelNode notMatch = new LabelNode("notMatch");
    // push first arg on the stack
    Variable firstValue = scope.createTempVariable(first.getType().getJavaType());
    BytecodeBlock block = new BytecodeBlock().comment("check if first arg is null").append(generatorContext.generate(first, Optional.empty())).append(ifWasNullPopAndGoto(scope, notMatch, void.class)).dup(first.getType().getJavaType()).putVariable(firstValue);
    Type firstType = first.getType();
    Type secondType = second.getType();
    // if (equal(cast(first as <common type>), cast(second as <common type>))
    FunctionAndTypeManager functionAndTypeManager = generatorContext.getFunctionManager();
    FunctionHandle equalFunction = functionAndTypeManager.resolveOperator(EQUAL, fromTypes(firstType, secondType));
    FunctionMetadata equalFunctionMetadata = functionAndTypeManager.getFunctionMetadata(equalFunction);
    JavaScalarFunctionImplementation equalsFunction = generatorContext.getFunctionManager().getJavaScalarFunctionImplementation(equalFunction);
    BytecodeNode equalsCall = generatorContext.generateCall(EQUAL.name(), equalsFunction, ImmutableList.of(cast(generatorContext, firstValue, firstType, equalFunctionMetadata.getArgumentTypes().get(0)), cast(generatorContext, generatorContext.generate(second, Optional.empty()), secondType, equalFunctionMetadata.getArgumentTypes().get(1))));
    BytecodeBlock conditionBlock = new BytecodeBlock().append(equalsCall).append(BytecodeUtils.ifWasNullClearPopAndGoto(scope, notMatch, void.class, boolean.class));
    // if first and second are equal, return null
    BytecodeBlock trueBlock = new BytecodeBlock().append(generatorContext.wasNull().set(constantTrue())).pop(first.getType().getJavaType()).pushJavaDefault(first.getType().getJavaType());
    // else return first (which is still on the stack
    block.append(new IfStatement().condition(conditionBlock).ifTrue(trueBlock).ifFalse(notMatch));
    outputBlockVariable.ifPresent(output -> block.append(generateWrite(generatorContext, returnType, output)));
    return block;
}
Also used : LabelNode(com.facebook.presto.bytecode.instruction.LabelNode) FunctionMetadata(com.facebook.presto.spi.function.FunctionMetadata) JavaScalarFunctionImplementation(com.facebook.presto.spi.function.JavaScalarFunctionImplementation) IfStatement(com.facebook.presto.bytecode.control.IfStatement) CastType(com.facebook.presto.metadata.CastType) Type(com.facebook.presto.common.type.Type) Variable(com.facebook.presto.bytecode.Variable) Scope(com.facebook.presto.bytecode.Scope) FunctionAndTypeManager(com.facebook.presto.metadata.FunctionAndTypeManager) BytecodeBlock(com.facebook.presto.bytecode.BytecodeBlock) RowExpression(com.facebook.presto.spi.relation.RowExpression) BytecodeNode(com.facebook.presto.bytecode.BytecodeNode) FunctionHandle(com.facebook.presto.spi.function.FunctionHandle)

Aggregations

FunctionHandle (com.facebook.presto.spi.function.FunctionHandle)44 Test (org.testng.annotations.Test)20 CallExpression (com.facebook.presto.spi.relation.CallExpression)16 Type (com.facebook.presto.common.type.Type)14 RowExpression (com.facebook.presto.spi.relation.RowExpression)13 FunctionAndTypeManager (com.facebook.presto.metadata.FunctionAndTypeManager)9 VariableReferenceExpression (com.facebook.presto.spi.relation.VariableReferenceExpression)9 ImmutableList (com.google.common.collect.ImmutableList)8 Variable (com.facebook.presto.bytecode.Variable)7 JavaScalarFunctionImplementation (com.facebook.presto.spi.function.JavaScalarFunctionImplementation)7 BytecodeBlock (com.facebook.presto.bytecode.BytecodeBlock)6 IfStatement (com.facebook.presto.bytecode.control.IfStatement)6 Page (com.facebook.presto.common.Page)6 ArrayType (com.facebook.presto.common.type.ArrayType)6 Map (java.util.Map)6 BytecodeNode (com.facebook.presto.bytecode.BytecodeNode)5 Scope (com.facebook.presto.bytecode.Scope)5 FunctionMetadata (com.facebook.presto.spi.function.FunctionMetadata)5 LabelNode (com.facebook.presto.bytecode.instruction.LabelNode)4 MapType (com.facebook.presto.common.type.MapType)4