private LongStrategy(FunctionRegistry registry, Type type) { hashCodeHandle = registry.getScalarFunctionImplementation(registry.resolveOperator(HASH_CODE, ImmutableList.of(type))).getMethodHandle(); equalsHandle = registry.getScalarFunctionImplementation(registry.resolveOperator(EQUAL, ImmutableList.of(type, type))).getMethodHandle(); }
protected List<MethodHandle> getMethodHandles(RowType type, FunctionRegistry functionRegistry, OperatorType operatorType) { ImmutableList.Builder<MethodHandle> argumentMethods = ImmutableList.builder(); for (Type parameterType : type.getTypeParameters()) { Signature signature = functionRegistry.resolveOperator(operatorType, ImmutableList.of(parameterType, parameterType)); argumentMethods.add(functionRegistry.getScalarFunctionImplementation(signature).getMethodHandle()); } return argumentMethods.build(); }
@Override public MethodHandle resolveOperator(OperatorType operatorType, List<? extends Type> argumentTypes) { requireNonNull(functionRegistry, "functionRegistry is null"); return functionRegistry.getScalarFunctionImplementation(functionRegistry.resolveOperator(operatorType, argumentTypes)).getMethodHandle(); }
private DoubleStrategy(FunctionRegistry registry, Type type) { hashCodeHandle = registry.getScalarFunctionImplementation(registry.resolveOperator(HASH_CODE, ImmutableList.of(type))).getMethodHandle(); equalsHandle = registry.getScalarFunctionImplementation(registry.resolveOperator(EQUAL, ImmutableList.of(type, type))).getMethodHandle(); }
private static MethodHandle resolveEqualOperator(Type type, FunctionRegistry functionRegistry) { Signature operator = functionRegistry.resolveOperator(EQUAL, ImmutableList.of(type, type)); ScalarFunctionImplementation implementation = functionRegistry.getScalarFunctionImplementation(operator); return implementation.getMethodHandle(); }
private ObjectStrategy(FunctionRegistry registry, Type type) { hashCodeHandle = registry.getScalarFunctionImplementation(registry.resolveOperator(HASH_CODE, ImmutableList.of(type))) .getMethodHandle() .asType(MethodType.methodType(long.class, Object.class)); equalsHandle = registry.getScalarFunctionImplementation(registry.resolveOperator(EQUAL, ImmutableList.of(type, type))) .getMethodHandle() .asType(MethodType.methodType(Boolean.class, Object.class, Object.class)); }
public FieldSetFilteringRecordSet(FunctionRegistry functionRegistry, RecordSet delegate, List<Set<Integer>> fieldSets) { requireNonNull(functionRegistry, "functionRegistry is null"); this.delegate = requireNonNull(delegate, "delegate is null"); ImmutableList.Builder<Set<Field>> fieldSetsBuilder = ImmutableList.builder(); List<Type> columnTypes = delegate.getColumnTypes(); for (Set<Integer> fieldSet : requireNonNull(fieldSets, "fieldSets is null")) { ImmutableSet.Builder<Field> fieldSetBuilder = ImmutableSet.builder(); for (int field : fieldSet) { fieldSetBuilder.add(new Field( field, functionRegistry.getScalarFunctionImplementation(internalOperator(OperatorType.EQUAL, BooleanType.BOOLEAN, ImmutableList.of(columnTypes.get(field), columnTypes.get(field)))).getMethodHandle())); } fieldSetsBuilder.add(fieldSetBuilder.build()); } this.fieldSets = fieldSetsBuilder.build(); }
@Override public Boolean visitCall(CallExpression call, Void context) { Signature signature = call.getSignature(); if (registry.isRegistered(signature) && !registry.getScalarFunctionImplementation(signature).isDeterministic()) { return false; } return call.getArguments().stream() .allMatch(expression -> expression.accept(this, context)); }
private boolean returnsNullOnGivenInputTypes(ApplicableFunction applicableFunction, List<Type> parameterTypes) { Signature boundSignature = applicableFunction.getBoundSignature(); FunctionKind functionKind = boundSignature.getKind(); // Window and Aggregation functions have fixed semantic where NULL values are always skipped if (functionKind != SCALAR) { return true; } for (int i = 0; i < parameterTypes.size(); i++) { Type parameterType = parameterTypes.get(i); if (parameterType.equals(UNKNOWN)) { // TODO: Move information about nullable arguments to FunctionSignature. Remove this hack. ScalarFunctionImplementation implementation = getScalarFunctionImplementation(boundSignature); if (implementation.getArgumentProperty(i).getNullConvention() != RETURN_NULL_ON_NULL) { return false; } } } return true; }
@Override public InternalAggregationFunction specialize(BoundVariables boundVariables, int arity, TypeManager typeManager, FunctionRegistry functionRegistry) { Type type = boundVariables.getTypeVariable("E"); MethodHandle compareMethodHandle = functionRegistry.getScalarFunctionImplementation(internalOperator(operatorType, BOOLEAN, ImmutableList.of(type, type))).getMethodHandle(); return generateAggregation(type, compareMethodHandle); }
@Override public MethodHandle resolve(BoundVariables boundVariables, TypeManager typeManager, FunctionRegistry functionRegistry) { Signature signature = applyBoundVariables(this.signature, boundVariables, this.signature.getArgumentTypes().size()); if (invocationConvention.isPresent()) { return functionRegistry.getFunctionInvokerProvider().createFunctionInvoker(signature, invocationConvention).methodHandle(); } else { return functionRegistry.getScalarFunctionImplementation(signature).getMethodHandle(); } }
@Override public ScalarFunctionImplementation specialize(BoundVariables boundVariables, int arity, TypeManager typeManager, FunctionRegistry functionRegistry) { Type type = boundVariables.getTypeVariable("E"); checkArgument(type.isOrderable(), "Type must be orderable"); MethodHandle compareMethod = functionRegistry.getScalarFunctionImplementation(internalOperator(operatorType, BOOLEAN, ImmutableList.of(type, type))).getMethodHandle(); List<Class<?>> javaTypes = IntStream.range(0, arity) .mapToObj(i -> type.getJavaType()) .collect(toImmutableList()); Class<?> clazz = generate(javaTypes, type, compareMethod); MethodHandle methodHandle = methodHandle(clazz, getSignature().getName(), javaTypes.toArray(new Class<?>[javaTypes.size()])); return new ScalarFunctionImplementation( false, nCopies(javaTypes.size(), valueTypeArgumentProperty(RETURN_NULL_ON_NULL)), methodHandle, isDeterministic()); }
public FunctionInvoker createFunctionInvoker(Signature signature, Optional<InvocationConvention> invocationConvention) { ScalarFunctionImplementation scalarFunctionImplementation = functionRegistry.getScalarFunctionImplementation(signature); for (ScalarImplementationChoice choice : scalarFunctionImplementation.getAllChoices()) { if (checkChoice(choice.getArgumentProperties(), choice.isNullable(), choice.hasSession(), invocationConvention)) { return new FunctionInvoker(choice.getMethodHandle()); } } checkState(invocationConvention.isPresent()); throw new PrestoException(FUNCTION_NOT_FOUND, format("Dependent function implementation (%s) with convention (%s) is not available", signature, invocationConvention.toString())); }
public Signature getCoercion(TypeSignature fromType, TypeSignature toType) { Signature signature = internalOperator(OperatorType.CAST.name(), toType, ImmutableList.of(fromType)); try { getScalarFunctionImplementation(signature); } catch (PrestoException e) { if (e.getErrorCode().getCode() == FUNCTION_IMPLEMENTATION_MISSING.toErrorCode().getCode()) { throw new OperatorNotFoundException(OperatorType.CAST, ImmutableList.of(fromType), toType); } throw e; } return signature; }
@Override public ScalarFunctionImplementation specialize(BoundVariables boundVariables, int arity, TypeManager typeManager, FunctionRegistry functionRegistry) { Type keyType = boundVariables.getTypeVariable("K"); Type valueType = boundVariables.getTypeVariable("V"); MethodHandle keyHashCodeFunction = functionRegistry.getScalarFunctionImplementation(internalOperator(HASH_CODE, BIGINT, ImmutableList.of(keyType))).getMethodHandle(); MethodHandle valueHashCodeFunction = functionRegistry.getScalarFunctionImplementation(internalOperator(HASH_CODE, BIGINT, ImmutableList.of(valueType))).getMethodHandle(); MethodHandle method = METHOD_HANDLE.bindTo(keyHashCodeFunction).bindTo(valueHashCodeFunction).bindTo(keyType).bindTo(valueType); return new ScalarFunctionImplementation( false, ImmutableList.of(valueTypeArgumentProperty(RETURN_NULL_ON_NULL)), method, isDeterministic()); }
public boolean isRegistered(Signature signature) { try { // TODO: this is hacky, but until the magic literal and row field reference hacks are cleaned up it's difficult to implement this. getScalarFunctionImplementation(signature); return true; } catch (PrestoException e) { if (e.getErrorCode().getCode() == FUNCTION_IMPLEMENTATION_MISSING.toErrorCode().getCode()) { return false; } throw e; } }
@Override public BytecodeNode generateExpression(Signature signature, BytecodeGeneratorContext generatorContext, Type returnType, List<RowExpression> arguments, Optional<Variable> outputBlockVariable) { RowExpression argument = arguments.get(0); Signature function = generatorContext .getRegistry() .getCoercion(argument.getType(), returnType); BytecodeBlock block = new BytecodeBlock() .append(generatorContext.generateCall( function.getName(), generatorContext.getRegistry().getScalarFunctionImplementation(function), ImmutableList.of(generatorContext.generate(argument, Optional.empty())))); outputBlockVariable.ifPresent(output -> block.append(generateWrite(generatorContext, returnType, output))); return block; } }
@Override public ScalarFunctionImplementation specialize(BoundVariables boundVariables, int arity, TypeManager typeManager, FunctionRegistry functionRegistry) { Type keyType = boundVariables.getTypeVariable("K"); Type valueType = boundVariables.getTypeVariable("V"); Type mapType = typeManager.getParameterizedType(MAP, ImmutableList.of(TypeSignatureParameter.of(keyType.getTypeSignature()), TypeSignatureParameter.of(valueType.getTypeSignature()))); MethodHandle keyHashCode = functionRegistry.getScalarFunctionImplementation(functionRegistry.resolveOperator(OperatorType.HASH_CODE, ImmutableList.of(keyType))).getMethodHandle(); MethodHandle keyEqual = functionRegistry.getScalarFunctionImplementation(functionRegistry.resolveOperator(OperatorType.EQUAL, ImmutableList.of(keyType, keyType))).getMethodHandle(); MethodHandle keyIndeterminate = functionRegistry.getScalarFunctionImplementation(internalOperator(INDETERMINATE.name(), BOOLEAN.getTypeSignature(), ImmutableList.of(keyType.getTypeSignature()))).getMethodHandle(); MethodHandle instanceFactory = constructorMethodHandle(State.class, MapType.class).bindTo(mapType); return new ScalarFunctionImplementation( false, ImmutableList.of( valueTypeArgumentProperty(RETURN_NULL_ON_NULL), valueTypeArgumentProperty(RETURN_NULL_ON_NULL)), METHOD_HANDLE.bindTo(mapType).bindTo(keyEqual).bindTo(keyHashCode).bindTo(keyIndeterminate), Optional.of(instanceFactory), isDeterministic()); }
private static BytecodeNode cast( BytecodeGeneratorContext generatorContext, BytecodeNode argument, Type actualType, TypeSignature requiredType) { if (actualType.getTypeSignature().equals(requiredType)) { return argument; } Signature function = generatorContext .getRegistry() .getCoercion(actualType.getTypeSignature(), requiredType); // TODO: do we need a full function call? (nullability checks, etc) return generatorContext.generateCall(function.getName(), generatorContext.getRegistry().getScalarFunctionImplementation(function), ImmutableList.of(argument)); } }
@Override public ScalarFunctionImplementation specialize(BoundVariables boundVariables, int arity, TypeManager typeManager, FunctionRegistry functionRegistry) { Type fromType = boundVariables.getTypeVariable("F"); Type toType = boundVariables.getTypeVariable("T"); Class<?> returnType = Primitives.wrap(toType.getJavaType()); List<ArgumentProperty> argumentProperties; MethodHandle tryCastHandle; // the resulting method needs to return a boxed type Signature signature = functionRegistry.getCoercion(fromType, toType); ScalarFunctionImplementation implementation = functionRegistry.getScalarFunctionImplementation(signature); argumentProperties = ImmutableList.of(implementation.getArgumentProperty(0)); MethodHandle coercion = implementation.getMethodHandle(); coercion = coercion.asType(methodType(returnType, coercion.type())); MethodHandle exceptionHandler = dropArguments(constant(returnType, null), 0, RuntimeException.class); tryCastHandle = catchException(coercion, RuntimeException.class, exceptionHandler); return new ScalarFunctionImplementation(true, argumentProperties, tryCastHandle, isDeterministic()); } }