BigQueryUtils { public static Object convertAvroFormat( FieldType beamFieldType, Object avroValue, BigQueryUtils.ConversionOptions options) { TypeName beamFieldTypeName = beamFieldType.getTypeName(); if (avroValue == null) { if (beamFieldType.getNullable()) { return null; } else { throw new IllegalArgumentException(String.format("Field %s not nullable", beamFieldType)); } } switch (beamFieldTypeName) { case BYTE: case INT16: case INT32: case INT64: case FLOAT: case DOUBLE: case STRING: case BYTES: case BOOLEAN: return convertAvroPrimitiveTypes(beamFieldTypeName, avroValue); case DATETIME: switch (options.getTruncateTimestamps()) { case TRUNCATE: return truncateToMillis(avroValue); case REJECT: return safeToMillis(avroValue); default: throw new IllegalArgumentException( String.format( "Unknown timestamp truncation option: %s", options.getTruncateTimestamps())); } case ARRAY: return convertAvroArray(beamFieldType, avroValue, options); case LOGICAL_TYPE: String identifier = beamFieldType.getLogicalType().getIdentifier(); if (SqlTypes.DATE.getIdentifier().equals(identifier)) { return convertAvroDate(avroValue); } else if (SqlTypes.TIME.getIdentifier().equals(identifier)) { return convertAvroTime(avroValue); } else if (SQL_DATE_TIME_TYPES.contains(identifier)) { switch (options.getTruncateTimestamps()) { case TRUNCATE: return truncateToMillis(avroValue); case REJECT: return safeToMillis(avroValue); default: throw new IllegalArgumentException( String.format( "Unknown timestamp truncation option: %s", options.getTruncateTimestamps())); } } else if (SQL_STRING_TYPES.contains(identifier)) { return convertAvroPrimitiveTypes(TypeName.STRING, avroValue); } else { throw new RuntimeException("Unknown logical type " + identifier); } case ROW: Schema rowSchema = beamFieldType.getRowSchema(); if (rowSchema == null) { throw new IllegalArgumentException("Nested ROW missing row schema"); } GenericData.Record record = (GenericData.Record) avroValue; return toBeamRow(record, rowSchema, options); case DECIMAL: throw new RuntimeException("Does not support converting DECIMAL type value"); case MAP: throw new RuntimeException("Does not support converting MAP type value"); default: throw new RuntimeException( "Does not support converting unknown type value: " + beamFieldTypeName); } }  @Experimental(Kind.SCHEMAS) static TableSchema toTableSchema(Schema schema); @Experimental(Kind.SCHEMAS) static Schema fromTableSchema(TableSchema tableSchema); @Experimental(Kind.SCHEMAS) static org.apache.avro.Schema toGenericAvroSchema(
      String schemaName, List<TableFieldSchema> fieldSchemas); static final BigQueryIO.TypedRead.ToBeamRowFunction<TableRow> tableRowToBeamRow(); static final BigQueryIO.TypedRead.FromBeamRowFunction<TableRow> tableRowFromBeamRow(); static SerializableFunction<Row, TableRow> toTableRow(); static SerializableFunction<T, TableRow> toTableRow(
      SerializableFunction<T, Row> toRow); @Experimental(Kind.SCHEMAS) static Row toBeamRow(GenericRecord record, Schema schema, ConversionOptions options); static TableRow convertGenericRecordToTableRow(
      GenericRecord record, TableSchema tableSchema); static TableRow toTableRow(Row row); @Experimental(Kind.SCHEMAS) static Row toBeamRow(Schema rowSchema, TableRow jsonBqRow); @Experimental(Kind.SCHEMAS) static Row toBeamRow(Schema rowSchema, TableSchema bqSchema, TableRow jsonBqRow); static Object convertAvroFormat(
      FieldType beamFieldType, Object avroValue, BigQueryUtils.ConversionOptions options);  }
@Test public void testSubMilliPrecisionRejected() { assertThrows( "precision", IllegalArgumentException.class, () -> BigQueryUtils.convertAvroFormat(FieldType.DATETIME, 1000000001L, REJECT_OPTIONS)); }
@Test public void testMilliPrecisionOk() { long millis = 123456789L; assertThat( BigQueryUtils.convertAvroFormat(FieldType.DATETIME, millis * 1000, REJECT_OPTIONS), equalTo(new Instant(millis))); }
@Test public void testSubMilliPrecisionTruncated() { long millis = 123456789L; assertThat( BigQueryUtils.convertAvroFormat(FieldType.DATETIME, millis * 1000 + 123, TRUNCATE_OPTIONS), equalTo(new Instant(millis))); }
@Test public void testDateType() { LocalDate d = LocalDate.parse("2020-06-04"); assertThat( BigQueryUtils.convertAvroFormat( FieldType.logicalType(SqlTypes.DATE), (int) d.toEpochDay(), REJECT_OPTIONS), equalTo(d)); }
@Test public void testMicroPrecisionTimeType() { LocalTime t = LocalTime.parse("12:34:56.789876"); assertThat( BigQueryUtils.convertAvroFormat( FieldType.logicalType(SqlTypes.TIME), t.toNanoOfDay() / 1000, REJECT_OPTIONS), equalTo(t)); }
@Test public void testBytesType() { byte[] bytes = "hello".getBytes(StandardCharsets.UTF_8); assertThat( BigQueryUtils.convertAvroFormat(FieldType.BYTES, ByteBuffer.wrap(bytes), REJECT_OPTIONS), equalTo(bytes)); }