-
Notifications
You must be signed in to change notification settings - Fork 30
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
18 changed files
with
536 additions
and
494 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -199,7 +199,11 @@ func (r *RelationTestSuite) TestPostgresEventWithSchemaAndTimestampNoTZ() { | |
// Testing typing. | ||
assert.Equal(r.T(), evtData["id"], int64(1001)) | ||
assert.Equal(r.T(), evtData["another_id"], int64(333)) | ||
assert.Equal(r.T(), typing.ParseValue(typing.Settings{}, "another_id", evt.GetOptionalSchema(), evtData["another_id"]), typing.Integer) | ||
|
||
schema, err := evt.GetOptionalSchema() | ||
assert.NoError(r.T(), err) | ||
|
||
assert.Equal(r.T(), typing.ParseValue(typing.Settings{}, "another_id", schema, evtData["another_id"]), typing.Integer) | ||
|
||
assert.Equal(r.T(), evtData["email"], "[email protected]") | ||
|
||
|
@@ -518,7 +522,8 @@ func (r *RelationTestSuite) TestGetEventFromBytes_MySQL() { | |
assert.Equal(r.T(), time.Date(2023, time.March, 13, 19, 19, 24, 0, time.UTC), evt.GetExecutionTime()) | ||
assert.Equal(r.T(), "customers", evt.GetTableName()) | ||
|
||
schema := evt.GetOptionalSchema() | ||
schema, err := evt.GetOptionalSchema() | ||
assert.NoError(r.T(), err) | ||
assert.Equal(r.T(), typing.Struct, schema["custom_fields"]) | ||
|
||
kvMap := map[string]any{ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
package converters | ||
|
||
import ( | ||
"encoding/base64" | ||
"fmt" | ||
|
||
"github.com/artie-labs/transfer/lib/debezium/encode" | ||
|
||
"github.com/artie-labs/transfer/lib/maputil" | ||
"github.com/artie-labs/transfer/lib/typing" | ||
"github.com/artie-labs/transfer/lib/typing/decimal" | ||
) | ||
|
||
// toBytes attempts to convert a value (type []byte, or string) to a slice of bytes. | ||
// - If value is already a slice of bytes it will be directly returned. | ||
// - If value is a string we will attempt to base64 decode it. | ||
func toBytes(value any) ([]byte, error) { | ||
var stringVal string | ||
|
||
switch typedValue := value.(type) { | ||
case []byte: | ||
return typedValue, nil | ||
case string: | ||
stringVal = typedValue | ||
default: | ||
return nil, fmt.Errorf("failed to cast value '%v' with type '%T' to []byte", value, value) | ||
} | ||
|
||
data, err := base64.StdEncoding.DecodeString(stringVal) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to base64 decode: %w", err) | ||
} | ||
return data, nil | ||
} | ||
|
||
type Decimal struct { | ||
precision int32 | ||
scale int32 | ||
|
||
variableNumeric bool | ||
} | ||
|
||
func NewDecimal(precision int32, scale int32, variableNumeric bool) *Decimal { | ||
return &Decimal{ | ||
precision: precision, | ||
scale: scale, | ||
variableNumeric: variableNumeric, | ||
} | ||
} | ||
|
||
func (d Decimal) ToKindDetails() typing.KindDetails { | ||
return typing.NewDecimalDetailsFromTemplate(typing.EDecimal, decimal.NewDetails(d.precision, d.scale)) | ||
} | ||
|
||
func (d Decimal) Convert(val any) (any, error) { | ||
if d.variableNumeric { | ||
valueStruct, isOk := val.(map[string]any) | ||
if !isOk { | ||
return nil, fmt.Errorf("value is not map[string]any type") | ||
} | ||
|
||
scale, err := maputil.GetInt32FromMap(valueStruct, "scale") | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
val, isOk := valueStruct["value"] | ||
if !isOk { | ||
return nil, fmt.Errorf("encoded value does not exist") | ||
} | ||
|
||
bytes, err := toBytes(val) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return decimal.NewDecimal(encode.DecodeDecimal(bytes, scale)), nil | ||
} else { | ||
bytes, err := toBytes(val) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return decimal.NewDecimalWithPrecision(encode.DecodeDecimal(bytes, d.scale), d.precision), nil | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package converters | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/artie-labs/transfer/lib/typing/decimal" | ||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func BenchmarkDecodeDecimal_P64_S10(b *testing.B) { | ||
converter := NewDecimal(64, 10, false) | ||
for i := 0; i < b.N; i++ { | ||
val, err := converter.Convert([]byte("AwBGAw8m9GLXrCGifrnVP/8jPHrNEtd1r4rS")) | ||
assert.NoError(b, err) | ||
|
||
dec, isOk := val.(decimal.Decimal) | ||
assert.True(b, isOk) | ||
assert.Equal(b, "123456789012345678901234567890123456789012345678901234.1234567890", dec.String()) | ||
} | ||
} | ||
|
||
func BenchmarkDecodeDecimal_P38_S2(b *testing.B) { | ||
converter := NewDecimal(38, 2, false) | ||
for i := 0; i < b.N; i++ { | ||
val, err := converter.Convert("AMCXznvJBxWzS58P/////w==") | ||
assert.NoError(b, err) | ||
|
||
dec, isOk := val.(decimal.Decimal) | ||
assert.True(b, isOk) | ||
assert.Equal(b, "9999999999999999999999999999999999.99", dec.String()) | ||
} | ||
} | ||
|
||
func BenchmarkDecodeDecimal_P5_S2(b *testing.B) { | ||
converter := NewDecimal(5, 2, false) | ||
for i := 0; i < b.N; i++ { | ||
val, err := converter.Convert("AOHJ") | ||
assert.NoError(b, err) | ||
|
||
dec, isOk := val.(decimal.Decimal) | ||
assert.True(b, isOk) | ||
assert.Equal(b, "578.01", dec.String()) | ||
} | ||
} |
Oops, something went wrong.