-
Notifications
You must be signed in to change notification settings - Fork 387
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
Fix protobuf serde errors #425
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,6 +9,7 @@ | |
import com.google.protobuf.Descriptors.FieldDescriptor.JavaType; | ||
import com.google.protobuf.Descriptors.FieldDescriptor.Type; | ||
import com.google.protobuf.ByteString; | ||
import com.google.protobuf.DynamicMessage; | ||
import com.google.protobuf.Message; | ||
|
||
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector; | ||
|
@@ -30,6 +31,21 @@ public static class ProtobufStructField implements StructField { | |
public ProtobufStructField(FieldDescriptor fieldDescriptor) { | ||
this.fieldDescriptor = fieldDescriptor; | ||
oi = this.createOIForField(); | ||
comment = fieldDescriptor.getFullName(); | ||
} | ||
|
||
@Override | ||
public boolean equals(Object obj) { | ||
if (obj instanceof ProtobufStructField) { | ||
ProtobufStructField other = (ProtobufStructField)obj; | ||
return fieldDescriptor.equals(other.fieldDescriptor); | ||
} | ||
return false; | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return fieldDescriptor.hashCode(); | ||
} | ||
|
||
@Override | ||
|
@@ -108,6 +124,21 @@ private ObjectInspector createOIForField() { | |
} | ||
} | ||
|
||
@Override | ||
public boolean equals(Object obj) { | ||
if (obj instanceof ProtobufStructObjectInspector) { | ||
ProtobufStructObjectInspector other = (ProtobufStructObjectInspector)obj; | ||
return this.descriptor.equals(other.descriptor) && | ||
this.structFields.equals(other.structFields); | ||
} | ||
return false; | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return descriptor.hashCode(); | ||
} | ||
|
||
@Override | ||
public Category getCategory() { | ||
return Category.STRUCT; | ||
|
@@ -132,15 +163,32 @@ public String getTypeName() { | |
|
||
@Override | ||
public Object create() { | ||
return descriptor.toProto().toBuilder().build(); | ||
return DynamicMessage.newBuilder(descriptor); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. does this return a new builder, or a new record? .build() was being called previously. |
||
} | ||
|
||
@Override | ||
public Object setStructFieldData(Object data, StructField field, Object fieldValue) { | ||
return ((Message) data) | ||
.toBuilder() | ||
.setField(descriptor.findFieldByName(field.getFieldName()), fieldValue) | ||
.build(); | ||
DynamicMessage.Builder builder = (DynamicMessage.Builder)data; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. oh, I see, is the contract that data here will be the result of create()? |
||
ProtobufStructField psf = (ProtobufStructField)field; | ||
FieldDescriptor fd = psf.getFieldDescriptor(); | ||
if (fd.isRepeated()) { | ||
return builder.setField(fd, fieldValue); | ||
} | ||
switch (fd.getType()) { | ||
case ENUM: | ||
builder.setField(fd, fd.getEnumType().findValueByName((String) fieldValue)); | ||
break; | ||
case BYTES: | ||
builder.setField(fd, ByteString.copyFrom((byte[])fieldValue)); | ||
break; | ||
case MESSAGE: | ||
builder.setField(fd, ((Message.Builder)fieldValue).build()); | ||
break; | ||
default: | ||
builder.setField(fd, fieldValue); | ||
break; | ||
} | ||
return builder; | ||
} | ||
|
||
@Override | ||
|
@@ -153,16 +201,32 @@ public Object getStructFieldData(Object data, StructField structField) { | |
if (data == null) { | ||
return null; | ||
} | ||
Message m = (Message) data; | ||
Message.Builder builder; | ||
if (data instanceof Message.Builder) { | ||
builder = (Message.Builder)data; | ||
} else if (data instanceof Message) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. since this fix uses only the builder, do you ever expect Message? |
||
builder = ((Message)data).toBuilder(); | ||
} else { | ||
throw new RuntimeException("Type Message or Message.Builder expected: " + | ||
data.getClass().getCanonicalName()); | ||
} | ||
ProtobufStructField psf = (ProtobufStructField) structField; | ||
FieldDescriptor fieldDescriptor = psf.getFieldDescriptor(); | ||
Object result = m.getField(fieldDescriptor); | ||
Object result = builder.getField(fieldDescriptor); | ||
|
||
if (fieldDescriptor.isRepeated()) { | ||
return result; | ||
} | ||
|
||
if (fieldDescriptor.getType() == Type.ENUM) { | ||
return ((EnumValueDescriptor)result).getName(); | ||
} | ||
if (fieldDescriptor.getType() == Type.BYTES && (result instanceof ByteString)) { | ||
return ((ByteString)result).toByteArray(); | ||
} | ||
if (fieldDescriptor.getType() == Type.MESSAGE) { | ||
return ((Message)result).toBuilder(); | ||
} | ||
return result; | ||
} | ||
|
||
|
@@ -177,9 +241,8 @@ public List<Object> getStructFieldsDataAsList(Object data) { | |
return null; | ||
} | ||
List<Object> result = Lists.newArrayList(); | ||
Message m = (Message) data; | ||
for (FieldDescriptor fd : descriptor.getFields()) { | ||
result.add(m.getField(fd)); | ||
for (StructField field : structFields) { | ||
result.add(getStructFieldData(data, field)); | ||
} | ||
return result; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should this mix in structFields.hashCode() too? This is still correct, but will have more hash collisions in the case of comparing things with the same descriptor but different structFields (idk if that's common or not)