Skip to content

Commit

Permalink
fix: bug preventing decimals in (-1, 1) from being inserted / queried
Browse files Browse the repository at this point in the history
  • Loading branch information
maheshba committed Feb 4, 2022
1 parent 33c81f8 commit 8c2003c
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -274,10 +274,22 @@ public static SqlType fromValue(final BigDecimal value) {
? value.setScale(0, BigDecimal.ROUND_UNNECESSARY)
: value;

/* When a BigDecimal has value 0, the built-in method precision() always returns 1. To account
for this edge case, we just take the scale and add one and use that for the precision instead.
*/
if (decimal.compareTo(BigDecimal.ZERO) == 0) {
/* We can't use BigDecimal.precision() directly for all cases, since it defines
* precision differently from SQL Decimal.
* In particular, if the decimal is between -1 and 1, BigDecimal precision can be
* lower than scale, which is disallowed in SQL Decimal. For example, 0.005 in
* BigDecimal has a (precision, scale) of (1, 3); whereas we expect (4, 3).
* To account for this edge case, we just take the scale and add one and use that
* for the precision instead. This works since BigDecimal defines scale as the
* number of digits to the right of the period; which is one lower than the precision for
* anything in the range (-1, 1).
* This covers the case where BigDecimal has a value of 0.
* Note: This solution differs from the SQL definition in that it returns (4, 3) for
* both "0.005" and ".005", whereas SQL expects (3, 3) for the latter. This is unavoidable
* if we use BigDecimal as an intermediate representation, since the two strings are parsed
* identically by it to have precision 1.
*/
if (decimal.compareTo(BigDecimal.ONE) < 0 && decimal.compareTo(BigDecimal.ONE.negate()) > 0) {
return SqlTypes.decimal(decimal.scale() + 1, decimal.scale());
}
return SqlTypes.decimal(decimal.precision(), Math.max(decimal.scale(), 0));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -355,8 +355,12 @@ public void shouldGetSchemaFromDecimal2_2() {
// When:
final SqlType schema = DecimalUtil.fromValue(new BigDecimal(".12"));

// Note: this behavior is different from the SQL specification, where
// we expect precision = 2, scale = 2. This difference is because we use
// BigDecimal in our implementation, which treats precision differently.

// Then:
assertThat(schema, is(SqlTypes.decimal(2, 2)));
assertThat(schema, is(SqlTypes.decimal(3, 2)));
}

@Test
Expand Down Expand Up @@ -386,6 +390,15 @@ public void shouldGetSchemaFromDecimal10_5() {
assertThat(schema, is(SqlTypes.decimal(10, 5)));
}

@Test
public void shouldGetSchemaFromDecimal4_3() {
// When:
final SqlType schema = DecimalUtil.fromValue(new BigDecimal("0.005"));

// Then:
assertThat(schema, is(SqlTypes.decimal(4, 3)));
}

@Test
public void shouldFailIfBuilderWithZeroPrecision() {
// When:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,18 @@
{"topic": "test_topic", "key": 1, "value": {"V0": 0.00}}
]
},
{
"name": "should insert decimals between zero and one",
"statements": [
"CREATE STREAM S (ID INT KEY, V0 DECIMAL(12, 2)) WITH (kafka_topic='test_topic',partitions = 1, value_format='JSON');",
"INSERT INTO S (ID,V0) VALUES (1,0.05);"
],
"inputs": [
],
"outputs": [
{"topic": "test_topic", "key": 1, "value": {"V0": 0.05}}
]
},
{
"name": "should fail on column reference",
"statements": [
Expand Down

0 comments on commit 8c2003c

Please sign in to comment.