-
Notifications
You must be signed in to change notification settings - Fork 85
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Default value is not supported for schema evolution #93
Comments
Related issue in goavro package linkedin/goavro#166 with thoughts why schema evolution is broken in Avro 1.x. |
This isn't related to karrick's discussion of Aveo being an untagged format, it seems like a VM bug. I'll take a look in the next few days, thanks for reporting it. |
Hey oleksmir, so it turns out this kind of related to Karrick's post after all. Because you're dealing with raw records and not container files, you need to provide the writer schema when deserializing data. This code works as intended: package avro
import (
"bytes"
"testing"
"github.com/actgardner/gogen-avro/compiler"
evolution "github.com/actgardner/gogen-avro/test/defaults/evolution"
"github.com/actgardner/gogen-avro/vm"
"github.com/stretchr/testify/assert"
)
func TestDeserializeUser(t *testing.T) {
// Make an old User struct and serialize it
oldUser := NewUser()
var buf bytes.Buffer
err := oldUser.Serialize(&buf)
assert.Nil(t, err)
// Make a new User struct
newUser := evolution.NewUser()
// Compile the deserializer program that reads an old User and puts the contents in a new User.
// This program knows how to set the default fields and won't throw an io.EOF because it runs out of bytes.
deser, err := compiler.CompileSchemaBytes([]byte(oldUser.Schema()), []byte(newUser.Schema()))
assert.Nil(t, err)
// Evaluate the program over the input data (buf.Bytes()) and put the result in newUser
// You can reuse deser, the bytecode for deserializing your structs, any time you're taking in the old schema and putting the data in the new structs. This will improve performance
err = vm.Eval(bytes.NewReader(buf.Bytes()), deser, newUser)
assert.Nil(t, err)
// Because the VM knows about the old and new schemas it can correctly set the default values
assert.Equal(t, "test_first_name", newUser.FirstName)
assert.Equal(t, "test_last_name", newUser.LastName)
assert.Equal(t, "test_info", newUser.Info)
} |
Cool, thank you. It works and default values are set properly. Now I found that unions are not handled.
New schema:
After deserializing (using method from previous comment) the newUser structure will have nil on unionField place instead of having pointer to UnionNullString. It would be nice if somewhere default union structure would be created. Currently it throws panic dereferencing nil. |
@oleksmir this time it was a bug in the generated code which wasn't setting the defaults for union fields correctly. I've corrected it in the head of master and added a test, let me know if it's resolved for you. |
@actgardner thank you for fast fix. Addition of new union field works as expected no matter in which part of record it is added. I found another case where it does not work.
I removed
The test I run:
The error I get:
Even If I use
|
Hey @oleksmir, I finally found some time to work on this. The following cases now work correctly and have regression tests:
Can you try the current master out and let me know if it works for you? Then I can cut a new release. Sorry about the delay! |
I've tagged release 6.1 with these fixes, feel free to open a new issue if you have more problems with schema evolution! |
@actgardner Sorry for long delay. Seem to be working now. Thank you a lot. |
I am trying deserializing old messages using new schema, but default values seems not working.
Old schema:
New schema:
Test:
Test result:
NewUser (with new schema) is created inside DeserializeUser function, that is why missed field receive default golang values instead of default schema values:
The text was updated successfully, but these errors were encountered: