This repository was archived by the owner on Feb 5, 2026. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 210
feat: support high precision timestamp strings on getRows calls #1596
Merged
gcf-merge-on-green
merged 63 commits into
main
from
fix-high-precision-timestamps-12704073509468064918
Jan 30, 2026
+300
−21
Merged
Changes from 35 commits
Commits
Show all changes
63 commits
Select commit
Hold shift + click to select a range
a6dd325
feat: add system tests for timestampOutputFormat options
google-labs-jules[bot] 173e65a
feat: add system tests for timestampOutputFormat options
google-labs-jules[bot] 489be58
Add error visibility to readrows calls
danieljbruce a1f1bba
Add a comment about why the try/catch block is there
danieljbruce a0f7fd3
Do an assertion check and report the error
danieljbruce e6b03c1
Fix another test to expect an error
danieljbruce e934164
Change other tests to expect errors
danieljbruce 9567663
Change string error messages
danieljbruce b9e81ac
Adjust another error message
danieljbruce da842e5
Revert "Adjust another error message"
danieljbruce 38148e1
Change another test to expect an error
danieljbruce c52c9f4
Change the schema to include timestamp precision
danieljbruce f0ab80e
Source code changes for int64 and timestamp
danieljbruce 07aa7f1
test: add tests for timestampOutputFormat/useInt64Timestamp defaults
google-labs-jules[bot] 1b09a9c
Implement proper timestamp parsing
danieljbruce 1ff7a2c
more test corrections
danieljbruce c206170
Support proper business logic for timestamps
danieljbruce d83f2a5
listParams pass through
danieljbruce c131f4e
correct test value
danieljbruce 8c4efef
fix: support high precision timestamp strings in BigQueryTimestamp
google-labs-jules[bot] 4366e9e
run the linter
danieljbruce 074d05f
Remove unnecessary line of code
danieljbruce 5fb38d4
add Z
danieljbruce 7e5d6b0
list all users of the mergeSchemaWithRows_ method
danieljbruce e5506e9
run linter
danieljbruce ad2211a
remove only
danieljbruce 3d072d0
Update file header
danieljbruce 44e6e7b
fix: support high precision timestamp strings in BigQueryTimestamp
google-labs-jules[bot] dbea718
Revert "fix: support high precision timestamp strings in BigQueryTime…
danieljbruce 14bb0a8
fix: support high precision timestamp strings in BigQueryTimestamp
google-labs-jules[bot] 1cf914e
parameterize the new system tests
danieljbruce 02601d3
feat: Parameterize timestamp output format tests
danieljbruce feb0f9a
feat: Re-add undefined test cases for timestamp output format
danieljbruce 26a4f07
Merge branch 'fix-high-precision-timestamps-12704073509468064918' of …
danieljbruce 6e9de44
fix: support high precision timestamp strings in BigQueryTimestamp
google-labs-jules[bot] c45bde8
run the linter
danieljbruce bdde5d4
fix: support high precision timestamp strings in BigQueryTimestamp
google-labs-jules[bot] 7ebd6ee
Merge branch 'fix-high-precision-timestamps-12704073509468064918' of …
danieljbruce a17f421
meet requirements change
danieljbruce fb38379
cleaner inclusion code
danieljbruce 506edb8
Number cast was removed by mistake
danieljbruce efacb53
Adding listParams back in
danieljbruce 41c5948
Pass list params
danieljbruce 33f05ab
selectively use ISO8601_STRING as timestampOutputF
danieljbruce 6913244
Fix the tests not to expect errors
danieljbruce d53b6c5
run the linter
danieljbruce 00b8bc7
remove only
danieljbruce 1077b8e
don’t change this file
danieljbruce a1bbfc1
Correct unit tests
danieljbruce 08b0b62
add a TODO
danieljbruce 0547069
Merge branch 'main' into fix-high-precision-timestamps-12704073509468…
danieljbruce d199177
linter fix
danieljbruce 629b519
Remove this import
danieljbruce cd5d35a
Add a test that ensures the request is correct
danieljbruce 7de53d4
test should send back an error
danieljbruce 3df3939
Update src/table.ts
danieljbruce 1b27a26
simpler logic for default timestamp
danieljbruce eaaa4d9
broader only
danieljbruce 6f58be2
remove useInt64Timestamp changes
danieljbruce 678ff01
Modify logic slightly to account for no parameter
danieljbruce 5e094af
run the linter
danieljbruce 703de99
remove only
danieljbruce 1ae67bc
Add void keyword
danieljbruce File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,195 @@ | ||
| // Copyright 2024 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. | ||
|
|
||
| import * as assert from 'assert'; | ||
| import {describe, it, before, after} from 'mocha'; | ||
| import {BigQuery} from '../src'; | ||
| import {randomUUID} from 'crypto'; | ||
|
|
||
| const bigquery = new BigQuery(); | ||
|
|
||
| describe.only('Timestamp Output Format System Tests', () => { | ||
| const datasetId = `timestamp_test_${randomUUID().replace(/-/g, '_')}`; | ||
| const tableId = `timestamp_table_${randomUUID().replace(/-/g, '_')}`; | ||
| const dataset = bigquery.dataset(datasetId); | ||
| const table = dataset.table(tableId); | ||
| const expectedValue = '2023-01-01T12:00:00.123456000Z'; | ||
| const highPrecisionExpectedValue = '2023-01-01T12:00:00.123456789123Z'; | ||
|
|
||
| before(async () => { | ||
| await dataset.create(); | ||
| await table.create({ | ||
| schema: [{name: 'ts', type: 'TIMESTAMP', timestampPrecision: '12'}], | ||
| }); | ||
| // Insert a row to test retrieval | ||
| await table.insert([{ts: highPrecisionExpectedValue}]); | ||
| }); | ||
|
|
||
| after(async () => { | ||
| try { | ||
| await dataset.delete({force: true}); | ||
| } catch (e) { | ||
| console.error('Error deleting dataset:', e); | ||
| } | ||
| }); | ||
|
|
||
| interface TestCase { | ||
| description: string; | ||
| options: { | ||
| 'formatOptions.timestampOutputFormat'?: 'TIMESTAMP_OUTPUT_FORMAT_UNSPECIFIED' | 'FLOAT64' | 'INT64' | 'ISO8601_STRING'; | ||
| 'formatOptions.useInt64Timestamp'?: boolean; | ||
| }; | ||
| expectedValue?: string; | ||
| shouldFail?: boolean; | ||
| expectedErrorMessage?: string; | ||
| } | ||
|
|
||
| const testCases: TestCase[] = [ | ||
| { | ||
| description: 'should call getRows with TIMESTAMP_OUTPUT_FORMAT_UNSPECIFIED and useInt64Timestamp=true', | ||
| options: { | ||
| 'formatOptions.timestampOutputFormat': 'TIMESTAMP_OUTPUT_FORMAT_UNSPECIFIED', | ||
| 'formatOptions.useInt64Timestamp': true, | ||
| }, | ||
| expectedValue: expectedValue, | ||
| }, | ||
| { | ||
| description: 'should call getRows with TIMESTAMP_OUTPUT_FORMAT_UNSPECIFIED and useInt64Timestamp=false', | ||
| options: { | ||
| 'formatOptions.timestampOutputFormat': 'TIMESTAMP_OUTPUT_FORMAT_UNSPECIFIED', | ||
| 'formatOptions.useInt64Timestamp': false, | ||
| }, | ||
| expectedValue: expectedValue, | ||
| }, | ||
| { | ||
| description: 'should call getRows with FLOAT64 and useInt64Timestamp=true', | ||
| options: { | ||
| 'formatOptions.timestampOutputFormat': 'FLOAT64', | ||
| 'formatOptions.useInt64Timestamp': true, | ||
| }, | ||
| shouldFail: true, | ||
| expectedErrorMessage: 'Cannot specify both use_int64_timestamp and timestamp_output_format.', | ||
| }, | ||
| { | ||
| description: 'should call getRows with FLOAT64 and useInt64Timestamp=false', | ||
| options: { | ||
| 'formatOptions.timestampOutputFormat': 'FLOAT64', | ||
| 'formatOptions.useInt64Timestamp': false, | ||
| }, | ||
| expectedValue: expectedValue, | ||
| }, | ||
| { | ||
| description: 'should call getRows with INT64 and useInt64Timestamp=true', | ||
| options: { | ||
| 'formatOptions.timestampOutputFormat': 'INT64', | ||
| 'formatOptions.useInt64Timestamp': true, | ||
| }, | ||
| expectedValue: expectedValue, | ||
| }, | ||
| { | ||
| description: 'should call getRows with INT64 and useInt64Timestamp=false', | ||
| options: { | ||
| 'formatOptions.timestampOutputFormat': 'INT64', | ||
| 'formatOptions.useInt64Timestamp': false, | ||
| }, | ||
| expectedValue: expectedValue, | ||
| }, | ||
| { | ||
| description: 'should call getRows with ISO8601_STRING and useInt64Timestamp=true', | ||
| options: { | ||
| 'formatOptions.timestampOutputFormat': 'ISO8601_STRING', | ||
| 'formatOptions.useInt64Timestamp': true, | ||
| }, | ||
| shouldFail: true, | ||
| expectedErrorMessage: 'Cannot specify both use_int64_timestamp and timestamp_output_format.', | ||
| }, | ||
| { | ||
| description: 'should call getRows with ISO8601_STRING and useInt64Timestamp=false', | ||
| options: { | ||
| 'formatOptions.timestampOutputFormat': 'ISO8601_STRING', | ||
| 'formatOptions.useInt64Timestamp': false, | ||
| }, | ||
| expectedValue: '2023-01-01T12:00:00.123456789123', | ||
| }, | ||
| { | ||
| description: 'should call getRows with timestampOutputFormat undefined and useInt64Timestamp=true', | ||
| options: { | ||
| 'formatOptions.useInt64Timestamp': true, | ||
| }, | ||
| expectedValue: expectedValue, | ||
| }, | ||
| { | ||
| description: 'should call getRows with timestampOutputFormat undefined and useInt64Timestamp=false', | ||
| options: { | ||
| 'formatOptions.useInt64Timestamp': false, | ||
| }, | ||
| expectedValue: expectedValue, | ||
| }, | ||
| { | ||
| description: 'should call getRows with TIMESTAMP_OUTPUT_FORMAT_UNSPECIFIED and useInt64Timestamp undefined', | ||
| options: { | ||
| 'formatOptions.timestampOutputFormat': 'TIMESTAMP_OUTPUT_FORMAT_UNSPECIFIED', | ||
| }, | ||
| expectedValue: expectedValue, | ||
| }, | ||
| { | ||
| description: 'should call getRows with FLOAT64 and useInt64Timestamp undefined', | ||
| options: { | ||
| 'formatOptions.timestampOutputFormat': 'FLOAT64', | ||
|
||
| }, | ||
| shouldFail: true, | ||
| expectedErrorMessage: 'Cannot specify both use_int64_timestamp and timestamp_output_format.', | ||
| }, | ||
| { | ||
| description: 'should call getRows with INT64 and useInt64Timestamp undefined', | ||
| options: { | ||
| 'formatOptions.timestampOutputFormat': 'INT64', | ||
| }, | ||
| expectedValue: expectedValue, | ||
| }, | ||
| { | ||
| description: 'should call getRows with ISO8601_STRING and useInt64Timestamp undefined', | ||
| options: { | ||
| 'formatOptions.timestampOutputFormat': 'ISO8601_STRING', | ||
| }, | ||
| shouldFail: true, | ||
| expectedErrorMessage: 'Cannot specify both use_int64_timestamp and timestamp_output_format.', | ||
| }, | ||
| { | ||
| description: 'should call getRows with timestampOutputFormat undefined and useInt64Timestamp undefined', | ||
| options: {}, | ||
| expectedValue: expectedValue, | ||
| }, | ||
| ]; | ||
|
|
||
| testCases.forEach(testCase => { | ||
| it(testCase.description, async () => { | ||
| try { | ||
| // eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
| const [rows] = await table.getRows(testCase.options as any); | ||
| if (testCase.shouldFail) { | ||
| assert.fail('The call should not have succeeded'); | ||
| } | ||
| assert(rows.length > 0); | ||
| assert.strictEqual(rows[0].ts.value, testCase.expectedValue); | ||
| } catch (e) { | ||
| if (testCase.shouldFail) { | ||
| assert.strictEqual((e as Error).message, testCase.expectedErrorMessage); | ||
| } else { | ||
| throw e; | ||
| } | ||
| } | ||
| }); | ||
| }); | ||
| }); | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.