feat(bigquery-jdbc): add picosecond precision support for TIMESTAMP - #14031
feat(bigquery-jdbc): add picosecond precision support for TIMESTAMP#14031keshavdandeva wants to merge 5 commits into
TIMESTAMP#14031Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces support for 12-digit picosecond precision for TIMESTAMP columns in the BigQuery JDBC driver, adding a new EnableTimestampPicos connection property and updating result sets, metadata, and statement processing to handle the higher precision. The review feedback highlights a potential runtime crash in BigQueryTemporalUtility.boxTimestamp when falling back to Timestamp.valueOf with untruncated strings, and suggests removing an unused enableTimestampPicos parameter from formatTimestampStringFromMicroseconds along with updating its caller.
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request introduces support for 12-digit picosecond precision for TIMESTAMP columns in the BigQuery JDBC driver, controlled by a new EnableTimestampPicos connection property. It updates result set implementations, metadata handling, and temporal utilities to format, parse, and truncate high-precision timestamps correctly. The review feedback suggests simplifying the newly registered type coercion lambdas in BigQueryTypeCoercionUtility by using a method reference and removing explicit parameter types to improve readability.
| .registerTypeCoercion( | ||
| (Text text) -> BigQueryTemporalUtility.boxTimestamp(text.toString()), | ||
| Text.class, | ||
| Timestamp.class) | ||
| .registerTypeCoercion( | ||
| (String str) -> BigQueryTemporalUtility.boxTimestamp(str), | ||
| String.class, | ||
| Timestamp.class) |
There was a problem hiding this comment.
These lambdas can be simplified to use a method reference and a standard lambda without explicit parameter types to improve readability and maintain consistency with other type coercions in this file.
| .registerTypeCoercion( | |
| (Text text) -> BigQueryTemporalUtility.boxTimestamp(text.toString()), | |
| Text.class, | |
| Timestamp.class) | |
| .registerTypeCoercion( | |
| (String str) -> BigQueryTemporalUtility.boxTimestamp(str), | |
| String.class, | |
| Timestamp.class) | |
| .registerTypeCoercion( | |
| text -> BigQueryTemporalUtility.boxTimestamp(text.toString()), | |
| Text.class, | |
| Timestamp.class) | |
| .registerTypeCoercion( | |
| BigQueryTemporalUtility::boxTimestamp, | |
| String.class, | |
| Timestamp.class) |
b/544843125
b/544839231
This PR introduces support for picosecond precision (up to 12 fractional digits) when reading BigQuery
TIMESTAMPcolumns and standardizes timestamp string representation across both Arrow and JSON engines.Key Architectural Notes
Picosecond Precision Gating (
EnableTimestampPicos):EnableTimestampPicosconnection property.displaySize=26, precision=26, scale=6),getString(),getTimestamp(), andgetObject().displaySize=32, precision=32, scale=12inResultSetMetaDataand preserves full 12-digit picosecond precision ingetString().TIMESTAMP
getString()Formatting Normalization:getString()on the JSON REST path returned raw numeric epoch strings (e.g.,"1408452095.22"or"1.6905474E9"), diverging from the Arrow engine.getString()on the JSON path now standardizes allTIMESTAMPcolumns to formatted UTC timestamp strings ("yyyy-MM-dd HH:mm:ss.ffffff"), ensuring consistent, JVM-timezone-independent representation across both Arrow and JSON engines regardless of the flag.EnableTimestampPicoscontrols the fractional digit scale (6 vs. up to 12 digits).Changes Made
Configuration:
EnableTimestampPicosconnection property inBigQueryConnectionandDataSource.Arrow Storage Engine:
ReadSessioncreation inBigQueryStatementto explicitly requestTIMESTAMP_PRECISION_PICOSwhenEnableTimestampPicosis enabled.Text -> TimestampandString -> TimestampinBigQueryTypeCoercionUtilitysogetObject()andgetTimestamp()seamlessly handle Arrow picosecondVarCharVectorcolumns.JSON REST Engine:
BigQueryJsonResultSet.getString()to format timestamp fields using UTC anchoring.BigQueryTemporalUtility.parseEpochDecimalToInstant()usingBigDecimalflooring (RoundingMode.DOWN). This losslessly handles standard decimals, scientific notation (e.g.,"1.6905474E9"), whole integer epochs, and pre-1970 negative epoch decimals.FieldValueToTimestampto delegate directly toparseEpochDecimalToInstant(), preserving nanosecond precision forgetTimestamp()andgetObject().JDBC Metadata:
BigQueryResultSetMetadatato reportdisplaySize=32,precision=32, andscale=12whenEnableTimestampPicosis active and the column schema precision is 12.Temporal Utilities & Precision Handling:
RoundingMode.DOWN) rather than rounding to avoid timestamp boundary rollovers (e.g., rounding23:59:59.9999999to the next day).boxTimestamp(): Gracefully truncates 12-digit picosecond strings to 9 digits (nanoseconds) forjava.sql.Timestamp, which maxes out at nanosecond precision and would otherwise throw aDateTimeParseException.formatTimestampStringFromMicroseconds(),formatTimestampStringFromIso(), andformatTimestampString().Testing
BigQueryTemporalUtilityTestandFieldValueTypeBigQueryCoercionUtilityTestverifying scientific notation, positive/negative pre-1970 epoch timestamps, and deterministic truncation for >6 and >9 digit fractions.BigQueryArrowResultSetTestverifyinggetString(),getTimestamp(), andgetObject()against picosecondTextcolumns.BigQueryResultSetMetadataTestverifying precision, scale, and display size with picoseconds enabled and disabled.REPEATEDandRECORDtimestamp handling inBigQueryJsonResultSetTest.