private Type getOperator( AnalysisContext context, Expression node, OperatorType operatorType, Expression... arguments) { ImmutableList.Builder<Type> argumentTypes = ImmutableList.builder(); for (Expression expression : arguments) { argumentTypes.add(process(expression, context)); } Signature operatorSignature; try { operatorSignature = functionRegistry.resolveOperator(operatorType, argumentTypes.build()); } catch (OperatorNotFoundException e) { throw new SemanticException(TYPE_MISMATCH, node, e.getMessage()); } for (int i = 0; i < arguments.length; i++) { Expression expression = arguments[i]; Type type = typeManager.getType(operatorSignature.getArgumentTypes().get(i)); coerceType( context, expression, type, String.format("Operator %s argument %d", operatorSignature, i)); } Type type = typeManager.getType(operatorSignature.getReturnType()); expressionTypes.put(node, type); return type; }
private ReflectionParametricScalar( Signature signature, String description, boolean hidden, Map<Signature, Implementation> exactImplementations, List<Implementation> specializedImplementations, List<Implementation> implementations, boolean deterministic) { super( signature.getName(), signature.getTypeParameterRequirements(), signature.getReturnType().toString(), signature .getArgumentTypes() .stream() .map(TypeSignature::toString) .collect(toImmutableList())); this.description = description; this.hidden = hidden; this.exactImplementations = ImmutableMap.copyOf(requireNonNull(exactImplementations, "exactImplementations is null")); this.specializedImplementations = ImmutableList.copyOf( requireNonNull(specializedImplementations, "specializedImplementations is null")); this.implementations = ImmutableList.copyOf(requireNonNull(implementations, "implementations is null")); this.deterministic = deterministic; }
public MethodHandleAndConstructor specialize( Signature boundSignature, Map<String, Type> boundTypeParameters, TypeManager typeManager, FunctionRegistry functionRegistry) { for (Map.Entry<String, Class<?>> entry : specializedTypeParameters.entrySet()) { if (!entry .getValue() .isAssignableFrom(boundTypeParameters.get(entry.getKey()).getJavaType())) { return null; } } Class<?> returnContainerType = getNullAwareContainerType( typeManager.getType(boundSignature.getReturnType()).getJavaType(), nullable); if (!returnContainerType.equals(methodHandle.type().returnType())) { return null; } for (int i = 0; i < boundSignature.getArgumentTypes().size(); i++) { Class<?> argumentContainerType = getNullAwareContainerType( typeManager.getType(boundSignature.getArgumentTypes().get(i)).getJavaType(), nullableArguments.get(i)); if (!argumentNativeContainerTypes.get(i).isAssignableFrom(argumentContainerType)) { return null; } } MethodHandle methodHandle = this.methodHandle; for (ImplementationDependency dependency : dependencies) { methodHandle = methodHandle.bindTo( dependency.resolve(boundTypeParameters, typeManager, functionRegistry)); } MethodHandle constructor = null; if (this.constructor.isPresent()) { constructor = this.constructor.get(); for (ImplementationDependency dependency : constructorDependencies) { constructor = constructor.bindTo( dependency.resolve(boundTypeParameters, typeManager, functionRegistry)); } } return new MethodHandleAndConstructor(methodHandle, Optional.ofNullable(constructor)); }
public static Expression toExpression(Object object, Type type) { requireNonNull(type, "type is null"); if (object instanceof Expression) { return (Expression) object; } if (object == null) { if (type.equals(UNKNOWN)) { return new NullLiteral(); } return new Cast(new NullLiteral(), type.getTypeSignature().toString(), false, true); } checkArgument( Primitives.wrap(type.getJavaType()).isInstance(object), "object.getClass (%s) and type.getJavaType (%s) do not agree", object.getClass(), type.getJavaType()); if (type.equals(BIGINT)) { return new LongLiteral(object.toString()); } if (type.equals(DOUBLE)) { Double value = (Double) object; // WARNING: the ORC predicate code depends on NaN and infinity not appearing in a tuple // domain, so // if you remove this, you will need to update the TupleDomainOrcPredicate if (value.isNaN()) { return new FunctionCall(new QualifiedName("nan"), ImmutableList.<Expression>of()); } else if (value.equals(Double.NEGATIVE_INFINITY)) { return ArithmeticUnaryExpression.negative( new FunctionCall(new QualifiedName("infinity"), ImmutableList.<Expression>of())); } else if (value.equals(Double.POSITIVE_INFINITY)) { return new FunctionCall(new QualifiedName("infinity"), ImmutableList.<Expression>of()); } else { return new DoubleLiteral(object.toString()); } } if (type instanceof VarcharType) { if (object instanceof String) { object = Slices.utf8Slice((String) object); } if (object instanceof Slice) { Slice value = (Slice) object; int length = SliceUtf8.countCodePoints(value); if (length == ((VarcharType) type).getLength()) { return new StringLiteral(value.toStringUtf8()); } return new Cast( new StringLiteral(value.toStringUtf8()), type.getDisplayName(), false, true); } throw new IllegalArgumentException( "object must be instance of Slice or String when type is VARCHAR"); } if (type.equals(BOOLEAN)) { return new BooleanLiteral(object.toString()); } if (object instanceof Block) { SliceOutput output = new DynamicSliceOutput(((Block) object).getSizeInBytes()); BlockSerdeUtil.writeBlock(output, (Block) object); object = output.slice(); // This if condition will evaluate to true: object instanceof Slice && !type.equals(VARCHAR) } if (object instanceof Slice) { // HACK: we need to serialize VARBINARY in a format that can be embedded in an expression to // be // able to encode it in the plan that gets sent to workers. // We do this by transforming the in-memory varbinary into a call to // from_base64(<base64-encoded value>) FunctionCall fromBase64 = new FunctionCall( new QualifiedName("from_base64"), ImmutableList.of( new StringLiteral(VarbinaryFunctions.toBase64((Slice) object).toStringUtf8()))); Signature signature = FunctionRegistry.getMagicLiteralFunctionSignature(type); return new FunctionCall(new QualifiedName(signature.getName()), ImmutableList.of(fromBase64)); } Signature signature = FunctionRegistry.getMagicLiteralFunctionSignature(type); Expression rawLiteral = toExpression(object, FunctionRegistry.typeForMagicLiteral(type)); return new FunctionCall(new QualifiedName(signature.getName()), ImmutableList.of(rawLiteral)); }
@Override protected Type visitFunctionCall(FunctionCall node, AnalysisContext context) { if (node.getWindow().isPresent()) { for (Expression expression : node.getWindow().get().getPartitionBy()) { process(expression, context); Type type = expressionTypes.get(expression); if (!type.isComparable()) { throw new SemanticException( TYPE_MISMATCH, node, "%s is not comparable, and therefore cannot be used in window function PARTITION BY", type); } } for (SortItem sortItem : node.getWindow().get().getOrderBy()) { process(sortItem.getSortKey(), context); Type type = expressionTypes.get(sortItem.getSortKey()); if (!type.isOrderable()) { throw new SemanticException( TYPE_MISMATCH, node, "%s is not orderable, and therefore cannot be used in window function ORDER BY", type); } } if (node.getWindow().get().getFrame().isPresent()) { WindowFrame frame = node.getWindow().get().getFrame().get(); if (frame.getStart().getValue().isPresent()) { Type type = process(frame.getStart().getValue().get(), context); if (!type.equals(BIGINT)) { throw new SemanticException( TYPE_MISMATCH, node, "Window frame start value type must be BIGINT (actual %s)", type); } } if (frame.getEnd().isPresent() && frame.getEnd().get().getValue().isPresent()) { Type type = process(frame.getEnd().get().getValue().get(), context); if (!type.equals(BIGINT)) { throw new SemanticException( TYPE_MISMATCH, node, "Window frame end value type must be BIGINT (actual %s)", type); } } } } ImmutableList.Builder<TypeSignature> argumentTypes = ImmutableList.builder(); for (Expression expression : node.getArguments()) { argumentTypes.add(process(expression, context).getTypeSignature()); } Signature function = functionRegistry.resolveFunction( node.getName(), argumentTypes.build(), context.isApproximate()); for (int i = 0; i < node.getArguments().size(); i++) { Expression expression = node.getArguments().get(i); Type type = typeManager.getType(function.getArgumentTypes().get(i)); requireNonNull(type, format("Type %s not found", function.getArgumentTypes().get(i))); if (node.isDistinct() && !type.isComparable()) { throw new SemanticException( TYPE_MISMATCH, node, "DISTINCT can only be applied to comparable types (actual: %s)", type); } coerceType( context, expression, type, String.format("Function %s argument %d", function, i)); } resolvedFunctions.put(node, function); Type type = typeManager.getType(function.getReturnType()); expressionTypes.put(node, type); return type; }