Skip to content

Commit

Permalink
[typing] Clean up NewDecimalWithPrecision (#778)
Browse files Browse the repository at this point in the history
  • Loading branch information
nathan-artie authored Jun 27, 2024
1 parent 0e51830 commit b7f5f96
Show file tree
Hide file tree
Showing 4 changed files with 14 additions and 40 deletions.
8 changes: 4 additions & 4 deletions lib/debezium/types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -609,8 +609,8 @@ func TestField_DecodeDecimal(t *testing.T) {
assert.NoError(t, err)
assert.Equal(t, testCase.expectedValue, dec.String(), testCase.name)

assert.Equal(t, testCase.expectedPrecision, dec.Precision(), testCase.name)
assert.Equal(t, testCase.expectedScale, dec.Scale(), testCase.name)
assert.Equal(t, testCase.expectedPrecision, dec.Details().Precision(), testCase.name)
assert.Equal(t, testCase.expectedScale, dec.Details().Scale(), testCase.name)
}
}

Expand Down Expand Up @@ -695,8 +695,8 @@ func TestField_DecodeDebeziumVariableDecimal(t *testing.T) {
continue
}

assert.Equal(t, int32(-1), dec.Precision(), testCase.name)
assert.Equal(t, testCase.expectedScale, dec.Scale(), testCase.name)
assert.Equal(t, int32(-1), dec.Details().Precision(), testCase.name)
assert.Equal(t, testCase.expectedScale, dec.Details().Scale(), testCase.name)
assert.Equal(t, testCase.expectedValue, dec.String(), testCase.name)
}

Expand Down
29 changes: 3 additions & 26 deletions lib/typing/decimal/decimal.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,15 @@ import (
"github.com/cockroachdb/apd/v3"
)

const PrecisionNotSpecified int32 = -1

// Decimal is Artie's wrapper around [*apd.Decimal] which can store large numbers w/ no precision loss.
type Decimal struct {
precision int32
value *apd.Decimal
}

const (
DefaultScale int32 = 5
PrecisionNotSpecified int32 = -1
// MaxPrecisionBeforeString - if the precision is greater than 38, we'll cast it as a string.
// This is because Snowflake and BigQuery both do not have NUMERIC data types that go beyond 38.
MaxPrecisionBeforeString int32 = 38
)

func NewDecimalWithPrecision(value *apd.Decimal, precision int32) *Decimal {
scale := -value.Exponent
if scale > precision && precision != PrecisionNotSpecified {
// Note: -1 precision means it's not specified.

// This is typically not possible, but Postgres has a design flaw that allows you to do things like: NUMERIC(5, 6) which actually equates to NUMERIC(7, 6)
// We are setting precision to be scale + 1 to account for the leading zero for decimal numbers.
precision = scale + 1
}

return &Decimal{
precision: precision,
value: value,
Expand All @@ -38,14 +23,6 @@ func NewDecimal(value *apd.Decimal) *Decimal {
return NewDecimalWithPrecision(value, PrecisionNotSpecified)
}

func (d *Decimal) Scale() int32 {
return -d.value.Exponent
}

func (d *Decimal) Precision() int32 {
return d.precision
}

func (d *Decimal) Value() *apd.Decimal {
return d.value
}
Expand All @@ -58,5 +35,5 @@ func (d *Decimal) String() string {
}

func (d *Decimal) Details() Details {
return Details{scale: d.Scale(), precision: d.precision}
return NewDetails(d.precision, -d.value.Exponent)
}
10 changes: 0 additions & 10 deletions lib/typing/decimal/decimal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,6 @@ func TestNewDecimalWithPrecision(t *testing.T) {
assert.Equal(t, Details{scale: 2, precision: 4}, NewDecimalWithPrecision(numbers.MustParseDecimal("12.34"), 4).Details())
}

func TestDecimal_Scale(t *testing.T) {
assert.Equal(t, int32(0), NewDecimal(numbers.MustParseDecimal("0")).Scale())
assert.Equal(t, int32(0), NewDecimal(numbers.MustParseDecimal("12345")).Scale())
assert.Equal(t, int32(0), NewDecimal(numbers.MustParseDecimal("12300")).Scale())
assert.Equal(t, int32(1), NewDecimal(numbers.MustParseDecimal("12300.0")).Scale())
assert.Equal(t, int32(2), NewDecimal(numbers.MustParseDecimal("12300.00")).Scale())
assert.Equal(t, int32(2), NewDecimal(numbers.MustParseDecimal("12345.12")).Scale())
assert.Equal(t, int32(3), NewDecimal(numbers.MustParseDecimal("-12345.123")).Scale())
}

func TestDecimal_Details(t *testing.T) {
// -1 precision (PrecisionNotSpecified):
assert.Equal(t, Details{scale: 0, precision: -1}, NewDecimal(numbers.MustParseDecimal("0")).Details())
Expand Down
7 changes: 7 additions & 0 deletions lib/typing/decimal/details.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ import (
"fmt"
)

const (
DefaultScale int32 = 5
// MaxPrecisionBeforeString - if the precision is greater than 38, we'll cast it as a string.
// This is because Snowflake and BigQuery both do not have NUMERIC data types that go beyond 38.
MaxPrecisionBeforeString int32 = 38
)

type Details struct {
scale int32
precision int32
Expand Down

0 comments on commit b7f5f96

Please sign in to comment.