Skip to content

Commit 69a4d11

Browse files
committed
tighten BQ conversion logic
1 parent 2ada632 commit 69a4d11

4 files changed

Lines changed: 35 additions & 14 deletions

File tree

sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/bigquery/BigQueryUtils.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -932,7 +932,14 @@ public static Row toBeamRow(Schema rowSchema, TableSchema bqSchema, TableRow jso
932932
return java.time.Instant.parse(jsonBQString);
933933
}
934934
} else if (fieldType.isLogicalType(Timestamp.IDENTIFIER)) {
935-
return VAR_PRECISION_FORMATTER.parse(jsonBQString, java.time.Instant::from);
935+
try {
936+
BigDecimal bd = new BigDecimal(jsonBQString);
937+
long seconds = bd.longValue();
938+
long nanos = bd.remainder(BigDecimal.ONE).movePointRight(9).longValue();
939+
return java.time.Instant.ofEpochSecond(seconds, nanos);
940+
} catch (NumberFormatException e) {
941+
return VAR_PRECISION_FORMATTER.parse(jsonBQString, java.time.Instant::from);
942+
}
936943
}
937944
}
938945

sdks/java/io/google-cloud-platform/src/test/java/org/apache/beam/sdk/io/gcp/bigquery/BigQueryUtilsTest.java

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import java.time.LocalDate;
4242
import java.time.LocalDateTime;
4343
import java.time.LocalTime;
44+
import java.time.OffsetDateTime;
4445
import java.util.Arrays;
4546
import java.util.Base64;
4647
import java.util.Collections;
@@ -1449,17 +1450,27 @@ public void testToBeamRow_timestampMicros_utcSuffix() {
14491450

14501451
// BigQuery format with " UTC" suffix
14511452
String timestamp = "2024-08-10 16:52:07.123456 UTC";
1452-
1453-
Row beamRow = BigQueryUtils.toBeamRow(schema, new TableRow().set("ts", timestamp));
1454-
1455-
java.time.Instant actual = (java.time.Instant) beamRow.getValue("ts");
1456-
assertEquals(2024, actual.atZone(java.time.ZoneOffset.UTC).getYear());
1457-
assertEquals(8, actual.atZone(java.time.ZoneOffset.UTC).getMonthValue());
1458-
assertEquals(10, actual.atZone(java.time.ZoneOffset.UTC).getDayOfMonth());
1459-
assertEquals(16, actual.atZone(java.time.ZoneOffset.UTC).getHour());
1460-
assertEquals(52, actual.atZone(java.time.ZoneOffset.UTC).getMinute());
1461-
assertEquals(7, actual.atZone(java.time.ZoneOffset.UTC).getSecond());
1462-
assertEquals(123456000, actual.getNano());
1453+
String parsableTimestamp = "2024-08-10T16:52:07.123456Z";
1454+
java.time.Instant instant = OffsetDateTime.parse(parsableTimestamp).toInstant();
1455+
long seconds = instant.getEpochSecond();
1456+
long micros = instant.getNano() / 1000; // BQ stores in micros precision
1457+
String value = seconds + "." + micros;
1458+
1459+
List<TableRow> testRows =
1460+
Arrays.asList(new TableRow().set("ts", timestamp), new TableRow().set("ts", value));
1461+
1462+
for (TableRow row : testRows) {
1463+
Row beamRow = BigQueryUtils.toBeamRow(schema, row);
1464+
1465+
java.time.Instant actual = (java.time.Instant) beamRow.getValue("ts");
1466+
assertEquals(2024, actual.atZone(java.time.ZoneOffset.UTC).getYear());
1467+
assertEquals(8, actual.atZone(java.time.ZoneOffset.UTC).getMonthValue());
1468+
assertEquals(10, actual.atZone(java.time.ZoneOffset.UTC).getDayOfMonth());
1469+
assertEquals(16, actual.atZone(java.time.ZoneOffset.UTC).getHour());
1470+
assertEquals(52, actual.atZone(java.time.ZoneOffset.UTC).getMinute());
1471+
assertEquals(7, actual.atZone(java.time.ZoneOffset.UTC).getSecond());
1472+
assertEquals(123456000, actual.getNano());
1473+
}
14631474
}
14641475

14651476
@Test

sdks/java/io/iceberg/src/test/java/org/apache/beam/sdk/io/iceberg/catalog/BigQueryMetastoreCatalogIT.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ public Catalog createCatalog() {
5858
.put("gcp_project", OPTIONS.getProject())
5959
.put("gcp_location", "us-central1")
6060
.put("warehouse", warehouse)
61+
.put("io-impl", "org.apache.iceberg.gcp.gcs.GCSFileIO")
6162
.build(),
6263
new Configuration());
6364
}
@@ -115,6 +116,8 @@ public void testWriteToPartitionedAndValidateWithBQQuery()
115116
.map(tr -> BigQueryUtils.toBeamRow(BEAM_SCHEMA, tr))
116117
.collect(Collectors.toList());
117118

119+
System.out.println("returned: " + beamRows);
120+
System.out.println("expected: " + inputRows);
118121
assertThat(beamRows, containsInAnyOrder(inputRows.toArray()));
119122

120123
String queryByPartition =

sdks/java/io/iceberg/src/test/java/org/apache/beam/sdk/io/iceberg/catalog/IcebergCatalogBaseIT.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -308,8 +308,8 @@ public Row apply(Long num) {
308308
.addValue(LongStream.range(0, num % 10).boxed().collect(Collectors.toList()))
309309
.addValue(num % 2 == 0 ? null : nestedRow)
310310
.addValue(num)
311-
.addValue(DateTimeUtil.timestamptzFromMicros(timestampMillis * 1000).toInstant())
312-
.addValue(DateTimeUtil.timestampFromMicros(timestampMillis * 1000))
311+
.addValue(DateTimeUtil.timestamptzFromMicros(timestampMillis * 1000 + 123456789).toInstant())
312+
.addValue(DateTimeUtil.timestampFromMicros(timestampMillis * 1000 + 123456789))
313313
.addValue(DateTimeUtil.dateFromDays(Integer.parseInt(strNum)))
314314
.addValue(DateTimeUtil.timeFromMicros(num))
315315
.build();

0 commit comments

Comments
 (0)