Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions java-bigquery-jdbc/docs/USER_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,22 @@ String url = "jdbc:bigquery://https://bigquery.googleapis.com:443"
| :--- | :---: | :--- |
| `EnableTimestampPicos` | `false` | Enables 12-digit picosecond precision for `TIMESTAMP(12)` data types. When enabled, `TIMESTAMP(12)` columns are retrieved with 12 fractional digits formatted in UTC (`YYYY-MM-DD HH:MM:SS.ffffffffffff`) via `getString()` and `getObject()`, typed as `Types.VARCHAR` (`12`) with type name `"TIMESTAMP_PICOSECONDS"`. Picosecond precision is incompatible with Legacy SQL (`QueryDialect=BIG_QUERY`). |

> [!IMPORTANT]
> **Writing picosecond values with a `PreparedStatement`.** BigQuery currently truncates
> `TIMESTAMP`-typed query parameters to microsecond precision, even when the target column is
> `TIMESTAMP(12)`. Binding a value via `setTimestamp()` or `setObject(..., Types.TIMESTAMP)`
> therefore silently drops any sub-microsecond digits.
>
> To write full picosecond precision, bind the value as a string; it is coerced to `TIMESTAMP(12)`
> server side with all 12 digits intact:
>
> ```java
> ps.setString(1, "2026-10-05 08:15:30.987654321098");
> ```
>
> Reading picosecond values is unaffected; `getString()` returns all 12 digits on both the REST and
> Storage Read API paths.

### High-Throughput Storage & Write API Properties

| Property Name | Default Value | Description |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import com.google.cloud.bigquery.BigQueryException;
import com.google.cloud.bigquery.BigQueryOptions;
import com.google.cloud.bigquery.ConnectionProperty;
import com.google.cloud.bigquery.DataFormatOptions;
import com.google.cloud.bigquery.DatasetId;
import com.google.cloud.bigquery.Job;
import com.google.cloud.bigquery.JobInfo;
Expand Down Expand Up @@ -1294,6 +1295,16 @@ private BigQuery getBigQueryConnection() {
bigQueryOptions.setRetrySettings(retry_settings_builder.build());
}

// ISO8601_STRING is the only output format carrying the full 12-digit fraction
// ("YYYY-MM-DDTHH:MM:SS.FFFFFFFFFFFFZ"). The default FLOAT64 and the INT64 alternative both
// cap out at microseconds.
if (this.enableTimestampPicos) {
bigQueryOptions.setDataFormatOptions(
DataFormatOptions.newBuilder()
.timestampFormatOptions(DataFormatOptions.TimestampFormatOptions.ISO8601_STRING)
.build());
}

if (this.catalog != null) {
bigQueryOptions.setProjectId(this.catalog);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
import com.google.auth.oauth2.GoogleCredentials;
import com.google.cloud.bigquery.BigQuery;
import com.google.cloud.bigquery.BigQueryException;
import com.google.cloud.bigquery.DataFormatOptions;
import com.google.cloud.bigquery.Project;
import com.google.cloud.bigquery.QueryJobConfiguration.JobCreationMode;
import com.google.cloud.bigquery.exception.BigQueryJdbcException;
Expand Down Expand Up @@ -259,6 +260,24 @@ public void testWriteAPIConnectionProperties() throws SQLException {
}
}

@Test
public void testTimestampPicosControlsDataFormatOptions() throws IOException, SQLException {
try (BigQueryConnection connection =
new BigQueryConnection(BASE_URL + "EnableTimestampPicos=1;")) {
assertEquals(
DataFormatOptions.TimestampFormatOptions.ISO8601_STRING,
connection.getBigQuery().getOptions().getDataFormatOptions().timestampFormatOptions(),
"EnableTimestampPicos=1 must request ISO8601 timestamp serialization");
}

try (BigQueryConnection connection = new BigQueryConnection(BASE_URL)) {
assertEquals(
DataFormatOptions.TimestampFormatOptions.TIMESTAMP_OUTPUT_FORMAT_UNSPECIFIED,
connection.getBigQuery().getOptions().getDataFormatOptions().timestampFormatOptions(),
"Default connections must not alter the timestamp wire format");
}
}

@Test
public void testGetWriteClient() throws SQLException {
// Test without connection properties. Defaults to default values.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,9 @@ public static String getBaseConnectionUrl() {
getBaseConnectionUrl() + "ProjectId=" + DEFAULT_CATALOG + ";OAuthType=3;Timeout=3600;";
public static final BigQuery bigQuery = BigQueryJdbcBaseTest.getBigQuery(connectionUrl);

public static final String FORCE_READ_API_PROPERTIES =
"EnableHighThroughputAPI=1;HighThroughputActivationRatio=0;HighThroughputMinTableSize=0;MaxResults=1;";

public static final String createDatasetQuery =
"CREATE SCHEMA IF NOT EXISTS `%s.%s` OPTIONS(default_table_expiration_days = 5)";
public static final String dropSchema = "DROP SCHEMA IF EXISTS `%s.%s` CASCADE;";
Expand Down
Loading
Loading