Skip to content

Commit

Permalink
[fastserde] Fix issue with generating schema fingerprint (#511)
Browse files Browse the repository at this point in the history
when default value is NaN.
  • Loading branch information
krisso-rtb authored Aug 30, 2023
1 parent ecebef2 commit 4640b55
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 6 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"type": "record",
"name": "FloatWithDefaultNaN",
"namespace": "com.linkedin.avro.fastserde.generated.avro",
"doc": "Used to verify Utils.getSchemaFingerprint() method",
"fields": [
{
"name": "floatWithDefaultNaN",
"type": "float",
"default": "NaN"
}
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,19 @@
import org.testng.Assert;
import org.testng.annotations.Test;

import com.linkedin.avro.fastserde.generated.avro.FloatWithDefaultNaN;


public class UtilsTest {

@Test (groups = "deserializationTest")
public void testGenerateSourcePathFromPackageName() {
Assert.assertEquals(Utils.generateSourcePathFromPackageName("com.linkedin.avro"), Utils.fixSeparatorsToMatchOS("/com/linkedin/avro/"));
}

@Test
void testFingerprintOfSchemaWithDefaultNaN() {
// expect no exception is thrown
Utils.getSchemaFingerprint(FloatWithDefaultNaN.SCHEMA$);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -210,20 +210,19 @@ public static boolean isRoundNumber(JsonNode node) {
*/
public static JsonNode enforceUniformNumericDefaultValues(Schema.Field field) {
JsonNode defaultValue = field.defaultValue();
BigDecimal numericValue = defaultValue.getDecimalValue();
Schema schema = field.schema();
// a default value for a union, must match the first element of the union
Schema.Type defaultType = schema.getType() == UNION ? schema.getTypes().get(0).getType() : schema.getType();

switch (defaultType) {
case INT:
if (!isAMathematicalInteger(numericValue)) {
if (!isAMathematicalInteger(defaultValue.getDecimalValue())) {
LOGGER.warn(String.format("Invalid default value: %s for \"int\" field: %s", field.defaultValue(), field.name()));
return defaultValue;
}
return new IntNode(defaultValue.getNumberValue().intValue());
case LONG:
if (!isAMathematicalInteger(numericValue)) {
if (!isAMathematicalInteger(defaultValue.getDecimalValue())) {
LOGGER.warn(String.format("Invalid default value: %s for \"long\" field: %s", field.defaultValue(), field.name()));
return defaultValue;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,20 +143,19 @@ public static boolean isRoundNumber(JsonNode node) {
* Enforces uniform numeric default values across Avro versions
*/
public static JsonNode enforceUniformNumericDefaultValues(Schema.Field field, JsonNode genericDefaultValue) {
BigDecimal numericDefaultValue = genericDefaultValue.decimalValue();
Schema schema = field.schema();
// a default value for a union, must match the first element of the union
Schema.Type defaultType = schema.getType() == UNION ? schema.getTypes().get(0).getType() : schema.getType();

switch (defaultType) {
case INT:
if (!isAMathematicalInteger(numericDefaultValue)) {
if (!isAMathematicalInteger(genericDefaultValue.decimalValue())) {
LOGGER.warn(String.format("Invalid default value: %s for \"int\" field: %s", genericDefaultValue, field.name()));
return genericDefaultValue;
}
return new IntNode(genericDefaultValue.intValue());
case LONG:
if (!isAMathematicalInteger(numericDefaultValue)) {
if (!isAMathematicalInteger(genericDefaultValue.decimalValue())) {
LOGGER.warn(String.format("Invalid default value: %s for \"long\" field: %s", genericDefaultValue, field.name()));
return genericDefaultValue;
}
Expand Down

0 comments on commit 4640b55

Please sign in to comment.