Fix Loss of digits when doing CAST from varint/bigint to decimal

patch by Benjamin Lerer; reviewed by Andrés de la Peña for CASSANDRA-14170
This commit is contained in:
Benjamin Lerer 2018-02-14 12:29:17 +01:00
parent 171222ce05
commit 3fa7c08944
3 changed files with 35 additions and 7 deletions

View File

@ -1,4 +1,5 @@
3.11.3
* Fix Loss of digits when doing CAST from varint/bigint to decimal (CASSANDRA-14170)
* RateBasedBackPressure unnecessarily invokes a lock on the Guava RateLimiter (CASSANDRA-14163)
* Fix wildcard GROUP BY queries (CASSANDRA-14209)
Merged from 3.0:

View File

@ -79,7 +79,7 @@ public final class CastFcts
addFunctionIfNeeded(functions, inputType, LongType.instance, Number::longValue);
addFunctionIfNeeded(functions, inputType, FloatType.instance, Number::floatValue);
addFunctionIfNeeded(functions, inputType, DoubleType.instance, Number::doubleValue);
addFunctionIfNeeded(functions, inputType, DecimalType.instance, p -> BigDecimal.valueOf(p.doubleValue()));
addFunctionIfNeeded(functions, inputType, DecimalType.instance, getDecimalConversionFunction(inputType));
addFunctionIfNeeded(functions, inputType, IntegerType.instance, p -> BigInteger.valueOf(p.longValue()));
functions.add(CastAsTextFunction.create(inputType, AsciiType.instance));
functions.add(CastAsTextFunction.create(inputType, UTF8Type.instance));
@ -112,6 +112,23 @@ public final class CastFcts
return functions;
}
/**
* Returns the conversion function to convert the specified type into a Decimal type
*
* @param inputType the input type
* @return the conversion function to convert the specified type into a Decimal type
*/
private static <I extends Number> java.util.function.Function<I, BigDecimal> getDecimalConversionFunction(AbstractType<? extends Number> inputType)
{
if (inputType == FloatType.instance || inputType == DoubleType.instance)
return p -> BigDecimal.valueOf(p.doubleValue());
if (inputType == IntegerType.instance)
return p -> new BigDecimal((BigInteger) p);
return p -> BigDecimal.valueOf(p.longValue());
}
/**
* Creates the name of the cast function use to cast to the specified type.
*

View File

@ -153,14 +153,14 @@ public class CastFctsTest extends CQLTester
"CAST(g AS decimal), " +
"CAST(h AS decimal), " +
"CAST(i AS decimal) FROM %s"),
row(BigDecimal.valueOf(1.0),
BigDecimal.valueOf(2.0),
BigDecimal.valueOf(3.0),
BigDecimal.valueOf(4.0),
row(BigDecimal.valueOf(1),
BigDecimal.valueOf(2),
BigDecimal.valueOf(3),
BigDecimal.valueOf(4),
BigDecimal.valueOf(5.2F),
BigDecimal.valueOf(6.3),
BigDecimal.valueOf(6.3),
BigDecimal.valueOf(4.0),
BigDecimal.valueOf(4),
null));
assertRows(execute("SELECT CAST(a AS ascii), " +
@ -202,6 +202,16 @@ public class CastFctsTest extends CQLTester
null));
}
@Test
public void testNoLossOfPrecisionForCastToDecimal() throws Throwable
{
createTable("CREATE TABLE %s (k int PRIMARY KEY, bigint_clmn bigint, varint_clmn varint)");
execute("INSERT INTO %s(k, bigint_clmn, varint_clmn) VALUES(2, 9223372036854775807, 1234567890123456789)");
assertRows(execute("SELECT CAST(bigint_clmn AS decimal), CAST(varint_clmn AS decimal) FROM %s"),
row(BigDecimal.valueOf(9223372036854775807L), BigDecimal.valueOf(1234567890123456789L)));
}
@Test
public void testTimeCastsInSelectionClause() throws Throwable
{
@ -309,6 +319,6 @@ public class CastFctsTest extends CQLTester
"CAST(b AS decimal), " +
"CAST(b AS ascii), " +
"CAST(b AS text) FROM %s"),
row((byte) 2, (short) 2, 2, 2L, 2.0F, 2.0, BigDecimal.valueOf(2.0), "2", "2"));
row((byte) 2, (short) 2, 2, 2L, 2.0F, 2.0, BigDecimal.valueOf(2), "2", "2"));
}
}