Search in sources :

Example 6 with RowExpression

use of com.facebook.presto.sql.relational.RowExpression in project presto by prestodb.

the class NullIfCodeGenerator method generateExpression.

@Override
public BytecodeNode generateExpression(Signature signature, BytecodeGeneratorContext generatorContext, Type returnType, List<RowExpression> arguments) {
    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
    BytecodeBlock block = new BytecodeBlock().comment("check if first arg is null").append(generatorContext.generate(first)).append(BytecodeUtils.ifWasNullPopAndGoto(scope, notMatch, void.class));
    Type firstType = first.getType();
    Type secondType = second.getType();
    // if (equal(cast(first as <common type>), cast(second as <common type>))
    Signature equalsSignature = generatorContext.getRegistry().resolveOperator(OperatorType.EQUAL, ImmutableList.of(firstType, secondType));
    ScalarFunctionImplementation equalsFunction = generatorContext.getRegistry().getScalarFunctionImplementation(equalsSignature);
    BytecodeNode equalsCall = generatorContext.generateCall(equalsSignature.getName(), equalsFunction, ImmutableList.of(cast(generatorContext, new BytecodeBlock().dup(firstType.getJavaType()), firstType, equalsSignature.getArgumentTypes().get(0)), cast(generatorContext, generatorContext.generate(second), secondType, equalsSignature.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));
    return block;
}
Also used : LabelNode(com.facebook.presto.bytecode.instruction.LabelNode) ScalarFunctionImplementation(com.facebook.presto.operator.scalar.ScalarFunctionImplementation) IfStatement(com.facebook.presto.bytecode.control.IfStatement) OperatorType(com.facebook.presto.spi.function.OperatorType) Type(com.facebook.presto.spi.type.Type) Scope(com.facebook.presto.bytecode.Scope) TypeSignature(com.facebook.presto.spi.type.TypeSignature) Signature(com.facebook.presto.metadata.Signature) BytecodeBlock(com.facebook.presto.bytecode.BytecodeBlock) RowExpression(com.facebook.presto.sql.relational.RowExpression) BytecodeNode(com.facebook.presto.bytecode.BytecodeNode)

Example 7 with RowExpression

use of com.facebook.presto.sql.relational.RowExpression 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.spi.type.IntegerType) ConstantExpression(com.facebook.presto.sql.relational.ConstantExpression) RowExpression(com.facebook.presto.sql.relational.RowExpression) DateType(com.facebook.presto.spi.type.DateType) BigintType(com.facebook.presto.spi.type.BigintType) VisibleForTesting(com.google.common.annotations.VisibleForTesting)

Example 8 with RowExpression

use of com.facebook.presto.sql.relational.RowExpression in project presto by prestodb.

the class InCodeGenerator method generateExpression.

@Override
public BytecodeNode generateExpression(Signature signature, BytecodeGeneratorContext generatorContext, Type returnType, List<RowExpression> arguments) {
    BytecodeNode value = generatorContext.generate(arguments.get(0));
    List<RowExpression> values = arguments.subList(1, arguments.size());
    ImmutableList.Builder<BytecodeNode> valuesBytecode = ImmutableList.builder();
    for (int i = 1; i < arguments.size(); i++) {
        BytecodeNode testNode = generatorContext.generate(arguments.get(i));
        valuesBytecode.add(testNode);
    }
    Type type = arguments.get(0).getType();
    Class<?> javaType = type.getJavaType();
    SwitchGenerationCase switchGenerationCase = checkSwitchGenerationCase(type, values);
    Signature hashCodeSignature = internalOperator(HASH_CODE, BIGINT, ImmutableList.of(type));
    MethodHandle hashCodeFunction = generatorContext.getRegistry().getScalarFunctionImplementation(hashCodeSignature).getMethodHandle();
    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);
        if (testValue instanceof ConstantExpression && ((ConstantExpression) testValue).getValue() != null) {
            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();
    BytecodeNode switchBlock;
    BytecodeBlock switchCaseBlocks = new BytecodeBlock();
    LookupSwitch.LookupSwitchBuilder switchBuilder = lookupSwitchBuilder();
    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), match);
            }
            switchBuilder.defaultCase(defaultLabel);
            switchBlock = new BytecodeBlock().comment("lookupSwitch(<stackValue>))").dup(javaType).append(new IfStatement().condition(new BytecodeBlock().dup(javaType).invokeStatic(InCodeGenerator.class, "isInteger", boolean.class, long.class)).ifFalse(new BytecodeBlock().pop(javaType).gotoLabel(defaultLabel))).longToInt().append(switchBuilder.build());
            break;
        case HASH_SWITCH:
            for (Map.Entry<Integer, Collection<BytecodeNode>> bucket : hashBuckets.asMap().entrySet()) {
                LabelNode label = new LabelNode("inHash" + bucket.getKey());
                switchBuilder.addCase(bucket.getKey(), label);
                Collection<BytecodeNode> testValues = bucket.getValue();
                BytecodeBlock caseBlock = buildInCase(generatorContext, scope, type, label, match, defaultLabel, testValues, false);
                switchCaseBlocks.append(caseBlock.setDescription("case " + bucket.getKey()));
            }
            switchBuilder.defaultCase(defaultLabel);
            Binding hashCodeBinding = generatorContext.getCallSiteBinder().bind(hashCodeFunction);
            switchBlock = new BytecodeBlock().comment("lookupSwitch(hashCode(<stackValue>))").dup(javaType).append(invoke(hashCodeBinding, hashCodeSignature)).invokeStatic(Long.class, "hashCode", int.class, long.class).append(switchBuilder.build()).append(switchCaseBlocks);
            break;
        case SET_CONTAINS:
            Set<?> constantValuesSet = toFastutilHashSet(constantValues, type, registry);
            Binding constant = generatorContext.getCallSiteBinder().bind(constantValuesSet, constantValuesSet.getClass());
            switchBlock = new BytecodeBlock().comment("inListSet.contains(<stackValue>)").append(new IfStatement().condition(new BytecodeBlock().comment("value").dup(javaType).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, defaultLabel, match, noMatch, defaultBucket.build(), true).setDescription("default");
    BytecodeBlock block = new BytecodeBlock().comment("IN").append(value).append(ifWasNullPopAndGoto(scope, end, boolean.class, javaType)).append(switchBlock).append(defaultCaseBlock);
    BytecodeBlock matchBlock = new BytecodeBlock().setDescription("match").visitLabel(match).pop(javaType).append(generatorContext.wasNull().set(constantFalse())).push(true).gotoLabel(end);
    block.append(matchBlock);
    BytecodeBlock noMatchBlock = new BytecodeBlock().setDescription("noMatch").visitLabel(noMatch).pop(javaType).push(false).gotoLabel(end);
    block.append(noMatchBlock);
    block.visitLabel(end);
    return block;
}
Also used : LabelNode(com.facebook.presto.bytecode.instruction.LabelNode) ImmutableList(com.google.common.collect.ImmutableList) ConstantExpression(com.facebook.presto.sql.relational.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) BytecodeBlock(com.facebook.presto.bytecode.BytecodeBlock) RowExpression(com.facebook.presto.sql.relational.RowExpression) IntegerType(com.facebook.presto.spi.type.IntegerType) DateType(com.facebook.presto.spi.type.DateType) Type(com.facebook.presto.spi.type.Type) BigintType(com.facebook.presto.spi.type.BigintType) LookupSwitch(com.facebook.presto.bytecode.control.LookupSwitch) Scope(com.facebook.presto.bytecode.Scope) Signature(com.facebook.presto.metadata.Signature) Collection(java.util.Collection) Map(java.util.Map) MethodHandle(java.lang.invoke.MethodHandle)

Example 9 with RowExpression

use of com.facebook.presto.sql.relational.RowExpression in project presto by prestodb.

the class TryCodeGenerator method generateExpression.

@Override
public BytecodeNode generateExpression(Signature signature, BytecodeGeneratorContext context, Type returnType, List<RowExpression> arguments) {
    checkArgument(arguments.size() == 1, "try methods only contain a single expression");
    checkArgument(getOnlyElement(arguments) instanceof CallExpression, "try methods must contain a call expression");
    CallExpression innerCallExpression = (CallExpression) getOnlyElement(arguments);
    checkState(tryMethodsMap.containsKey(innerCallExpression), "try methods map does not contain this try call");
    MethodDefinition definition = tryMethodsMap.get(innerCallExpression);
    ImmutableList<Variable> invokeArguments = definition.getParameters().stream().map(parameter -> context.getScope().getVariable(parameter.getName())).collect(toImmutableList());
    return new BytecodeBlock().append(context.getScope().getThis().invoke(definition, invokeArguments)).append(unboxPrimitiveIfNecessary(context.getScope(), Primitives.wrap(innerCallExpression.getType().getJavaType())));
}
Also used : MethodHandle(java.lang.invoke.MethodHandle) DIVISION_BY_ZERO(com.facebook.presto.spi.StandardErrorCode.DIVISION_BY_ZERO) TryCatch(com.facebook.presto.bytecode.control.TryCatch) PrestoException(com.facebook.presto.spi.PrestoException) MethodDefinition(com.facebook.presto.bytecode.MethodDefinition) BytecodeUtils.invoke(com.facebook.presto.sql.gen.BytecodeUtils.invoke) Access.a(com.facebook.presto.bytecode.Access.a) Preconditions.checkArgument(com.google.common.base.Preconditions.checkArgument) CallExpression(com.facebook.presto.sql.relational.CallExpression) ImmutableList(com.google.common.collect.ImmutableList) ParameterizedType.type(com.facebook.presto.bytecode.ParameterizedType.type) Reflection.methodHandle(com.facebook.presto.util.Reflection.methodHandle) Type(com.facebook.presto.spi.type.Type) BytecodeUtils.boxPrimitiveIfNecessary(com.facebook.presto.sql.gen.BytecodeUtils.boxPrimitiveIfNecessary) Map(java.util.Map) RowExpression(com.facebook.presto.sql.relational.RowExpression) BytecodeBlock(com.facebook.presto.bytecode.BytecodeBlock) INVALID_FUNCTION_ARGUMENT(com.facebook.presto.spi.StandardErrorCode.INVALID_FUNCTION_ARGUMENT) ImmutableCollectors.toImmutableList(com.facebook.presto.util.ImmutableCollectors.toImmutableList) MethodType.methodType(java.lang.invoke.MethodType.methodType) PUBLIC(com.facebook.presto.bytecode.Access.PUBLIC) Variable(com.facebook.presto.bytecode.Variable) Parameter(com.facebook.presto.bytecode.Parameter) Signature(com.facebook.presto.metadata.Signature) INVALID_CAST_ARGUMENT(com.facebook.presto.spi.StandardErrorCode.INVALID_CAST_ARGUMENT) BytecodeExpressions.constantBoolean(com.facebook.presto.bytecode.expression.BytecodeExpressions.constantBoolean) Iterables.getOnlyElement(com.google.common.collect.Iterables.getOnlyElement) Primitives(com.google.common.primitives.Primitives) Preconditions.checkState(com.google.common.base.Preconditions.checkState) BytecodeNode(com.facebook.presto.bytecode.BytecodeNode) ClassDefinition(com.facebook.presto.bytecode.ClassDefinition) List(java.util.List) NUMERIC_VALUE_OUT_OF_RANGE(com.facebook.presto.spi.StandardErrorCode.NUMERIC_VALUE_OUT_OF_RANGE) MethodType(java.lang.invoke.MethodType) Scope(com.facebook.presto.bytecode.Scope) BytecodeUtils.unboxPrimitiveIfNecessary(com.facebook.presto.sql.gen.BytecodeUtils.unboxPrimitiveIfNecessary) ParameterizedType(com.facebook.presto.bytecode.ParameterizedType) Variable(com.facebook.presto.bytecode.Variable) MethodDefinition(com.facebook.presto.bytecode.MethodDefinition) BytecodeBlock(com.facebook.presto.bytecode.BytecodeBlock) CallExpression(com.facebook.presto.sql.relational.CallExpression)

Example 10 with RowExpression

use of com.facebook.presto.sql.relational.RowExpression in project presto by prestodb.

the class IsNullCodeGenerator method generateExpression.

@Override
public BytecodeNode generateExpression(Signature signature, BytecodeGeneratorContext generatorContext, Type returnType, List<RowExpression> arguments) {
    Preconditions.checkArgument(arguments.size() == 1);
    RowExpression argument = arguments.get(0);
    if (argument.getType().equals(UNKNOWN)) {
        return loadBoolean(true);
    }
    BytecodeNode value = generatorContext.generate(argument);
    // evaluate the expression, pop the produced value, and load the null flag
    Variable wasNull = generatorContext.wasNull();
    BytecodeBlock block = new BytecodeBlock().comment("is null").append(value).pop(argument.getType().getJavaType()).append(wasNull);
    // clear the null flag
    block.append(wasNull.set(constantFalse()));
    return block;
}
Also used : Variable(com.facebook.presto.bytecode.Variable) BytecodeBlock(com.facebook.presto.bytecode.BytecodeBlock) RowExpression(com.facebook.presto.sql.relational.RowExpression) BytecodeNode(com.facebook.presto.bytecode.BytecodeNode)

Aggregations

RowExpression (com.facebook.presto.sql.relational.RowExpression)29 Signature (com.facebook.presto.metadata.Signature)12 CallExpression (com.facebook.presto.sql.relational.CallExpression)12 ConstantExpression (com.facebook.presto.sql.relational.ConstantExpression)12 Test (org.testng.annotations.Test)9 BytecodeBlock (com.facebook.presto.bytecode.BytecodeBlock)8 Type (com.facebook.presto.spi.type.Type)8 BytecodeNode (com.facebook.presto.bytecode.BytecodeNode)7 ArrayList (java.util.ArrayList)7 Variable (com.facebook.presto.bytecode.Variable)6 MethodDefinition (com.facebook.presto.bytecode.MethodDefinition)5 Parameter (com.facebook.presto.bytecode.Parameter)5 Scope (com.facebook.presto.bytecode.Scope)5 IfStatement (com.facebook.presto.bytecode.control.IfStatement)5 ImmutableList (com.google.common.collect.ImmutableList)5 ImmutableMap (com.google.common.collect.ImmutableMap)5 LabelNode (com.facebook.presto.bytecode.instruction.LabelNode)4 FunctionRegistry (com.facebook.presto.metadata.FunctionRegistry)4 TypeSignature.parseTypeSignature (com.facebook.presto.spi.type.TypeSignature.parseTypeSignature)4 LambdaDefinitionExpression (com.facebook.presto.sql.relational.LambdaDefinitionExpression)4