Bug with encoding union + fixed + decimal
Korzhenevskyi opened this issue · 6 comments
Korzhenevskyi commented
If I modify the following test from your repository
func TestEncoder_FixedRat_Positive(t *testing.T) {
schema := `{"type":"fixed", "name": "test", "size": 6,"logicalType":"decimal","precision":4,"scale":2}`
buf := bytes.NewBuffer([]byte{})
enc, err := avro.NewEncoder(schema, buf)
require.NoError(t, err)
err = enc.Encode(big.NewRat(1734, 5))
require.NoError(t, err)
assert.Equal(t, []byte{0x00, 0x00, 0x00, 0x00, 0x87, 0x78}, buf.Bytes())
}
to have a union type
func TestEncoder_FixedRat_Positive(t *testing.T) {
schema := `["null", {"type":"fixed", "name": "test", "size": 6,"logicalType":"decimal","precision":4,"scale":2}]`
buf := bytes.NewBuffer([]byte{})
enc, err := avro.NewEncoder(schema, buf)
require.NoError(t, err)
err = enc.Encode(big.NewRat(1734, 5))
require.NoError(t, err)
assert.Equal(t, []byte{0x00, 0x00, 0x00, 0x00, 0x87, 0x78}, buf.Bytes())
}
It returns an error avro: big.Rat is unsupported for Avro fixed, size=6
.
This looks like a bug.
If I define the avro type in a wrong way, please, tell me what to fix. It would be also great if you added this test to the repository.
nrwiersma commented
You have added a nullable union, so you need an extra pointer to deal with the union.
Korzhenevskyi commented
@nrwiersma could you give me an example, please?
Korzhenevskyi commented
should I use a map?
func TestEncoder_FixedRat_Positive(t *testing.T) {
schema := `["null", {"type":"fixed", "name": "test", "size": 6,"logicalType":"decimal","precision":4,"scale":2}]`
buf := bytes.NewBuffer([]byte{})
enc, err := avro.NewEncoder(schema, buf)
require.NoError(t, err)
m := map[string]any{
"test": big.NewRat(1734, 5),
}
err = enc.Encode(m)
require.NoError(t, err)
assert.Equal(t, []byte{0x02, 0x00, 0x00, 0x00, 0x00, 0x87, 0x78}, buf.Bytes())
}
Korzhenevskyi commented
I wonder why https://github.com/hamba/avro/blob/main/encoder_union_test.go#L427 -- this works for bytes, but doesn't work for fixed.
nrwiersma commented
You need to encode the pointer to the value, effectively a **big.Rat
.
val := big.NewRat(1734, 5)
err = enc.Encode(&val)
Korzhenevskyi commented
Thank you @nrwiersma!