public static SignatureBuilder modulusSignatureBuilder() { TypeSignature decimalLeftSignature = parseTypeSignature("decimal(a_precision, a_scale)", ImmutableSet.of("a_precision", "a_scale")); TypeSignature decimalRightSignature = parseTypeSignature("decimal(b_precision, b_scale)", ImmutableSet.of("b_precision", "b_scale")); TypeSignature decimalResultSignature = parseTypeSignature("decimal(r_precision, r_scale)", ImmutableSet.of("r_precision", "r_scale")); return Signature.builder() .longVariableConstraints( longVariableExpression("r_precision", "min(b_precision - b_scale, a_precision - a_scale) + max(a_scale, b_scale)"), longVariableExpression("r_scale", "max(a_scale, b_scale)")) .argumentTypes(decimalLeftSignature, decimalRightSignature) .returnType(decimalResultSignature); }
private static PolymorphicScalarFunctionBuilder makeBinaryOperatorFunctionBuilder(OperatorType operatorType) { Signature signature = Signature.builder() .kind(SCALAR) .operatorType(operatorType) .argumentTypes(DECIMAL_SIGNATURE, DECIMAL_SIGNATURE) .returnType(parseTypeSignature(BOOLEAN)) .build(); return SqlScalarFunction.builder(DecimalInequalityOperators.class) .signature(signature) .deterministic(true); }
@Test public void testBindDifferentLiteralParameters() { TypeSignature argType = parseTypeSignature("decimal(p,s)", ImmutableSet.of("p", "s")); Signature function = functionSignature() .returnType(parseTypeSignature(StandardTypes.BOOLEAN)) .argumentTypes(argType, argType) .build(); assertThat(function) .boundTo("decimal(2,1)", "decimal(3,1)") .fails(); }
private static SignatureBuilder functionSignature(List<String> arguments, String returnType, List<TypeVariableConstraint> typeVariableConstraints) { ImmutableSet<String> literalParameters = ImmutableSet.of("p", "s", "p1", "s1", "p2", "s2", "p3", "s3"); List<TypeSignature> argumentSignatures = arguments.stream() .map((signature) -> TypeSignature.parseTypeSignature(signature, literalParameters)) .collect(toImmutableList()); return new SignatureBuilder() .returnType(TypeSignature.parseTypeSignature(returnType, literalParameters)) .argumentTypes(argumentSignatures) .typeVariableConstraints(typeVariableConstraints) .kind(SCALAR); }
@Test public void testBindDoubleToBigint() { Signature function = functionSignature() .returnType(parseTypeSignature(StandardTypes.BOOLEAN)) .argumentTypes(parseTypeSignature(StandardTypes.DOUBLE), parseTypeSignature(StandardTypes.DOUBLE)) .build(); assertThat(function) .boundTo("double", "bigint") .withCoercion() .succeeds(); }
@Test public void testBindUnparametrizedVarchar() { Signature function = functionSignature() .returnType(parseTypeSignature("boolean")) .argumentTypes(parseTypeSignature("varchar(x)", ImmutableSet.of("x"))) .build(); assertThat(function) .boundTo("varchar") .produces(new BoundVariables( ImmutableMap.of(), ImmutableMap.of("x", (long) Integer.MAX_VALUE))); }
@Test public void testBindUnknownToConcreteArray() { Signature function = functionSignature() .returnType(parseTypeSignature(StandardTypes.BOOLEAN)) .argumentTypes(parseTypeSignature("array(boolean)")) .build(); assertThat(function) .boundTo("unknown") .withCoercion() .succeeds(); }
@Test public void testBindLiteralForDecimal() { TypeSignature leftType = parseTypeSignature("decimal(p1,s1)", ImmutableSet.of("p1", "s1")); TypeSignature rightType = parseTypeSignature("decimal(p2,s2)", ImmutableSet.of("p2", "s2")); Signature function = functionSignature() .returnType(parseTypeSignature(StandardTypes.BOOLEAN)) .argumentTypes(leftType, rightType) .build(); assertThat(function) .boundTo("decimal(2,1)", "decimal(1,0)") .produces(new BoundVariables( ImmutableMap.of(), ImmutableMap.of( "p1", 2L, "s1", 1L, "p2", 1L, "s2", 0L))); }
@Test public void testMismatchedArgumentCount() { Signature function = functionSignature() .returnType(parseTypeSignature(StandardTypes.BOOLEAN)) .argumentTypes(parseTypeSignature(StandardTypes.BIGINT), parseTypeSignature(StandardTypes.BIGINT)) .build(); assertThat(function) .boundTo("bigint", "bigint", "bigint") .fails(); assertThat(function) .boundTo("bigint") .fails(); }
@Test(expectedExceptions = UnsupportedOperationException.class) public void testNoVariableReuseAcrossTypes() { Set<String> literalParameters = ImmutableSet.of("p1", "p2", "s"); TypeSignature leftType = parseTypeSignature("decimal(p1,s)", literalParameters); TypeSignature rightType = parseTypeSignature("decimal(p2,s)", literalParameters); Signature function = functionSignature() .returnType(BOOLEAN.getTypeSignature()) .argumentTypes(leftType, rightType) .build(); assertThat(function) .boundTo("decimal(2,1)", "decimal(3,1)") .produces(new BoundVariables( ImmutableMap.of(), ImmutableMap.of())); }
@Test public void testBindUnknownToDecimal() { Signature function = functionSignature() .returnType(parseTypeSignature("boolean")) .argumentTypes(parseTypeSignature("decimal(p,s)", ImmutableSet.of("p", "s"))) .build(); assertThat(function) .boundTo("unknown") .withCoercion() .produces(new BoundVariables( ImmutableMap.of(), ImmutableMap.of( "p", 1L, "s", 0L))); }
@Test public void testBindUnknown() { Signature function = functionSignature() .returnType(parseTypeSignature(StandardTypes.BOOLEAN)) .argumentTypes(parseTypeSignature("varchar(x)", ImmutableSet.of("x"))) .build(); assertThat(function) .boundTo("unknown") .fails(); assertThat(function) .boundTo("unknown") .withCoercion() .succeeds(); }
private static SqlScalarFunction decimalMultiplyOperator() { TypeSignature decimalLeftSignature = parseTypeSignature("decimal(a_precision, a_scale)", ImmutableSet.of("a_precision", "a_scale")); TypeSignature decimalRightSignature = parseTypeSignature("decimal(b_precision, b_scale)", ImmutableSet.of("b_precision", "b_scale")); TypeSignature decimalResultSignature = parseTypeSignature("decimal(r_precision, r_scale)", ImmutableSet.of("r_precision", "r_scale")); Signature signature = Signature.builder() .kind(SCALAR) .operatorType(MULTIPLY) .longVariableConstraints( longVariableExpression("r_precision", "min(38, a_precision + b_precision)"), longVariableExpression("r_scale", "a_scale + b_scale")) .argumentTypes(decimalLeftSignature, decimalRightSignature) .returnType(decimalResultSignature) .build(); return SqlScalarFunction.builder(DecimalOperators.class) .signature(signature) .deterministic(true) .choice(choice -> choice .implementation(methodsGroup -> methodsGroup .methods("multiplyShortShortShort", "multiplyShortShortLong", "multiplyLongLongLong", "multiplyShortLongLong", "multiplyLongShortLong"))) .build(); }
@Test public void testBindTypeVariablesBasedOnTheSecondArgument() { Signature function = functionSignature() .returnType(parseTypeSignature("T")) .argumentTypes(parseTypeSignature("array(T)"), parseTypeSignature("T")) .typeVariableConstraints(ImmutableList.of(typeVariable("T"))) .build(); assertThat(function) .boundTo("unknown", "decimal(2,1)") .withCoercion() .produces(new BoundVariables( ImmutableMap.of("T", type("decimal(2,1)")), ImmutableMap.of())); }
@Test public void testBindUnknownToTypeParameter() { Signature function = functionSignature() .returnType(parseTypeSignature("T")) .argumentTypes(parseTypeSignature("T")) .typeVariableConstraints(ImmutableList.of(typeVariable("T"))) .build(); assertThat(function) .boundTo("unknown") .withCoercion() .produces(new BoundVariables( ImmutableMap.of("T", type("unknown")), ImmutableMap.of())); }
private static SqlScalarFunction genericIntegerTypeToDecimalSaturatedFloorCast(Type integerType) { return SqlScalarFunction.builder(DecimalSaturatedFloorCasts.class) .signature(Signature.builder() .kind(SCALAR) .operatorType(SATURATED_FLOOR_CAST) .argumentTypes(integerType.getTypeSignature()) .returnType(parseTypeSignature("decimal(result_precision,result_scale)", ImmutableSet.of("result_precision", "result_scale"))) .build()) .deterministic(true) .choice(choice -> choice .implementation(methodsGroup -> methodsGroup .methods("genericIntegerTypeToShortDecimal", "genericIntegerTypeToLongDecimal") .withExtraParameters((context) -> { int resultPrecision = toIntExact(context.getLiteral("result_precision")); int resultScale = toIntExact(context.getLiteral("result_scale")); return ImmutableList.of(resultPrecision, resultScale); }))) .build(); }
private static SqlScalarFunction decimalToGenericIntegerTypeSaturatedFloorCast(Type type, long minValue, long maxValue) { return SqlScalarFunction.builder(DecimalSaturatedFloorCasts.class) .signature(Signature.builder() .kind(SCALAR) .operatorType(SATURATED_FLOOR_CAST) .argumentTypes(parseTypeSignature("decimal(source_precision,source_scale)", ImmutableSet.of("source_precision", "source_scale"))) .returnType(type.getTypeSignature()) .build()) .deterministic(true) .choice(choice -> choice .implementation(methodsGroup -> methodsGroup .methods("shortDecimalToGenericIntegerType", "longDecimalToGenericIntegerType") .withExtraParameters((context) -> { int sourceScale = toIntExact(context.getLiteral("source_scale")); return ImmutableList.of(sourceScale, minValue, maxValue); }))) .build(); }
@Test public void testBindMixedLiteralAndTypeVariables() { Signature function = functionSignature() .returnType(parseTypeSignature(StandardTypes.BOOLEAN)) .typeVariableConstraints(ImmutableList.of(typeVariable("T"))) .argumentTypes(parseTypeSignature("array(T)"), parseTypeSignature("array(decimal(p,s))", ImmutableSet.of("p", "s"))) .build(); assertThat(function) .boundTo("array(decimal(2,1))", "array(decimal(3,1))") .withCoercion() .produces(new BoundVariables( ImmutableMap.of( "T", type("decimal(2,1)")), ImmutableMap.of( "p", 3L, "s", 1L))); }
@Test public void testBindToUnparametrizedVarcharIsImpossible() { Signature function = functionSignature() .returnType(parseTypeSignature("boolean")) .argumentTypes(parseTypeSignature("varchar")) .build(); assertThat(function) .boundTo("varchar(3)") .withCoercion() .succeeds(); assertThat(function) .boundTo("unknown") .withCoercion() .succeeds(); }
private static SqlScalarFunction decimalDivideOperator() { TypeSignature decimalLeftSignature = parseTypeSignature("decimal(a_precision, a_scale)", ImmutableSet.of("a_precision", "a_scale")); TypeSignature decimalRightSignature = parseTypeSignature("decimal(b_precision, b_scale)", ImmutableSet.of("b_precision", "b_scale")); TypeSignature decimalResultSignature = parseTypeSignature("decimal(r_precision, r_scale)", ImmutableSet.of("r_precision", "r_scale")); // we extend target precision by b_scale. This is upper bound on how much division result will grow. // pessimistic case is a / 0.0000001 // if scale of divisor is greater than scale of dividend we extend scale further as we // want result scale to be maximum of scales of divisor and dividend. Signature signature = Signature.builder() .kind(SCALAR) .operatorType(DIVIDE) .longVariableConstraints( longVariableExpression("r_precision", "min(38, a_precision + b_scale + max(b_scale - a_scale, 0))"), longVariableExpression("r_scale", "max(a_scale, b_scale)")) .argumentTypes(decimalLeftSignature, decimalRightSignature) .returnType(decimalResultSignature) .build(); return SqlScalarFunction.builder(DecimalOperators.class) .signature(signature) .deterministic(true) .choice(choice -> choice .implementation(methodsGroup -> methodsGroup .methods("divideShortShortShort", "divideShortLongShort", "divideLongShortShort", "divideShortShortLong", "divideLongLongLong", "divideShortLongLong", "divideLongShortLong") .withExtraParameters(DecimalOperators::divideRescaleFactor))) .build(); }