Skip to content
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

add omitempty option #2

Merged
merged 1 commit into from
Aug 13, 2024
Merged

add omitempty option #2

merged 1 commit into from
Aug 13, 2024

Conversation

RaduBerinde
Copy link
Member

This change adds a gogoproto.omitempty option that can be used (in conjunction with (gogoproto.nullable) = false) for non-nullable message fields.

When a message field is not nullable, its tag is always encoded - even if all message fields are unset. The omitempty option changes the marshalling code to check an IsEmpty() method on that message, which can be defined by the user. The result is that when the message is empty, the encoding matches the one we would get if the field was nullable and the pointer is unset.

i -= len(m.XXX_unrecognized)
copy(dAtA[i:], m.XXX_unrecognized)
}
if !m.InnerOmitEmpty.IsEmpty() {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line is pretty much what the option does.

@nvanbenschoten
Copy link
Member

Nice idea! Out of curiosity, why require an IsEmpty method, instead of just checking if the field is equal to its type's zero value? Flexibility? If so, are we planning to immediately use this flexibility? To enable uses with incomparable field types (e.g. those that contain slices)?

}
return nil
}
func (this *OmitEmpty) Equal(that interface{}) bool {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: if gogoproto is generating a method called Equal, would it be more consistent to rename IsEmpty to Empty?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

}
return nil
}
func (this *OmitEmpty) Equal(that interface{}) bool {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we follow the pattern set by Equal of exposing a gogoproto.empty option to generate an IsEmpty/Empty method?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not supercomfortable with working in this repo, I'd rather not complicate things here. It will be trivial to write it manually wherever we want to use this.

@RaduBerinde
Copy link
Member Author

I figured it could in some cases be faster than a full struct compare. For example for the timestamp I think it's enough to check the WallTime. Also it would allow non-strucr casttypes (which is the case for KVNemesisSeq in test builds).

@RaduBerinde RaduBerinde changed the title add omitempty options add omitempty option Jul 22, 2024
This change adds a `gogoproto.omitempty` option that can be used (in
conjunction with `(gogoproto.nullable) = false`) for non-nullable
message fields.

When a message field is not nullable, its tag is always encoded - even
if all message fields are unset. The `omitempty` option changes the
marshalling code to check an `Empty()` method on that message, which
must be defined by the user. The result is that when the message is
empty, the encoding matches the one we would get if the field was
nullable and the pointer is unset.
@msbutler
Copy link

You claim in the commit msg:

When a message field is not nullable, its tag is always encoded - even if all message fields are unset.

But i'm not sure that's always true. Consider the tombsone testcase in TestEncodeDecodeMVCCValue, which encodes to nothing on master, even though the test adds the DisableMetamorphicSimpleValueEncoding(t) flag. If that flag were not set, I'd expect 0 bytes to be encoded.

Do you understand why the empty fields of the MVCCValueheader are not encoded in the tombstone case, but are encoded in other test cases?

@RaduBerinde
Copy link
Member Author

Good question. It looks like the test disables that metamorphic constant:
https://github.com/cockroachdb/cockroach/blob/master/pkg/storage/mvcc_value_test.go#L166

@RaduBerinde RaduBerinde requested a review from tbg July 28, 2024 23:04
@RaduBerinde
Copy link
Member Author

I'd like to merge this soon to clean up the hacks in crdb.

Copy link
Member

@nvanbenschoten nvanbenschoten left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 🚢

@RaduBerinde
Copy link
Member Author

TFTR!

@RaduBerinde RaduBerinde merged commit 5407e52 into master Aug 13, 2024
0 of 6 checks passed
@RaduBerinde RaduBerinde deleted the omitempty branch August 13, 2024 15:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants