hamba/avro

Bug with encoding union + fixed + decimal

Korzhenevskyi opened this issue · 6 comments

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.

You have added a nullable union, so you need an extra pointer to deal with the union.

@nrwiersma could you give me an example, please?

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())
}

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.

You need to encode the pointer to the value, effectively a **big.Rat.

val := big.NewRat(1734, 5)
err = enc.Encode(&val)