NIFI-9629: Ensure that when we are setting default values on Avro GenericRecord objects that we convert from the schema's default value to the proper type

Signed-off-by: Pierre Villard <pierre.villard.fr@gmail.com>

This closes #5716.
This commit is contained in:
Mark Payne 2022-01-25 16:16:27 -05:00 committed by Pierre Villard
parent 43a24743cc
commit 038811d0dd
No known key found for this signature in database
GPG Key ID: F92A93B30C07C6D5
2 changed files with 23 additions and 3 deletions

View File

@ -622,12 +622,16 @@ public class AvroTypeUtil {
// see if the Avro schema has any fields that aren't in the RecordSchema, and if those fields have a default
// value then we want to populate it in the GenericRecord being produced
for (final Field field : avroSchema.getFields()) {
if (field.defaultVal() == null) {
final Object defaultValue = field.defaultVal();
if (defaultValue == null || defaultValue == JsonProperties.NULL_VALUE) {
continue;
}
if (rec.get(field.name()) == null) {
rec.put(field.name(), field.defaultVal());
// The default value may not actually be the proper value for Avro. For example, the schema may indicate that we need a long but provide a default value of 0.
// To address this, we need to ensure that the value that we set is correct based on the Avro schema, so we need to call convertToAvroObject even on the default value.
final Object normalized = convertToAvroObject(defaultValue, field.schema());
rec.put(field.name(), normalized);
}
}

View File

@ -139,9 +139,25 @@ public class TestAvroTypeUtil {
final GenericRecord avroRecord = AvroTypeUtil.createAvroRecord(record, avroSchema);
assertEquals("John Doe", avroRecord.get("name"));
assertEquals("blue", avroRecord.get("color"));
}
@Test
public void testAvroDefaultedLong() throws IOException {
final List<RecordField> fields = new ArrayList<>();
fields.add(new RecordField("name", RecordFieldType.STRING.getDataType()));
final RecordSchema personSchema = new SimpleRecordSchema(fields);
final org.apache.nifi.serialization.record.Record record = new MapRecord(personSchema, Collections.singletonMap("name", "John Doe"));
final Schema avroSchema = SchemaBuilder.record("person").namespace("nifi")
.fields()
.requiredString("name")
.name("number").type().longType().longDefault(0)
.endRecord();
final GenericRecord avroRecord = AvroTypeUtil.createAvroRecord(record, avroSchema);
assertEquals("John Doe", avroRecord.get("name"));
assertEquals(0L, avroRecord.get("number"));
}
@Test
public void testCreateAvroSchemaPrimitiveTypes() {