From 2626ae1e492ad35933cb99a35b921c6b42b782b1 Mon Sep 17 00:00:00 2001 From: Lawrence Qiu Date: Fri, 12 Dec 2025 17:01:21 -0500 Subject: [PATCH 1/7] test: Add integration tests for picosecond support --- .../testing/RemoteBigQueryHelper.java | 19 +- .../cloud/bigquery/it/ITBigQueryTest.java | 1 + .../bigquery/it/ITHighPrecisionTimestamp.java | 285 ++++++++++++++++++ 3 files changed, 300 insertions(+), 5 deletions(-) create mode 100644 google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITHighPrecisionTimestamp.java diff --git a/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/testing/RemoteBigQueryHelper.java b/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/testing/RemoteBigQueryHelper.java index 4b1767362c..c32e1a0516 100644 --- a/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/testing/RemoteBigQueryHelper.java +++ b/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/testing/RemoteBigQueryHelper.java @@ -120,18 +120,27 @@ public static RemoteBigQueryHelper create(String projectId, InputStream keyStrea * credentials. */ public static RemoteBigQueryHelper create() { + return create(BigQueryOptions.newBuilder()); + } + + /** + * Creates a {@code RemoteBigQueryHelper} object using default project id and authentication + * credentials. + * + * @param bigqueryOptionsBuilder Custom BigqueryOptions.Builder with some pre-defined settings + */ + public static RemoteBigQueryHelper create(BigQueryOptions.Builder bigqueryOptionsBuilder) { HttpTransportOptions transportOptions = BigQueryOptions.getDefaultHttpTransportOptions(); transportOptions = transportOptions.toBuilder() .setConnectTimeout(connectTimeout) .setReadTimeout(connectTimeout) .build(); - BigQueryOptions bigqueryOptions = - BigQueryOptions.newBuilder() + BigQueryOptions.Builder builder = + bigqueryOptionsBuilder .setRetrySettings(retrySettings()) - .setTransportOptions(transportOptions) - .build(); - return new RemoteBigQueryHelper(bigqueryOptions); + .setTransportOptions(transportOptions); + return new RemoteBigQueryHelper(builder.build()); } private static RetrySettings retrySettings() { diff --git a/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITBigQueryTest.java b/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITBigQueryTest.java index de9fef4ee5..101de76fad 100644 --- a/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITBigQueryTest.java +++ b/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITBigQueryTest.java @@ -1723,6 +1723,7 @@ public void testRangeType() throws InterruptedException { "timestampParam", QueryParameterValue.range(RANGE_TEST_VALUES_TIMESTAMP.get("bounded"))) .build(); + System.out.println(config.getQuery()); result = bigquery.query(config); assertEquals(1, Iterables.size(result.getValues())); diff --git a/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITHighPrecisionTimestamp.java b/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITHighPrecisionTimestamp.java new file mode 100644 index 0000000000..617b7a5d3d --- /dev/null +++ b/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITHighPrecisionTimestamp.java @@ -0,0 +1,285 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.cloud.bigquery.it; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertTrue; + +import com.google.cloud.bigquery.BigQuery; +import com.google.cloud.bigquery.BigQueryException; +import com.google.cloud.bigquery.BigQueryOptions; +import com.google.cloud.bigquery.DataFormatOptions; +import com.google.cloud.bigquery.DatasetId; +import com.google.cloud.bigquery.DatasetInfo; +import com.google.cloud.bigquery.Field; +import com.google.cloud.bigquery.FieldValueList; +import com.google.cloud.bigquery.InsertAllRequest; +import com.google.cloud.bigquery.InsertAllResponse; +import com.google.cloud.bigquery.QueryJobConfiguration; +import com.google.cloud.bigquery.QueryParameterValue; +import com.google.cloud.bigquery.Schema; +import com.google.cloud.bigquery.StandardSQLTypeName; +import com.google.cloud.bigquery.StandardTableDefinition; +import com.google.cloud.bigquery.Table; +import com.google.cloud.bigquery.TableId; +import com.google.cloud.bigquery.TableInfo; +import com.google.cloud.bigquery.TableResult; +import com.google.cloud.bigquery.testing.RemoteBigQueryHelper; +import com.google.protobuf.Timestamp; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +public class ITHighPrecisionTimestamp { + + public static final String TEST_HIGH_PRECISION_TIMESTAMP_TABLE_NAME = + "test_high_precision_timestamp"; + private static BigQuery bigquery; + private static final String DATASET = RemoteBigQueryHelper.generateDatasetName(); + private static TableId default_table_id; + public static final long TIMESTAMP_PICOSECOND_PRECISION = 12L; + private static final Field TIMESTAMP_HIGH_PRECISION_FIELD_SCHEMA = + Field.newBuilder("timestampHighPrecisionField", StandardSQLTypeName.TIMESTAMP) + .setTimestampPrecision(TIMESTAMP_PICOSECOND_PRECISION) + .build(); + private static final Schema TABLE_SCHEMA = Schema.of(TIMESTAMP_HIGH_PRECISION_FIELD_SCHEMA); + + private static final String TIMESTAMP1 = "2025-01-01T12:34:56.123456789123Z"; + private static final String TIMESTAMP2 = "1970-01-01T12:12:12.123456789123Z"; + + @BeforeClass + public static void beforeClass() { + BigQueryOptions.Builder builder = + BigQueryOptions.newBuilder() + .setDataFormatOptions( + DataFormatOptions.newBuilder() + .timestampFormatOptions(DataFormatOptions.TimestampFormatOptions.ISO8601_STRING) + .build()); + RemoteBigQueryHelper bigqueryHelper = RemoteBigQueryHelper.create(builder); + bigquery = bigqueryHelper.getOptions().getService(); + DatasetInfo info = DatasetInfo.newBuilder(DATASET).build(); + bigquery.create(info); + + StandardTableDefinition tableDefinition = + StandardTableDefinition.newBuilder().setSchema(TABLE_SCHEMA).build(); + default_table_id = TableId.of(DATASET, TEST_HIGH_PRECISION_TIMESTAMP_TABLE_NAME); + Table createdTable = bigquery.create(TableInfo.of(default_table_id, tableDefinition)); + assertNotNull(createdTable); + + // Populate with some starter data + Map timestamp1 = + Collections.singletonMap("timestampHighPrecisionField", TIMESTAMP1); + Map timestamp2 = + Collections.singletonMap("timestampHighPrecisionField", TIMESTAMP2); + InsertAllRequest request = + InsertAllRequest.newBuilder(default_table_id).addRow(timestamp1).addRow(timestamp2).build(); + InsertAllResponse response = bigquery.insertAll(request); + assertFalse(response.hasErrors()); + assertEquals(0, response.getInsertErrors().size()); + } + + @AfterClass + public static void afterClass() { + if (bigquery != null) { + bigquery.delete(default_table_id); + RemoteBigQueryHelper.forceDelete(bigquery, DATASET); + } + } + + @Test + public void query_highPrecisionTimestamp() throws InterruptedException { + String sql = "SELECT timestampHighPrecisionField FROM " + default_table_id.getTable() + ";"; + QueryJobConfiguration queryJobConfiguration = + QueryJobConfiguration.newBuilder(sql) + .setDefaultDataset(DatasetId.of(DATASET)) + .setUseLegacySql(false) + .build(); + TableResult result = bigquery.query(queryJobConfiguration); + assertNotNull(result.getJobId()); + String[] expected = new String[] {TIMESTAMP1, TIMESTAMP2}; + List list = + StreamSupport.stream(result.getValues().spliterator(), false).collect(Collectors.toList()); + assertEquals(expected.length, list.size()); + for (int i = 0; i < list.size(); i++) { + assertEquals(expected[i], list.get(i).get(0).getValue()); + } + } + + @Test + public void insert_highPrecisionTimestamp_ISOValidFormat() { + StandardTableDefinition tableDefinition = + StandardTableDefinition.newBuilder().setSchema(TABLE_SCHEMA).build(); + String tempTable = "insert_temp_" + TEST_HIGH_PRECISION_TIMESTAMP_TABLE_NAME; + TableId tableId = TableId.of(DATASET, tempTable); + Table createdTable = bigquery.create(TableInfo.of(tableId, tableDefinition)); + assertNotNull(createdTable); + + Map timestampISO = + Collections.singletonMap("timestampHighPrecisionField", "2025-01-01 12:34:56.123456Z"); + InsertAllRequest request = InsertAllRequest.newBuilder(tableId).addRow(timestampISO).build(); + InsertAllResponse response = bigquery.insertAll(request); + assertFalse(response.hasErrors()); + assertEquals(0, response.getInsertErrors().size()); + + bigquery.delete(tableId); + } + + @Test + public void insert_highPrecisionTimestamp_invalidFormats() { + StandardTableDefinition tableDefinition = + StandardTableDefinition.newBuilder().setSchema(TABLE_SCHEMA).build(); + String tempTable = "insert_temp_" + TEST_HIGH_PRECISION_TIMESTAMP_TABLE_NAME; + TableId tableId = TableId.of(DATASET, tempTable); + Table createdTable = bigquery.create(TableInfo.of(tableId, tableDefinition)); + assertNotNull(createdTable); + + Map timestampInMicros = + Collections.singletonMap("timestampHighPrecisionField", 123456); + Map timestampInMicrosString = + Collections.singletonMap("timestampHighPrecisionField", "123456"); + Map timestampNegative = + Collections.singletonMap("timestampHighPrecisionField", -123456); + Map timestampFloat = + Collections.singletonMap("timestampHighPrecisionField", 1000.0); + Map timestampProtobuf = + Collections.singletonMap( + "timestampHighPrecisionField", + Timestamp.newBuilder().setSeconds(123456789).setNanos(123456789).build()); + Map timestampProtobufNegative = + Collections.singletonMap( + "timestampHighPrecisionField", + Timestamp.newBuilder().setSeconds(-123456789).setNanos(-123456789).build()); + InsertAllRequest request = + InsertAllRequest.newBuilder(tableId) + .addRow(timestampInMicros) + .addRow(timestampInMicrosString) + .addRow(timestampNegative) + .addRow(timestampFloat) + .addRow(timestampProtobuf) + .addRow(timestampProtobufNegative) + .build(); + InsertAllResponse response = bigquery.insertAll(request); + assertTrue(response.hasErrors()); + assertEquals(request.getRows().size(), response.getInsertErrors().size()); + + bigquery.delete(tableId); + } + + @Test + public void queryNamedParameter_highPrecisionTimestamp() throws InterruptedException { + String query = + String.format( + "SELECT * FROM %s.%s WHERE timestampHighPrecisionField >= CAST(@timestampParam AS TIMESTAMP(12))", + DATASET, default_table_id.getTable()); + + QueryJobConfiguration queryConfig = + QueryJobConfiguration.newBuilder(query) + .setDefaultDataset(DATASET) + .setUseLegacySql(false) + .addNamedParameter( + "timestampParam", QueryParameterValue.timestamp("2000-01-01 12:34:56.123456789123")) + .build(); + + TableResult result = bigquery.query(queryConfig); + assertNotNull(result); + List timestamps = + StreamSupport.stream(result.getValues().spliterator(), false) + .map(x -> (String) x.get(0).getValue()) + .collect(Collectors.toList()); + assertEquals(1, timestamps.size()); + assertEquals(TIMESTAMP1, timestamps.get(0)); + } + + @Test + public void queryNamedParameter_highPrecisionTimestamp_microsLong() throws InterruptedException { + String query = + String.format( + "SELECT * FROM %s.%s WHERE timestampHighPrecisionField >= CAST(@timestampParam AS TIMESTAMP(12))", + DATASET, default_table_id.getTable()); + + QueryJobConfiguration queryConfig = + QueryJobConfiguration.newBuilder(query) + .setDefaultDataset(DATASET) + .setUseLegacySql(false) + .addNamedParameter( + "timestampParam", + QueryParameterValue.timestamp(946730096123456L)) // 2000-01-01 12:34:56.123456 + .build(); + + TableResult result = bigquery.query(queryConfig); + assertNotNull(result); + List timestamps = + StreamSupport.stream(result.getValues().spliterator(), false) + .map(x -> (String) x.get(0).getValue()) + .collect(Collectors.toList()); + assertEquals(1, timestamps.size()); + assertEquals(TIMESTAMP1, timestamps.get(0)); + } + + @Test + public void queryNamedParameter_highPrecisionTimestamp_microsISOString() + throws InterruptedException { + String query = + String.format( + "SELECT * FROM %s.%s WHERE timestampHighPrecisionField >= CAST(@timestampParam AS TIMESTAMP(12))", + DATASET, default_table_id.getTable()); + + QueryJobConfiguration queryConfig = + QueryJobConfiguration.newBuilder(query) + .setDefaultDataset(DATASET) + .setUseLegacySql(false) + .addNamedParameter( + "timestampParam", QueryParameterValue.timestamp("2000-01-01 12:34:56.123456")) + .build(); + + TableResult result = bigquery.query(queryConfig); + assertNotNull(result); + List timestamps = + StreamSupport.stream(result.getValues().spliterator(), false) + .map(x -> (String) x.get(0).getValue()) + .collect(Collectors.toList()); + assertEquals(1, timestamps.size()); + assertEquals(TIMESTAMP1, timestamps.get(0)); + } + + @Test + public void queryNamedParameter_highPrecisionTimestamp_noExplicitCastInQuery_fails() { + String query = + String.format( + "SELECT * FROM %s.%s WHERE timestampHighPrecisionField >= @timestampParam", + DATASET, default_table_id.getTable()); + + QueryJobConfiguration queryConfig = + QueryJobConfiguration.newBuilder(query) + .setDefaultDataset(DATASET) + .setUseLegacySql(false) + .addNamedParameter( + "timestampParam", QueryParameterValue.timestamp("2000-01-01 12:34:56.123456789123")) + .build(); + + BigQueryException exception = + assertThrows(BigQueryException.class, () -> bigquery.query(queryConfig)); + assertEquals("Invalid argument type passed to a function", exception.getMessage()); + } +} From c4ec38526bfb6664ca2d0a61f09df172535c3344 Mon Sep 17 00:00:00 2001 From: Lawrence Qiu Date: Fri, 12 Dec 2025 17:45:58 -0500 Subject: [PATCH 2/7] chore: Add a micro -> pico exact timestamp test case --- .../cloud/bigquery/it/ITBigQueryTest.java | 1 - .../bigquery/it/ITHighPrecisionTimestamp.java | 108 +++++++++++++----- 2 files changed, 81 insertions(+), 28 deletions(-) diff --git a/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITBigQueryTest.java b/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITBigQueryTest.java index 101de76fad..de9fef4ee5 100644 --- a/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITBigQueryTest.java +++ b/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITBigQueryTest.java @@ -1723,7 +1723,6 @@ public void testRangeType() throws InterruptedException { "timestampParam", QueryParameterValue.range(RANGE_TEST_VALUES_TIMESTAMP.get("bounded"))) .build(); - System.out.println(config.getQuery()); result = bigquery.query(config); assertEquals(1, Iterables.size(result.getValues())); diff --git a/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITHighPrecisionTimestamp.java b/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITHighPrecisionTimestamp.java index 617b7a5d3d..4bd63f34e1 100644 --- a/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITHighPrecisionTimestamp.java +++ b/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITHighPrecisionTimestamp.java @@ -28,7 +28,6 @@ import com.google.cloud.bigquery.DatasetId; import com.google.cloud.bigquery.DatasetInfo; import com.google.cloud.bigquery.Field; -import com.google.cloud.bigquery.FieldValueList; import com.google.cloud.bigquery.InsertAllRequest; import com.google.cloud.bigquery.InsertAllResponse; import com.google.cloud.bigquery.QueryJobConfiguration; @@ -45,6 +44,7 @@ import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.UUID; import java.util.stream.Collectors; import java.util.stream.StreamSupport; import org.junit.AfterClass; @@ -57,7 +57,7 @@ public class ITHighPrecisionTimestamp { "test_high_precision_timestamp"; private static BigQuery bigquery; private static final String DATASET = RemoteBigQueryHelper.generateDatasetName(); - private static TableId default_table_id; + private static TableId defaultTableId; public static final long TIMESTAMP_PICOSECOND_PRECISION = 12L; private static final Field TIMESTAMP_HIGH_PRECISION_FIELD_SCHEMA = Field.newBuilder("timestampHighPrecisionField", StandardSQLTypeName.TIMESTAMP) @@ -67,6 +67,7 @@ public class ITHighPrecisionTimestamp { private static final String TIMESTAMP1 = "2025-01-01T12:34:56.123456789123Z"; private static final String TIMESTAMP2 = "1970-01-01T12:12:12.123456789123Z"; + private static final String TIMESTAMP3 = "2000-01-01T12:34:56.123456789123Z"; @BeforeClass public static void beforeClass() { @@ -83,8 +84,8 @@ public static void beforeClass() { StandardTableDefinition tableDefinition = StandardTableDefinition.newBuilder().setSchema(TABLE_SCHEMA).build(); - default_table_id = TableId.of(DATASET, TEST_HIGH_PRECISION_TIMESTAMP_TABLE_NAME); - Table createdTable = bigquery.create(TableInfo.of(default_table_id, tableDefinition)); + defaultTableId = TableId.of(DATASET, TEST_HIGH_PRECISION_TIMESTAMP_TABLE_NAME); + Table createdTable = bigquery.create(TableInfo.of(defaultTableId, tableDefinition)); assertNotNull(createdTable); // Populate with some starter data @@ -92,8 +93,14 @@ public static void beforeClass() { Collections.singletonMap("timestampHighPrecisionField", TIMESTAMP1); Map timestamp2 = Collections.singletonMap("timestampHighPrecisionField", TIMESTAMP2); + Map timestamp3 = + Collections.singletonMap("timestampHighPrecisionField", TIMESTAMP3); InsertAllRequest request = - InsertAllRequest.newBuilder(default_table_id).addRow(timestamp1).addRow(timestamp2).build(); + InsertAllRequest.newBuilder(defaultTableId) + .addRow(timestamp1) + .addRow(timestamp2) + .addRow(timestamp3) + .build(); InsertAllResponse response = bigquery.insertAll(request); assertFalse(response.hasErrors()); assertEquals(0, response.getInsertErrors().size()); @@ -102,14 +109,21 @@ public static void beforeClass() { @AfterClass public static void afterClass() { if (bigquery != null) { - bigquery.delete(default_table_id); + bigquery.delete(defaultTableId); RemoteBigQueryHelper.forceDelete(bigquery, DATASET); } } + private static String generateTempTableName() { + return String.format( + "insert_temp_%s%s", + UUID.randomUUID().toString().substring(0, 6), TEST_HIGH_PRECISION_TIMESTAMP_TABLE_NAME); + } + @Test public void query_highPrecisionTimestamp() throws InterruptedException { - String sql = "SELECT timestampHighPrecisionField FROM " + default_table_id.getTable() + ";"; + String sql = + String.format("SELECT timestampHighPrecisionField FROM %s;", defaultTableId.getTable()); QueryJobConfiguration queryJobConfiguration = QueryJobConfiguration.newBuilder(sql) .setDefaultDataset(DatasetId.of(DATASET)) @@ -117,12 +131,14 @@ public void query_highPrecisionTimestamp() throws InterruptedException { .build(); TableResult result = bigquery.query(queryJobConfiguration); assertNotNull(result.getJobId()); - String[] expected = new String[] {TIMESTAMP1, TIMESTAMP2}; - List list = - StreamSupport.stream(result.getValues().spliterator(), false).collect(Collectors.toList()); - assertEquals(expected.length, list.size()); - for (int i = 0; i < list.size(); i++) { - assertEquals(expected[i], list.get(i).get(0).getValue()); + String[] expected = new String[] {TIMESTAMP1, TIMESTAMP2, TIMESTAMP3}; + List timestamps = + StreamSupport.stream(result.getValues().spliterator(), false) + .map(x -> (String) x.get(0).getValue()) + .collect(Collectors.toList()); + assertEquals(expected.length, timestamps.size()); + for (int i = 0; i < timestamps.size(); i++) { + assertEquals(expected[i], timestamps.get(i)); } } @@ -130,13 +146,13 @@ public void query_highPrecisionTimestamp() throws InterruptedException { public void insert_highPrecisionTimestamp_ISOValidFormat() { StandardTableDefinition tableDefinition = StandardTableDefinition.newBuilder().setSchema(TABLE_SCHEMA).build(); - String tempTable = "insert_temp_" + TEST_HIGH_PRECISION_TIMESTAMP_TABLE_NAME; - TableId tableId = TableId.of(DATASET, tempTable); + String tempTableName = generateTempTableName(); + TableId tableId = TableId.of(DATASET, tempTableName); Table createdTable = bigquery.create(TableInfo.of(tableId, tableDefinition)); assertNotNull(createdTable); Map timestampISO = - Collections.singletonMap("timestampHighPrecisionField", "2025-01-01 12:34:56.123456Z"); + Collections.singletonMap("timestampHighPrecisionField", "2025-01-01T12:34:56.123456Z"); InsertAllRequest request = InsertAllRequest.newBuilder(tableId).addRow(timestampISO).build(); InsertAllResponse response = bigquery.insertAll(request); assertFalse(response.hasErrors()); @@ -149,7 +165,7 @@ public void insert_highPrecisionTimestamp_ISOValidFormat() { public void insert_highPrecisionTimestamp_invalidFormats() { StandardTableDefinition tableDefinition = StandardTableDefinition.newBuilder().setSchema(TABLE_SCHEMA).build(); - String tempTable = "insert_temp_" + TEST_HIGH_PRECISION_TIMESTAMP_TABLE_NAME; + String tempTable = generateTempTableName(); TableId tableId = TableId.of(DATASET, tempTable); Table createdTable = bigquery.create(TableInfo.of(tableId, tableDefinition)); assertNotNull(createdTable); @@ -191,7 +207,7 @@ public void queryNamedParameter_highPrecisionTimestamp() throws InterruptedExcep String query = String.format( "SELECT * FROM %s.%s WHERE timestampHighPrecisionField >= CAST(@timestampParam AS TIMESTAMP(12))", - DATASET, default_table_id.getTable()); + DATASET, defaultTableId.getTable()); QueryJobConfiguration queryConfig = QueryJobConfiguration.newBuilder(query) @@ -203,12 +219,15 @@ public void queryNamedParameter_highPrecisionTimestamp() throws InterruptedExcep TableResult result = bigquery.query(queryConfig); assertNotNull(result); + String[] expected = new String[] {TIMESTAMP1, TIMESTAMP3}; List timestamps = StreamSupport.stream(result.getValues().spliterator(), false) .map(x -> (String) x.get(0).getValue()) .collect(Collectors.toList()); - assertEquals(1, timestamps.size()); - assertEquals(TIMESTAMP1, timestamps.get(0)); + assertEquals(expected.length, timestamps.size()); + for (int i = 0; i < timestamps.size(); i++) { + assertEquals(expected[i], timestamps.get(i)); + } } @Test @@ -216,7 +235,7 @@ public void queryNamedParameter_highPrecisionTimestamp_microsLong() throws Inter String query = String.format( "SELECT * FROM %s.%s WHERE timestampHighPrecisionField >= CAST(@timestampParam AS TIMESTAMP(12))", - DATASET, default_table_id.getTable()); + DATASET, defaultTableId.getTable()); QueryJobConfiguration queryConfig = QueryJobConfiguration.newBuilder(query) @@ -224,7 +243,8 @@ public void queryNamedParameter_highPrecisionTimestamp_microsLong() throws Inter .setUseLegacySql(false) .addNamedParameter( "timestampParam", - QueryParameterValue.timestamp(946730096123456L)) // 2000-01-01 12:34:56.123456 + QueryParameterValue.timestamp( + 946730096123456L)) // micros for 2000-01-01 12:34:56.123456 .build(); TableResult result = bigquery.query(queryConfig); @@ -233,8 +253,39 @@ public void queryNamedParameter_highPrecisionTimestamp_microsLong() throws Inter StreamSupport.stream(result.getValues().spliterator(), false) .map(x -> (String) x.get(0).getValue()) .collect(Collectors.toList()); - assertEquals(1, timestamps.size()); + assertEquals(2, timestamps.size()); assertEquals(TIMESTAMP1, timestamps.get(0)); + // Exact timestamp for TIMESTAMP 3 is `2000-01-01T12:34:56.123456789123Z` and for the micros + // is `2000-01-01T12:34:56.123456Z`. The micros value gets cast to 12 digits of precision, so + // it becomes `2000-01-01T12:34:56.1234560000Z`. + assertEquals(TIMESTAMP3, timestamps.get(1)); + + String query1 = + String.format( + "SELECT * FROM %s.%s WHERE timestampHighPrecisionField < CAST(@timestampParam AS TIMESTAMP(12))", + DATASET, defaultTableId.getTable()); + + QueryJobConfiguration queryConfig1 = + QueryJobConfiguration.newBuilder(query1) + .setDefaultDataset(DATASET) + .setUseLegacySql(false) + .addNamedParameter( + "timestampParam", + QueryParameterValue.timestamp( + 946730096123456L)) // micros for 2000-01-01 12:34:56.123456 + .build(); + + TableResult result1 = bigquery.query(queryConfig1); + assertNotNull(result1); + List timestamps1 = + StreamSupport.stream(result1.getValues().spliterator(), false) + .map(x -> (String) x.get(0).getValue()) + .collect(Collectors.toList()); + assertEquals(1, timestamps1.size()); + // Exact timestamp for TIMESTAMP 3 is `2000-01-01T12:34:56.123456789123Z` and for the micros + // is `2000-01-01T12:34:56.123456Z`. The micros value gets cast to 12 digits of precision, so + // it becomes `2000-01-01T12:34:56.1234560000Z`. + assertEquals(TIMESTAMP2, timestamps1.get(0)); } @Test @@ -243,7 +294,7 @@ public void queryNamedParameter_highPrecisionTimestamp_microsISOString() String query = String.format( "SELECT * FROM %s.%s WHERE timestampHighPrecisionField >= CAST(@timestampParam AS TIMESTAMP(12))", - DATASET, default_table_id.getTable()); + DATASET, defaultTableId.getTable()); QueryJobConfiguration queryConfig = QueryJobConfiguration.newBuilder(query) @@ -259,8 +310,11 @@ public void queryNamedParameter_highPrecisionTimestamp_microsISOString() StreamSupport.stream(result.getValues().spliterator(), false) .map(x -> (String) x.get(0).getValue()) .collect(Collectors.toList()); - assertEquals(1, timestamps.size()); - assertEquals(TIMESTAMP1, timestamps.get(0)); + String[] expected = new String[] {TIMESTAMP1, TIMESTAMP3}; + assertEquals(expected.length, timestamps.size()); + for (int i = 0; i < timestamps.size(); i++) { + assertEquals(expected[i], timestamps.get(i)); + } } @Test @@ -268,7 +322,7 @@ public void queryNamedParameter_highPrecisionTimestamp_noExplicitCastInQuery_fai String query = String.format( "SELECT * FROM %s.%s WHERE timestampHighPrecisionField >= @timestampParam", - DATASET, default_table_id.getTable()); + DATASET, defaultTableId.getTable()); QueryJobConfiguration queryConfig = QueryJobConfiguration.newBuilder(query) From b135624e1af3799879b0d9adbf14d9674bb98e06 Mon Sep 17 00:00:00 2001 From: Lawrence Qiu Date: Mon, 15 Dec 2025 11:59:06 -0500 Subject: [PATCH 3/7] chore: Add additional test cases --- .../bigquery/it/ITHighPrecisionTimestamp.java | 54 ++++++++++++++----- 1 file changed, 42 insertions(+), 12 deletions(-) diff --git a/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITHighPrecisionTimestamp.java b/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITHighPrecisionTimestamp.java index 4bd63f34e1..a41dec296e 100644 --- a/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITHighPrecisionTimestamp.java +++ b/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITHighPrecisionTimestamp.java @@ -66,7 +66,7 @@ public class ITHighPrecisionTimestamp { private static final Schema TABLE_SCHEMA = Schema.of(TIMESTAMP_HIGH_PRECISION_FIELD_SCHEMA); private static final String TIMESTAMP1 = "2025-01-01T12:34:56.123456789123Z"; - private static final String TIMESTAMP2 = "1970-01-01T12:12:12.123456789123Z"; + private static final String TIMESTAMP2 = "1970-01-01T12:34:56.123456789123Z"; private static final String TIMESTAMP3 = "2000-01-01T12:34:56.123456789123Z"; @BeforeClass @@ -228,6 +228,31 @@ public void queryNamedParameter_highPrecisionTimestamp() throws InterruptedExcep for (int i = 0; i < timestamps.size(); i++) { assertEquals(expected[i], timestamps.get(i)); } + + String query1 = + String.format( + "SELECT * FROM %s.%s WHERE timestampHighPrecisionField < CAST(@timestampParam AS TIMESTAMP(12))", + DATASET, defaultTableId.getTable()); + + QueryJobConfiguration queryConfig1 = + QueryJobConfiguration.newBuilder(query1) + .setDefaultDataset(DATASET) + .setUseLegacySql(false) + .addNamedParameter( + "timestampParam", QueryParameterValue.timestamp("2000-01-01 12:34:56.123456789123")) + .build(); + + TableResult result1 = bigquery.query(queryConfig1); + assertNotNull(result1); + String[] expected1 = new String[] {TIMESTAMP2}; + List timestamps1 = + StreamSupport.stream(result1.getValues().spliterator(), false) + .map(x -> (String) x.get(0).getValue()) + .collect(Collectors.toList()); + assertEquals(expected1.length, timestamps1.size()); + for (int i = 0; i < timestamps1.size(); i++) { + assertEquals(expected1[i], timestamps1.get(i)); + } } @Test @@ -249,16 +274,18 @@ public void queryNamedParameter_highPrecisionTimestamp_microsLong() throws Inter TableResult result = bigquery.query(queryConfig); assertNotNull(result); + // Exact timestamp for TIMESTAMP3 is `2000-01-01T12:34:56.123456789123Z` and for the micros + // is `2000-01-01T12:34:56.123456Z`. The micros value gets cast to 12 digits of precision, so + // it becomes `2000-01-01T12:34:56.123456000000Z`. We do expect it as part of the query. + String[] expected = new String[] {TIMESTAMP1, TIMESTAMP3}; List timestamps = StreamSupport.stream(result.getValues().spliterator(), false) .map(x -> (String) x.get(0).getValue()) .collect(Collectors.toList()); - assertEquals(2, timestamps.size()); - assertEquals(TIMESTAMP1, timestamps.get(0)); - // Exact timestamp for TIMESTAMP 3 is `2000-01-01T12:34:56.123456789123Z` and for the micros - // is `2000-01-01T12:34:56.123456Z`. The micros value gets cast to 12 digits of precision, so - // it becomes `2000-01-01T12:34:56.1234560000Z`. - assertEquals(TIMESTAMP3, timestamps.get(1)); + assertEquals(expected.length, timestamps.size()); + for (int i = 0; i < timestamps.size(); i++) { + assertEquals(expected[i], timestamps.get(i)); + } String query1 = String.format( @@ -277,15 +304,18 @@ public void queryNamedParameter_highPrecisionTimestamp_microsLong() throws Inter TableResult result1 = bigquery.query(queryConfig1); assertNotNull(result1); + // Exact timestamp for TIMESTAMP3 is `2000-01-01T12:34:56.123456789123Z` and for the micros + // is `2000-01-01T12:34:56.123456Z`. The micros value gets cast to 12 digits of precision, so + // it becomes `2000-01-01T12:34:56.123456000000Z`. Do not expect it as part of the query. + String[] expected1 = new String[] {TIMESTAMP2}; List timestamps1 = StreamSupport.stream(result1.getValues().spliterator(), false) .map(x -> (String) x.get(0).getValue()) .collect(Collectors.toList()); - assertEquals(1, timestamps1.size()); - // Exact timestamp for TIMESTAMP 3 is `2000-01-01T12:34:56.123456789123Z` and for the micros - // is `2000-01-01T12:34:56.123456Z`. The micros value gets cast to 12 digits of precision, so - // it becomes `2000-01-01T12:34:56.1234560000Z`. - assertEquals(TIMESTAMP2, timestamps1.get(0)); + assertEquals(expected1.length, timestamps1.size()); + for (int i = 0; i < timestamps1.size(); i++) { + assertEquals(expected1[i], timestamps1.get(i)); + } } @Test From ed8030dbc80727ffc0198718f1e9e7fa5e2d45c7 Mon Sep 17 00:00:00 2001 From: Lawrence Qiu Date: Mon, 15 Dec 2025 13:07:15 -0500 Subject: [PATCH 4/7] chore: Fix test cases with 'Z' --- .../google/cloud/bigquery/QueryParameterValue.java | 6 +++--- .../cloud/bigquery/it/ITHighPrecisionTimestamp.java | 12 +++++++----- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/QueryParameterValue.java b/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/QueryParameterValue.java index cb4e44861d..89e7ae85bf 100644 --- a/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/QueryParameterValue.java +++ b/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/QueryParameterValue.java @@ -328,9 +328,9 @@ public static QueryParameterValue timestamp(Long value) { *

This method supports up to picosecond precision (12 digits) for timestamp. Input should * conform to ISO8601 format. * - *

Must be in the format "yyyy-MM-dd HH:mm:ss.SSSSSS{SSSSSSS}ZZ", e.g. "2014-08-19 - * 12:41:35.123456+00:00" for microsecond precision and "2014-08-19 12:41:35.123456789123+00:00" - * for picosecond precision + *

Should be in the format "yyyy-MM-dd HH:mm:ss.SSSSSS{SSSSSSS}Z", e.g. "2014-08-19 + * 12:41:35.123456Z" for microsecond precision and "2014-08-19 12:41:35.123456789123Z" for + * picosecond precision */ public static QueryParameterValue timestamp(String value) { return of(value, StandardSQLTypeName.TIMESTAMP); diff --git a/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITHighPrecisionTimestamp.java b/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITHighPrecisionTimestamp.java index a41dec296e..0067db42ee 100644 --- a/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITHighPrecisionTimestamp.java +++ b/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITHighPrecisionTimestamp.java @@ -214,7 +214,8 @@ public void queryNamedParameter_highPrecisionTimestamp() throws InterruptedExcep .setDefaultDataset(DATASET) .setUseLegacySql(false) .addNamedParameter( - "timestampParam", QueryParameterValue.timestamp("2000-01-01 12:34:56.123456789123")) + "timestampParam", + QueryParameterValue.timestamp("2000-01-01 12:34:56.123456789123Z")) .build(); TableResult result = bigquery.query(queryConfig); @@ -239,7 +240,8 @@ public void queryNamedParameter_highPrecisionTimestamp() throws InterruptedExcep .setDefaultDataset(DATASET) .setUseLegacySql(false) .addNamedParameter( - "timestampParam", QueryParameterValue.timestamp("2000-01-01 12:34:56.123456789123")) + "timestampParam", + QueryParameterValue.timestamp("2000-01-01 12:34:56.123456789123Z")) .build(); TableResult result1 = bigquery.query(queryConfig1); @@ -269,7 +271,7 @@ public void queryNamedParameter_highPrecisionTimestamp_microsLong() throws Inter .addNamedParameter( "timestampParam", QueryParameterValue.timestamp( - 946730096123456L)) // micros for 2000-01-01 12:34:56.123456 + 946730096123456L)) // micros for 2000-01-01 12:34:56.123456Z .build(); TableResult result = bigquery.query(queryConfig); @@ -299,7 +301,7 @@ public void queryNamedParameter_highPrecisionTimestamp_microsLong() throws Inter .addNamedParameter( "timestampParam", QueryParameterValue.timestamp( - 946730096123456L)) // micros for 2000-01-01 12:34:56.123456 + 946730096123456L)) // micros for 2000-01-01 12:34:56.123456Z .build(); TableResult result1 = bigquery.query(queryConfig1); @@ -331,7 +333,7 @@ public void queryNamedParameter_highPrecisionTimestamp_microsISOString() .setDefaultDataset(DATASET) .setUseLegacySql(false) .addNamedParameter( - "timestampParam", QueryParameterValue.timestamp("2000-01-01 12:34:56.123456")) + "timestampParam", QueryParameterValue.timestamp("2000-01-01 12:34:56.123456Z")) .build(); TableResult result = bigquery.query(queryConfig); From c3fc2e587d1683035021c177f96e74b5f79a711d Mon Sep 17 00:00:00 2001 From: Lawrence Qiu Date: Mon, 15 Dec 2025 13:29:19 -0500 Subject: [PATCH 5/7] chore: Test if first query has an impact --- .../bigquery/it/ITHighPrecisionTimestamp.java | 116 ++++++++++-------- 1 file changed, 62 insertions(+), 54 deletions(-) diff --git a/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITHighPrecisionTimestamp.java b/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITHighPrecisionTimestamp.java index 0067db42ee..1ce585d40c 100644 --- a/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITHighPrecisionTimestamp.java +++ b/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITHighPrecisionTimestamp.java @@ -79,12 +79,16 @@ public static void beforeClass() { .build()); RemoteBigQueryHelper bigqueryHelper = RemoteBigQueryHelper.create(builder); bigquery = bigqueryHelper.getOptions().getService(); + + // Create a new dataset DatasetInfo info = DatasetInfo.newBuilder(DATASET).build(); bigquery.create(info); StandardTableDefinition tableDefinition = StandardTableDefinition.newBuilder().setSchema(TABLE_SCHEMA).build(); defaultTableId = TableId.of(DATASET, TEST_HIGH_PRECISION_TIMESTAMP_TABLE_NAME); + + // Create a new table that can be re-used by the test cases Table createdTable = bigquery.create(TableInfo.of(defaultTableId, tableDefinition)); assertNotNull(createdTable); @@ -204,31 +208,32 @@ public void insert_highPrecisionTimestamp_invalidFormats() { @Test public void queryNamedParameter_highPrecisionTimestamp() throws InterruptedException { - String query = - String.format( - "SELECT * FROM %s.%s WHERE timestampHighPrecisionField >= CAST(@timestampParam AS TIMESTAMP(12))", - DATASET, defaultTableId.getTable()); - - QueryJobConfiguration queryConfig = - QueryJobConfiguration.newBuilder(query) - .setDefaultDataset(DATASET) - .setUseLegacySql(false) - .addNamedParameter( - "timestampParam", - QueryParameterValue.timestamp("2000-01-01 12:34:56.123456789123Z")) - .build(); - - TableResult result = bigquery.query(queryConfig); - assertNotNull(result); - String[] expected = new String[] {TIMESTAMP1, TIMESTAMP3}; - List timestamps = - StreamSupport.stream(result.getValues().spliterator(), false) - .map(x -> (String) x.get(0).getValue()) - .collect(Collectors.toList()); - assertEquals(expected.length, timestamps.size()); - for (int i = 0; i < timestamps.size(); i++) { - assertEquals(expected[i], timestamps.get(i)); - } + // String query = + // String.format( + // "SELECT * FROM %s.%s WHERE timestampHighPrecisionField >= CAST(@timestampParam AS + // TIMESTAMP(12))", + // DATASET, defaultTableId.getTable()); + // + // QueryJobConfiguration queryConfig = + // QueryJobConfiguration.newBuilder(query) + // .setDefaultDataset(DATASET) + // .setUseLegacySql(false) + // .addNamedParameter( + // "timestampParam", + // QueryParameterValue.timestamp("2000-01-01 12:34:56.123456789123Z")) + // .build(); + // + // TableResult result = bigquery.query(queryConfig); + // assertNotNull(result); + // String[] expected = new String[] {TIMESTAMP1, TIMESTAMP3}; + // List timestamps = + // StreamSupport.stream(result.getValues().spliterator(), false) + // .map(x -> (String) x.get(0).getValue()) + // .collect(Collectors.toList()); + // assertEquals(expected.length, timestamps.size()); + // for (int i = 0; i < timestamps.size(); i++) { + // assertEquals(expected[i], timestamps.get(i)); + // } String query1 = String.format( @@ -259,35 +264,38 @@ public void queryNamedParameter_highPrecisionTimestamp() throws InterruptedExcep @Test public void queryNamedParameter_highPrecisionTimestamp_microsLong() throws InterruptedException { - String query = - String.format( - "SELECT * FROM %s.%s WHERE timestampHighPrecisionField >= CAST(@timestampParam AS TIMESTAMP(12))", - DATASET, defaultTableId.getTable()); - - QueryJobConfiguration queryConfig = - QueryJobConfiguration.newBuilder(query) - .setDefaultDataset(DATASET) - .setUseLegacySql(false) - .addNamedParameter( - "timestampParam", - QueryParameterValue.timestamp( - 946730096123456L)) // micros for 2000-01-01 12:34:56.123456Z - .build(); - - TableResult result = bigquery.query(queryConfig); - assertNotNull(result); - // Exact timestamp for TIMESTAMP3 is `2000-01-01T12:34:56.123456789123Z` and for the micros - // is `2000-01-01T12:34:56.123456Z`. The micros value gets cast to 12 digits of precision, so - // it becomes `2000-01-01T12:34:56.123456000000Z`. We do expect it as part of the query. - String[] expected = new String[] {TIMESTAMP1, TIMESTAMP3}; - List timestamps = - StreamSupport.stream(result.getValues().spliterator(), false) - .map(x -> (String) x.get(0).getValue()) - .collect(Collectors.toList()); - assertEquals(expected.length, timestamps.size()); - for (int i = 0; i < timestamps.size(); i++) { - assertEquals(expected[i], timestamps.get(i)); - } + // String query = + // String.format( + // "SELECT * FROM %s.%s WHERE timestampHighPrecisionField >= CAST(@timestampParam AS + // TIMESTAMP(12))", + // DATASET, defaultTableId.getTable()); + // + // QueryJobConfiguration queryConfig = + // QueryJobConfiguration.newBuilder(query) + // .setDefaultDataset(DATASET) + // .setUseLegacySql(false) + // .addNamedParameter( + // "timestampParam", + // QueryParameterValue.timestamp( + // 946730096123456L)) // micros for 2000-01-01 12:34:56.123456Z + // .build(); + // + // TableResult result = bigquery.query(queryConfig); + // assertNotNull(result); + // // Exact timestamp for TIMESTAMP3 is `2000-01-01T12:34:56.123456789123Z` and for the + // micros + // // is `2000-01-01T12:34:56.123456Z`. The micros value gets cast to 12 digits of precision, + // so + // // it becomes `2000-01-01T12:34:56.123456000000Z`. We do expect it as part of the query. + // String[] expected = new String[] {TIMESTAMP1, TIMESTAMP3}; + // List timestamps = + // StreamSupport.stream(result.getValues().spliterator(), false) + // .map(x -> (String) x.get(0).getValue()) + // .collect(Collectors.toList()); + // assertEquals(expected.length, timestamps.size()); + // for (int i = 0; i < timestamps.size(); i++) { + // assertEquals(expected[i], timestamps.get(i)); + // } String query1 = String.format( From 0e36d846d9b02eb2be3c41c8283e69d3884bd37f Mon Sep 17 00:00:00 2001 From: Lawrence Qiu Date: Mon, 15 Dec 2025 14:02:15 -0500 Subject: [PATCH 6/7] chore: Remove flaky test for now --- .../bigquery/it/ITHighPrecisionTimestamp.java | 118 +++++------------- 1 file changed, 29 insertions(+), 89 deletions(-) diff --git a/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITHighPrecisionTimestamp.java b/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITHighPrecisionTimestamp.java index 1ce585d40c..4b5c5970c2 100644 --- a/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITHighPrecisionTimestamp.java +++ b/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITHighPrecisionTimestamp.java @@ -112,10 +112,10 @@ public static void beforeClass() { @AfterClass public static void afterClass() { - if (bigquery != null) { - bigquery.delete(defaultTableId); - RemoteBigQueryHelper.forceDelete(bigquery, DATASET); - } + // if (bigquery != null) { + // bigquery.delete(defaultTableId); + // RemoteBigQueryHelper.forceDelete(bigquery, DATASET); + // } } private static String generateTempTableName() { @@ -208,40 +208,13 @@ public void insert_highPrecisionTimestamp_invalidFormats() { @Test public void queryNamedParameter_highPrecisionTimestamp() throws InterruptedException { - // String query = - // String.format( - // "SELECT * FROM %s.%s WHERE timestampHighPrecisionField >= CAST(@timestampParam AS - // TIMESTAMP(12))", - // DATASET, defaultTableId.getTable()); - // - // QueryJobConfiguration queryConfig = - // QueryJobConfiguration.newBuilder(query) - // .setDefaultDataset(DATASET) - // .setUseLegacySql(false) - // .addNamedParameter( - // "timestampParam", - // QueryParameterValue.timestamp("2000-01-01 12:34:56.123456789123Z")) - // .build(); - // - // TableResult result = bigquery.query(queryConfig); - // assertNotNull(result); - // String[] expected = new String[] {TIMESTAMP1, TIMESTAMP3}; - // List timestamps = - // StreamSupport.stream(result.getValues().spliterator(), false) - // .map(x -> (String) x.get(0).getValue()) - // .collect(Collectors.toList()); - // assertEquals(expected.length, timestamps.size()); - // for (int i = 0; i < timestamps.size(); i++) { - // assertEquals(expected[i], timestamps.get(i)); - // } - - String query1 = + String query = String.format( - "SELECT * FROM %s.%s WHERE timestampHighPrecisionField < CAST(@timestampParam AS TIMESTAMP(12))", + "SELECT * FROM %s.%s WHERE timestampHighPrecisionField >= CAST(@timestampParam AS TIMESTAMP(12))", DATASET, defaultTableId.getTable()); - QueryJobConfiguration queryConfig1 = - QueryJobConfiguration.newBuilder(query1) + QueryJobConfiguration queryConfig = + QueryJobConfiguration.newBuilder(query) .setDefaultDataset(DATASET) .setUseLegacySql(false) .addNamedParameter( @@ -249,61 +222,28 @@ public void queryNamedParameter_highPrecisionTimestamp() throws InterruptedExcep QueryParameterValue.timestamp("2000-01-01 12:34:56.123456789123Z")) .build(); - TableResult result1 = bigquery.query(queryConfig1); - assertNotNull(result1); - String[] expected1 = new String[] {TIMESTAMP2}; - List timestamps1 = - StreamSupport.stream(result1.getValues().spliterator(), false) + TableResult result = bigquery.query(queryConfig); + assertNotNull(result); + String[] expected = new String[] {TIMESTAMP1, TIMESTAMP3}; + List timestamps = + StreamSupport.stream(result.getValues().spliterator(), false) .map(x -> (String) x.get(0).getValue()) .collect(Collectors.toList()); - assertEquals(expected1.length, timestamps1.size()); - for (int i = 0; i < timestamps1.size(); i++) { - assertEquals(expected1[i], timestamps1.get(i)); + assertEquals(expected.length, timestamps.size()); + for (int i = 0; i < timestamps.size(); i++) { + assertEquals(expected[i], timestamps.get(i)); } } @Test public void queryNamedParameter_highPrecisionTimestamp_microsLong() throws InterruptedException { - // String query = - // String.format( - // "SELECT * FROM %s.%s WHERE timestampHighPrecisionField >= CAST(@timestampParam AS - // TIMESTAMP(12))", - // DATASET, defaultTableId.getTable()); - // - // QueryJobConfiguration queryConfig = - // QueryJobConfiguration.newBuilder(query) - // .setDefaultDataset(DATASET) - // .setUseLegacySql(false) - // .addNamedParameter( - // "timestampParam", - // QueryParameterValue.timestamp( - // 946730096123456L)) // micros for 2000-01-01 12:34:56.123456Z - // .build(); - // - // TableResult result = bigquery.query(queryConfig); - // assertNotNull(result); - // // Exact timestamp for TIMESTAMP3 is `2000-01-01T12:34:56.123456789123Z` and for the - // micros - // // is `2000-01-01T12:34:56.123456Z`. The micros value gets cast to 12 digits of precision, - // so - // // it becomes `2000-01-01T12:34:56.123456000000Z`. We do expect it as part of the query. - // String[] expected = new String[] {TIMESTAMP1, TIMESTAMP3}; - // List timestamps = - // StreamSupport.stream(result.getValues().spliterator(), false) - // .map(x -> (String) x.get(0).getValue()) - // .collect(Collectors.toList()); - // assertEquals(expected.length, timestamps.size()); - // for (int i = 0; i < timestamps.size(); i++) { - // assertEquals(expected[i], timestamps.get(i)); - // } - - String query1 = + String query = String.format( - "SELECT * FROM %s.%s WHERE timestampHighPrecisionField < CAST(@timestampParam AS TIMESTAMP(12))", + "SELECT * FROM %s.%s WHERE timestampHighPrecisionField >= CAST(@timestampParam AS TIMESTAMP(12))", DATASET, defaultTableId.getTable()); - QueryJobConfiguration queryConfig1 = - QueryJobConfiguration.newBuilder(query1) + QueryJobConfiguration queryConfig = + QueryJobConfiguration.newBuilder(query) .setDefaultDataset(DATASET) .setUseLegacySql(false) .addNamedParameter( @@ -312,19 +252,19 @@ public void queryNamedParameter_highPrecisionTimestamp_microsLong() throws Inter 946730096123456L)) // micros for 2000-01-01 12:34:56.123456Z .build(); - TableResult result1 = bigquery.query(queryConfig1); - assertNotNull(result1); + TableResult result = bigquery.query(queryConfig); + assertNotNull(result); // Exact timestamp for TIMESTAMP3 is `2000-01-01T12:34:56.123456789123Z` and for the micros // is `2000-01-01T12:34:56.123456Z`. The micros value gets cast to 12 digits of precision, so - // it becomes `2000-01-01T12:34:56.123456000000Z`. Do not expect it as part of the query. - String[] expected1 = new String[] {TIMESTAMP2}; - List timestamps1 = - StreamSupport.stream(result1.getValues().spliterator(), false) + // it becomes `2000-01-01T12:34:56.123456000000Z`. We do expect it as part of the query. + String[] expected = new String[] {TIMESTAMP1, TIMESTAMP3}; + List timestamps = + StreamSupport.stream(result.getValues().spliterator(), false) .map(x -> (String) x.get(0).getValue()) .collect(Collectors.toList()); - assertEquals(expected1.length, timestamps1.size()); - for (int i = 0; i < timestamps1.size(); i++) { - assertEquals(expected1[i], timestamps1.get(i)); + assertEquals(expected.length, timestamps.size()); + for (int i = 0; i < timestamps.size(); i++) { + assertEquals(expected[i], timestamps.get(i)); } } From 128906e5ec3bb49275eab04306bfc78988c4d687 Mon Sep 17 00:00:00 2001 From: Lawrence Qiu Date: Mon, 15 Dec 2025 14:58:13 -0500 Subject: [PATCH 7/7] chore: Remove testing comment --- .../cloud/bigquery/it/ITHighPrecisionTimestamp.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITHighPrecisionTimestamp.java b/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITHighPrecisionTimestamp.java index 4b5c5970c2..332071a620 100644 --- a/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITHighPrecisionTimestamp.java +++ b/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITHighPrecisionTimestamp.java @@ -112,10 +112,10 @@ public static void beforeClass() { @AfterClass public static void afterClass() { - // if (bigquery != null) { - // bigquery.delete(defaultTableId); - // RemoteBigQueryHelper.forceDelete(bigquery, DATASET); - // } + if (bigquery != null) { + bigquery.delete(defaultTableId); + RemoteBigQueryHelper.forceDelete(bigquery, DATASET); + } } private static String generateTempTableName() {