Skip to content

Commit

Permalink
[go] Fix bug with encoding negative decimal numbers
Browse files Browse the repository at this point in the history
  • Loading branch information
nathan-artie committed Jun 24, 2024
1 parent aa2902e commit fbba141
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 3 deletions.
10 changes: 7 additions & 3 deletions lib/debezium/decimal.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package debezium
import (
"fmt"
"math/big"
"slices"

"github.com/artie-labs/transfer/lib/typing/decimal"
)
Expand All @@ -23,11 +24,14 @@ func EncodeDecimal(value string, scale uint16) ([]byte, error) {
return nil, fmt.Errorf("unable to use %q as a floating-point number", value)
}

data := bigIntValue.Bytes()
data := bigIntValue.Bytes() // [Bytes] returns the absolute value of the number.
if bigIntValue.Sign() < 0 {
// Convert to two's complement if the number is negative
bigIntValue = bigIntValue.Neg(bigIntValue)
data = bigIntValue.Bytes()

if data[0] > 127 {
// Prepend an empty byte if the first bit is already set.
data = slices.Concat([]byte{0}, data)
}

// Inverting bits for two's complement.
for i := range data {
Expand Down
27 changes: 27 additions & 0 deletions lib/debezium/decimal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,23 @@ import (
"github.com/stretchr/testify/assert"
)

func encodeDecode(value string, scale uint16) (string, error) {

Check failure on line 9 in lib/debezium/decimal_test.go

View workflow job for this annotation

GitHub Actions / test

func encodeDecode is unused (U1000)
bytes, err := EncodeDecimal(value, scale)
if err != nil {
return "", err
}
return DecodeDecimal(bytes, nil, int(scale)).String(), nil
}

func mustEncodeDecode(value string, scale uint16) string {

Check failure on line 17 in lib/debezium/decimal_test.go

View workflow job for this annotation

GitHub Actions / test

func mustEncodeDecode is unused (U1000)
out, err := encodeDecode(value, scale)
if err != nil {
panic(err)
}

return out
}

func TestEncodeDecimal(t *testing.T) {
testCases := []struct {
name string
Expand Down Expand Up @@ -71,6 +88,16 @@ func TestEncodeDecimal(t *testing.T) {
value: "1.05",
scale: 2,
},
{
name: "negative number: 2^16 - 255",
value: "-65281",
scale: 0,
},
{
name: "negative number: 2^16 - 1",
value: "-65535",
scale: 0,
},
{
name: "malformed - empty string",
value: "",
Expand Down

0 comments on commit fbba141

Please sign in to comment.