From b7f5f96eb8eae9f78f4c092d9dfdfd7585971d01 Mon Sep 17 00:00:00 2001
From: Nathan <148575555+nathan-artie@users.noreply.github.com>
Date: Thu, 27 Jun 2024 14:37:43 -0700
Subject: [PATCH] [typing] Clean up `NewDecimalWithPrecision` (#778)

---
 lib/debezium/types_test.go         |  8 ++++----
 lib/typing/decimal/decimal.go      | 29 +++--------------------------
 lib/typing/decimal/decimal_test.go | 10 ----------
 lib/typing/decimal/details.go      |  7 +++++++
 4 files changed, 14 insertions(+), 40 deletions(-)

diff --git a/lib/debezium/types_test.go b/lib/debezium/types_test.go
index 8dfdcbcfa..61d9f7550 100644
--- a/lib/debezium/types_test.go
+++ b/lib/debezium/types_test.go
@@ -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)
 	}
 }
 
@@ -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)
 	}
 
diff --git a/lib/typing/decimal/decimal.go b/lib/typing/decimal/decimal.go
index c220c353b..cefa1617f 100644
--- a/lib/typing/decimal/decimal.go
+++ b/lib/typing/decimal/decimal.go
@@ -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,
@@ -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
 }
@@ -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)
 }
diff --git a/lib/typing/decimal/decimal_test.go b/lib/typing/decimal/decimal_test.go
index 2fc86aa60..78c4dae33 100644
--- a/lib/typing/decimal/decimal_test.go
+++ b/lib/typing/decimal/decimal_test.go
@@ -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())
diff --git a/lib/typing/decimal/details.go b/lib/typing/decimal/details.go
index 688046866..dd348c9b6 100644
--- a/lib/typing/decimal/details.go
+++ b/lib/typing/decimal/details.go
@@ -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