Search in sources :

Example 1 with ConstantExpression

use of com.facebook.presto.spi.relation.ConstantExpression 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 ConstantExpression

use of com.facebook.presto.spi.relation.ConstantExpression 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 3 with ConstantExpression

use of com.facebook.presto.spi.relation.ConstantExpression in project presto by prestodb.

the class PageFunctionCompiler method compileProjection.

private Supplier<PageProjection> compileProjection(SqlFunctionProperties sqlFunctionProperties, Map<SqlFunctionId, SqlInvokedFunction> sessionFunctions, RowExpression projection, Optional<String> classNameSuffix) {
    if (projection instanceof InputReferenceExpression) {
        InputReferenceExpression input = (InputReferenceExpression) projection;
        InputPageProjection projectionFunction = new InputPageProjection(input.getField());
        return () -> projectionFunction;
    }
    if (projection instanceof ConstantExpression) {
        ConstantExpression constant = (ConstantExpression) projection;
        ConstantPageProjection projectionFunction = new ConstantPageProjection(constant.getValue(), constant.getType());
        return () -> projectionFunction;
    }
    return compileProjectionCached(sqlFunctionProperties, sessionFunctions, ImmutableList.of(projection), false, classNameSuffix);
}
Also used : InputReferenceExpression(com.facebook.presto.spi.relation.InputReferenceExpression) InputPageProjection(com.facebook.presto.operator.project.InputPageProjection) ConstantPageProjection(com.facebook.presto.operator.project.ConstantPageProjection) ConstantExpression(com.facebook.presto.spi.relation.ConstantExpression)

Example 4 with ConstantExpression

use of com.facebook.presto.spi.relation.ConstantExpression in project presto by prestodb.

the class InCodeGenerator method checkSwitchGenerationCase.

@VisibleForTesting
static SwitchGenerationCase checkSwitchGenerationCase(Type type, List<RowExpression> values) {
    if (values.size() > 32) {
        // * Benchmark shows performance of SET_CONTAINS is better at 50, but similar at 25.
        return SwitchGenerationCase.SET_CONTAINS;
    }
    if (!(type instanceof IntegerType || type instanceof BigintType || type instanceof DateType)) {
        return SwitchGenerationCase.HASH_SWITCH;
    }
    for (RowExpression expression : values) {
        // Same argument applies for nulls.
        if (!(expression instanceof ConstantExpression)) {
            continue;
        }
        Object constant = ((ConstantExpression) expression).getValue();
        if (constant == null) {
            continue;
        }
        long longConstant = ((Number) constant).longValue();
        if (longConstant < Integer.MIN_VALUE || longConstant > Integer.MAX_VALUE) {
            return SwitchGenerationCase.HASH_SWITCH;
        }
    }
    return SwitchGenerationCase.DIRECT_SWITCH;
}
Also used : IntegerType(com.facebook.presto.common.type.IntegerType) ConstantExpression(com.facebook.presto.spi.relation.ConstantExpression) RowExpression(com.facebook.presto.spi.relation.RowExpression) DateType(com.facebook.presto.common.type.DateType) BigintType(com.facebook.presto.common.type.BigintType) VisibleForTesting(com.google.common.annotations.VisibleForTesting)

Example 5 with ConstantExpression

use of com.facebook.presto.spi.relation.ConstantExpression in project presto by prestodb.

the class RemoteProjectOperator method addInput.

@Override
public void addInput(Page page) {
    checkState(!finishing, "Operator is already finishing");
    checkState(!processingPage(), "Still processing previous input");
    requireNonNull(page, "page is null");
    for (int channel = 0; channel < projections.size(); channel++) {
        RowExpression projection = projections.get(channel);
        if (projection instanceof InputReferenceExpression) {
            result[channel] = completedFuture(new SqlFunctionResult(page.getBlock(((InputReferenceExpression) projection).getField()), 0));
        } else if (projection instanceof CallExpression) {
            CallExpression remoteCall = (CallExpression) projection;
            result[channel] = functionAndTypeManager.executeFunction(operatorContext.getDriverContext().getTaskId().toString(), remoteCall.getFunctionHandle(), page, remoteCall.getArguments().stream().map(InputReferenceExpression.class::cast).map(InputReferenceExpression::getField).collect(toImmutableList()));
        } else {
            checkState(projection instanceof ConstantExpression, format("Does not expect expression type %s", projection.getClass()));
        }
    }
}
Also used : InputReferenceExpression(com.facebook.presto.spi.relation.InputReferenceExpression) ConstantExpression(com.facebook.presto.spi.relation.ConstantExpression) RowExpression(com.facebook.presto.spi.relation.RowExpression) SqlFunctionResult(com.facebook.presto.common.function.SqlFunctionResult) CallExpression(com.facebook.presto.spi.relation.CallExpression)

Aggregations

ConstantExpression (com.facebook.presto.spi.relation.ConstantExpression)33 RowExpression (com.facebook.presto.spi.relation.RowExpression)25 CallExpression (com.facebook.presto.spi.relation.CallExpression)14 VariableReferenceExpression (com.facebook.presto.spi.relation.VariableReferenceExpression)14 SpecialFormExpression (com.facebook.presto.spi.relation.SpecialFormExpression)10 Map (java.util.Map)8 ImmutableList (com.google.common.collect.ImmutableList)7 BytecodeBlock (com.facebook.presto.bytecode.BytecodeBlock)6 Type (com.facebook.presto.common.type.Type)6 InputReferenceExpression (com.facebook.presto.spi.relation.InputReferenceExpression)6 ImmutableMap (com.google.common.collect.ImmutableMap)6 Slice (io.airlift.slice.Slice)6 List (java.util.List)6 Scope (com.facebook.presto.bytecode.Scope)5 Variable (com.facebook.presto.bytecode.Variable)5 FunctionHandle (com.facebook.presto.spi.function.FunctionHandle)5 ImmutableList.toImmutableList (com.google.common.collect.ImmutableList.toImmutableList)5 Objects.requireNonNull (java.util.Objects.requireNonNull)5 Optional (java.util.Optional)5 IfStatement (com.facebook.presto.bytecode.control.IfStatement)4