diff --git a/clients/bigquery/storagewrite_test.go b/clients/bigquery/storagewrite_test.go index 36a8a0c38..7a0c5c073 100644 --- a/clients/bigquery/storagewrite_test.go +++ b/clients/bigquery/storagewrite_test.go @@ -137,9 +137,9 @@ func TestRowToMessage(t *testing.T) { "c_float_int32": int32(1234), "c_float_int64": int64(1234), "c_float_string": "4444.55555", - "c_numeric": decimal.NewDecimal(nil, 5, mustParseDecimal("3.1415926")), + "c_numeric": decimal.NewDecimal(nil, mustParseDecimal("3.14159")), "c_string": "foo bar", - "c_string_decimal": decimal.NewDecimal(nil, 5, mustParseDecimal("1.618033")), + "c_string_decimal": decimal.NewDecimal(nil, mustParseDecimal("1.61803")), "c_time": ext.NewExtendedTime(time.Date(0, 0, 0, 4, 5, 6, 7, time.UTC), ext.TimeKindType, ""), "c_date": ext.NewExtendedTime(time.Date(2001, 2, 3, 0, 0, 0, 0, time.UTC), ext.DateKindType, ""), "c_datetime": ext.NewExtendedTime(time.Date(2001, 2, 3, 4, 5, 6, 7, time.UTC), ext.DateTimeKindType, ""), diff --git a/lib/debezium/types.go b/lib/debezium/types.go index 13917104a..c7af11e9c 100644 --- a/lib/debezium/types.go +++ b/lib/debezium/types.go @@ -237,7 +237,7 @@ func (f Field) DecodeDecimal(encoded []byte) (*decimal.Decimal, error) { return nil, fmt.Errorf("failed to get scale and/or precision: %w", err) } _decimal := DecodeDecimal(encoded, int32(scale)) - return decimal.NewDecimal(precision, scale, _decimal), nil + return decimal.NewDecimal(precision, _decimal), nil } func (f Field) DecodeDebeziumVariableDecimal(value any) (*decimal.Decimal, error) { @@ -261,5 +261,5 @@ func (f Field) DecodeDebeziumVariableDecimal(value any) (*decimal.Decimal, error return nil, err } _decimal := DecodeDecimal(bytes, int32(scale)) - return decimal.NewDecimal(ptr.ToInt(decimal.PrecisionNotSpecified), scale, _decimal), nil + return decimal.NewDecimal(ptr.ToInt(decimal.PrecisionNotSpecified), _decimal), nil } diff --git a/lib/parquetutil/parse_values_test.go b/lib/parquetutil/parse_values_test.go index 7953368b0..5174ddb7d 100644 --- a/lib/parquetutil/parse_values_test.go +++ b/lib/parquetutil/parse_values_test.go @@ -66,7 +66,7 @@ func TestParseValue(t *testing.T) { }, { name: "decimal", - colVal: decimal.NewDecimal(ptr.ToInt(30), 5, numbers.MustParseDecimal("5000.2232")), + colVal: decimal.NewDecimal(ptr.ToInt(30), numbers.MustParseDecimal("5000.22320")), colKind: columns.NewColumn("", eDecimal), expectedValue: "5000.22320", }, diff --git a/lib/typing/decimal/decimal.go b/lib/typing/decimal/decimal.go index 281546a25..06c83b2fa 100644 --- a/lib/typing/decimal/decimal.go +++ b/lib/typing/decimal/decimal.go @@ -1,14 +1,12 @@ package decimal import ( - "github.com/artie-labs/transfer/lib/numbers" "github.com/artie-labs/transfer/lib/ptr" "github.com/cockroachdb/apd/v3" ) // Decimal is Artie's wrapper around [apd.Decimal] which can store large numbers w/ no precision loss. type Decimal struct { - scale int precision *int value *apd.Decimal } @@ -21,7 +19,9 @@ const ( MaxPrecisionBeforeString = 38 ) -func NewDecimal(precision *int, scale int, value *apd.Decimal) *Decimal { +func NewDecimal(precision *int, value *apd.Decimal) *Decimal { + scale := int(-value.Exponent) + if precision != nil { if scale > *precision && *precision != -1 { // Note: -1 precision means it's not specified. @@ -33,14 +33,13 @@ func NewDecimal(precision *int, scale int, value *apd.Decimal) *Decimal { } return &Decimal{ - scale: scale, precision: precision, value: value, } } func (d *Decimal) Scale() int { - return d.scale + return int(-d.value.Exponent) } func (d *Decimal) Precision() *int { @@ -51,14 +50,9 @@ func (d *Decimal) Precision() *int { // This is particularly useful for Snowflake because we're writing all the values as STRINGS into TSV format. // This function guarantees backwards compatibility. func (d *Decimal) String() string { - targetExponent := -int32(d.scale) - value := d.value - if value.Exponent != targetExponent { - value = numbers.DecimalWithNewExponent(value, targetExponent) - } - return value.Text('f') + return d.value.Text('f') } func (d *Decimal) Details() DecimalDetails { - return DecimalDetails{scale: d.scale, precision: d.precision} + return DecimalDetails{scale: d.Scale(), precision: d.precision} } diff --git a/lib/typing/values/string_test.go b/lib/typing/values/string_test.go index 62a7ac9cc..af33186d3 100644 --- a/lib/typing/values/string_test.go +++ b/lib/typing/values/string_test.go @@ -125,7 +125,7 @@ func TestToString(t *testing.T) { // Decimals _decimal, _, err := apd.NewFromString("585692791691858.25") assert.NoError(t, err) - value := decimal.NewDecimal(ptr.ToInt(38), 2, _decimal) + value := decimal.NewDecimal(ptr.ToInt(38), _decimal) val, err = ToString(value, columns.Column{KindDetails: typing.EDecimal}, nil) assert.NoError(t, err) assert.Equal(t, "585692791691858.25", val)