private Object coerceField()

in athena-elasticsearch/src/main/java/com/amazonaws/athena/connectors/elasticsearch/ElasticsearchFieldResolver.java [149:247]


    private Object coerceField(Field field, Object fieldValue)
    {
        Types.MinorType fieldType = Types.getMinorTypeForArrowType(field.getType());

        if (fieldType != Types.MinorType.LIST && fieldValue instanceof List) {
            // This is an abnormal case where the field was not defined as a list in the schema,
            // however, fieldValue returns a list => return first item in list only applying coercion
            // where necessary in order to match the type of the field being mapped into.
            return coerceField(field, ((List) fieldValue).get(0));
        }

        switch (fieldType) {
            case LIST:
                return coerceListField(field, fieldValue);
            case BIGINT:
                if (!field.getMetadata().isEmpty() && field.getMetadata().containsKey("scaling_factor")) {
                    // scaled_float w/scaling_factor - a float represented as a long.
                    double scalingFactor = new Double(field.getMetadata().get("scaling_factor"));
                    if (fieldValue instanceof String) {
                        return Math.round(new Double((String) fieldValue) * scalingFactor);
                    }
                    else if (fieldValue instanceof Number) {
                        return Math.round(((Number) fieldValue).doubleValue() * scalingFactor);
                    }
                    break;
                }
                else if (fieldValue instanceof String) {
                    return new Double((String) fieldValue).longValue();
                }
                else if (fieldValue instanceof Number) {
                    return ((Number) fieldValue).longValue();
                }
                break;
            case INT:
                if (fieldValue instanceof String) {
                    return new Double((String) fieldValue).intValue();
                }
                else if (fieldValue instanceof Number) {
                    return ((Number) fieldValue).intValue();
                }
                break;
            case SMALLINT:
                if (fieldValue instanceof String) {
                    return new Double((String) fieldValue).shortValue();
                }
                else if (fieldValue instanceof Number) {
                    return ((Number) fieldValue).shortValue();
                }
                break;
            case TINYINT:
                if (fieldValue instanceof String) {
                    return new Double((String) fieldValue).byteValue();
                }
                else if (fieldValue instanceof Number) {
                    return ((Number) fieldValue).byteValue();
                }
                break;
            case FLOAT8:
                if (fieldValue instanceof String) {
                    return new Double((String) fieldValue);
                }
                else if (fieldValue instanceof Number) {
                    return ((Number) fieldValue).doubleValue();
                }
                break;
            case FLOAT4:
                if (fieldValue instanceof String) {
                    return new Float((String) fieldValue);
                }
                else if (fieldValue instanceof Number) {
                    return ((Number) fieldValue).floatValue();
                }
                break;
            case DATEMILLI:
                if (fieldValue instanceof String) {
                    try {
                        return toEpochMillis((String) fieldValue);
                    }
                    catch (DateTimeParseException error) {
                        logger.warn("Error parsing localDateTime: {}.", error.getMessage());
                        return null;
                    }
                }
                if (fieldValue instanceof Number) {
                    // Date should be a long numeric value representing epoch milliseconds (e.g. 1589525370001).
                    return ((Number) fieldValue).longValue();
                }
                break;
            case BIT:
                if (fieldValue instanceof String) {
                    return new Boolean((String) fieldValue);
                }
                break;
            default:
                break;
        }

        return fieldValue;
    }