in athena-federation-sdk/src/main/java/com/amazonaws/athena/connector/lambda/data/BlockUtils.java [1153:1319]
protected static void writeMapValue(UnionMapWriter writer, Field field, BufferAllocator allocator, Object value)
{
writer.startEntry();
if (field.getName().equalsIgnoreCase("key")) {
writer = writer.key();
}
else if (field.getName().equalsIgnoreCase("value")) {
writer = writer.value();
}
else {
throw new IllegalStateException("Invalid Arrow Map schema: " + field);
}
if (value == null) {
return;
}
ArrowType type = field.getType();
try {
switch (Types.getMinorTypeForArrowType(type)) {
case TIMESTAMPMILLITZ:
long dateTimeWithZone;
if (value instanceof ZonedDateTime) {
dateTimeWithZone = DateTimeFormatterUtil.packDateTimeWithZone((ZonedDateTime) value);
}
else if (value instanceof LocalDateTime) {
dateTimeWithZone = DateTimeFormatterUtil.packDateTimeWithZone(
((LocalDateTime) value).atZone(UTC_ZONE_ID).toInstant().toEpochMilli(), UTC_ZONE_ID.getId());
}
else if (value instanceof Date) {
long ldtInLong = Instant.ofEpochMilli(((Date) value).getTime())
.atZone(UTC_ZONE_ID).toInstant().toEpochMilli();
dateTimeWithZone = DateTimeFormatterUtil.packDateTimeWithZone(ldtInLong, UTC_ZONE_ID.getId());
}
else {
dateTimeWithZone = (long) value;
}
writer.timeStampMilliTZ(field.getName()).writeTimeStampMilliTZ(dateTimeWithZone);
break;
case DATEMILLI:
if (value instanceof Date) {
writer.dateMilli(field.getName()).writeDateMilli(((Date) value).getTime());
}
else {
writer.dateMilli(field.getName()).writeDateMilli((long) value);
}
break;
case DATEDAY:
if (value instanceof Date) {
org.joda.time.Days days = org.joda.time.Days.daysBetween(EPOCH,
new org.joda.time.DateTime(((Date) value).getTime()));
writer.dateDay(field.getName()).writeDateDay(days.getDays());
}
else if (value instanceof LocalDate) {
int days = (int) ((LocalDate) value).toEpochDay();
writer.dateDay(field.getName()).writeDateDay(days);
}
else if (value instanceof Long) {
writer.dateDay(field.getName()).writeDateDay(((Long) value).intValue());
}
else {
writer.dateDay(field.getName()).writeDateDay((int) value);
}
break;
case FLOAT8:
writer.float8(field.getName()).writeFloat8((double) value);
break;
case FLOAT4:
writer.float4(field.getName()).writeFloat4((float) value);
break;
case INT:
if (value != null && value instanceof Long) {
//This may seem odd at first but many frameworks (like Presto) use long as the preferred
//native java type for representing integers. We do this to keep type conversions simple.
writer.integer(field.getName()).writeInt(((Long) value).intValue());
}
else {
writer.integer(field.getName()).writeInt((int) value);
}
break;
case TINYINT:
writer.tinyInt(field.getName()).writeTinyInt((byte) value);
break;
case SMALLINT:
writer.smallInt(field.getName()).writeSmallInt((short) value);
break;
case UINT1:
writer.uInt1(field.getName()).writeUInt1((byte) value);
break;
case UINT2:
writer.uInt2(field.getName()).writeUInt2((char) value);
break;
case UINT4:
writer.uInt4(field.getName()).writeUInt4((int) value);
break;
case UINT8:
writer.uInt8(field.getName()).writeUInt8((long) value);
break;
case BIGINT:
writer.bigInt(field.getName()).writeBigInt((long) value);
break;
case VARBINARY:
if (value instanceof ArrowBuf) {
ArrowBuf buf = (ArrowBuf) value;
writer.varBinary(field.getName()).writeVarBinary(0, (int) (buf.capacity()), buf);
}
else if (value instanceof byte[]) {
byte[] bytes = (byte[]) value;
try (ArrowBuf buf = allocator.buffer(bytes.length)) {
buf.writeBytes(bytes);
writer.varBinary(field.getName()).writeVarBinary(0, (int) (buf.readableBytes()), buf);
}
}
break;
case DECIMAL:
int scale = ((ArrowType.Decimal) type).getScale();
int precision = ((ArrowType.Decimal) type).getPrecision();
if (value instanceof Double) {
BigDecimal bdVal = new BigDecimal((double) value);
bdVal = bdVal.setScale(scale, RoundingMode.HALF_UP);
writer.decimal(field.getName(), scale, precision).writeDecimal(bdVal);
}
else {
BigDecimal scaledValue = ((BigDecimal) value).setScale(scale, RoundingMode.HALF_UP);
writer.decimal(field.getName(), scale, precision).writeDecimal(scaledValue);
}
break;
case VARCHAR:
if (value instanceof String) {
byte[] bytes = ((String) value).getBytes(Charsets.UTF_8);
try (ArrowBuf buf = allocator.buffer(bytes.length)) {
buf.writeBytes(bytes);
writer.varChar(field.getName()).writeVarChar(0, (int) (buf.readableBytes()), buf);
}
}
else if (value instanceof ArrowBuf) {
ArrowBuf buf = (ArrowBuf) value;
writer.varChar(field.getName()).writeVarChar(0, (int) (buf.readableBytes()), buf);
}
else if (value instanceof byte[]) {
byte[] bytes = (byte[]) value;
try (ArrowBuf buf = allocator.buffer(bytes.length)) {
buf.writeBytes(bytes);
writer.varChar(field.getName()).writeVarChar(0, (int) (buf.readableBytes()), buf);
}
}
break;
case BIT:
if (value instanceof Integer && (int) value > 0) {
writer.bit(field.getName()).writeBit(1);
}
else if (value instanceof Boolean && (boolean) value) {
writer.bit(field.getName()).writeBit(1);
}
else {
writer.bit(field.getName()).writeBit(0);
}
break;
default:
throw new IllegalArgumentException("Unknown type " + type);
}
}
catch (RuntimeException ex) {
throw new RuntimeException("Unable to write value for field " + field.getName() + " using value " + value, ex);
}
}