docs: private static Object cleanObject(Object value, Type type)
      {
          if (value == null) {
              return null;
          }
  
          // Array? Better be a block!
          if (Types.isArrayType(type)) {
              if (!(value instanceof Block)) {
                  throw new PrestoException(FUNCTION_IMPLEMENTATION_ERROR, "Object is not a Block, but " + value.getClass());
              }
              return value;
          }
  
          // Map? Better be a block!
          if (Types.isMapType(type)) {
              if (!(value instanceof Block)) {
                  throw new PrestoException(FUNCTION_IMPLEMENTATION_ERROR, "Object is not a Block, but " + value.getClass());
              }
              return value;
          }
  
          // And now for the plain types
          if (type.equals(BIGINT)) {
              if (!(value instanceof Long)) {
                  throw new PrestoException(FUNCTION_IMPLEMENTATION_ERROR, "Object is not a Long, but " + value.getClass());
              }
          }
          else if (type.equals(INTEGER)) {
              if (value instanceof Long) {
                  return ((Long) value).intValue();
              }
  
              if (!(value instanceof Integer)) {
                  throw new PrestoException(FUNCTION_IMPLEMENTATION_ERROR, "Object is not a Long or Integer, but " + value.getClass());
              }
          }
          else if (type.equals(BOOLEAN)) {
              if (!(value instanceof Boolean)) {
                  throw new PrestoException(FUNCTION_IMPLEMENTATION_ERROR, "Object is not a Boolean, but " + value.getClass());
              }
              return value;
          }
          else if (type.equals(DATE)) {
              if (value instanceof Long) {
                  return new Date(DAYS.toMillis((Long) value));
              }
  
              if (value instanceof Calendar) {
                  return new Date(((Calendar) value).getTime().getTime());
              }
  
              if (!(value instanceof Date)) {
                  throw new PrestoException(FUNCTION_IMPLEMENTATION_ERROR, "Object is not a Calendar, Date, or Long, but " + value.getClass());
              }
          }
          else if (type.equals(DOUBLE)) {
              if (!(value instanceof Double)) {
                  throw new PrestoException(FUNCTION_IMPLEMENTATION_ERROR, "Object is not a Double, but " + value.getClass());
              }
          }
          else if (type.equals(REAL)) {
              if (value instanceof Long) {
                  return Float.intBitsToFloat(((Long) value).intValue());
              }
  
              if (value instanceof Integer) {
                  return Float.intBitsToFloat((Integer) value);
              }
  
              if (!(value instanceof Float)) {
                  throw new PrestoException(FUNCTION_IMPLEMENTATION_ERROR, "Object is not a Float, but " + value.getClass());
              }
          }
          else if (type.equals(SMALLINT)) {
              if (value instanceof Long) {
                  return ((Long) value).shortValue();
              }
  
              if (value instanceof Integer) {
                  return ((Integer) value).shortValue();
              }
  
              if (!(value instanceof Short)) {
                  throw new PrestoException(FUNCTION_IMPLEMENTATION_ERROR, "Object is not a Short, but " + value.getClass());
              }
          }
          else if (type.equals(TIME)) {
              if (value instanceof Long) {
                  return new Time((Long) value);
              }
  
              if (!(value instanceof Time)) {
                  throw new PrestoException(FUNCTION_IMPLEMENTATION_ERROR, "Object is not a Long or Time, but " + value.getClass());
              }
          }
          else if (type.equals(TIMESTAMP)) {
              if (value instanceof Long) {
                  return new Timestamp((Long) value);
              }
  
              if (!(value instanceof Timestamp)) {
                  throw new PrestoException(FUNCTION_IMPLEMENTATION_ERROR, "Object is not a Long or Timestamp, but " + value.getClass());
              }
          }
          else if (type.equals(TINYINT)) {
              if (value instanceof Long) {
                  return ((Long) value).byteValue();
              }
  
              if (value instanceof Integer) {
                  return ((Integer) value).byteValue();
              }
  
              if (value instanceof Short) {
                  return ((Short) value).byteValue();
              }
  
              if (!(value instanceof Byte)) {
                  throw new PrestoException(FUNCTION_IMPLEMENTATION_ERROR, "Object is not a Byte, but " + value.getClass());
              }
          }
          else if (type.equals(VARBINARY)) {
              if (value instanceof Slice) {
                  return ((Slice) value).getBytes();
              }
  
              if (!(value instanceof byte[])) {
                  throw new PrestoException(FUNCTION_IMPLEMENTATION_ERROR, "Object is not a Slice byte[], but " + value.getClass());
              }
          }