diff --git a/handwritten/bigquery/src/bigquery.ts b/handwritten/bigquery/src/bigquery.ts index d52d07343b5..116434f173d 100644 --- a/handwritten/bigquery/src/bigquery.ts +++ b/handwritten/bigquery/src/bigquery.ts @@ -597,9 +597,6 @@ export class BigQuery extends Service { wrapIntegers: boolean | IntegerTypeCastOptions; selectedFields?: string[]; parseJSON?: boolean; - listParams?: - | bigquery.tabledata.IListParams - | bigquery.jobs.IGetQueryResultsParams; }, ) { // deep copy schema fields to avoid mutation @@ -1100,11 +1097,6 @@ export class BigQuery extends Service { }; }), }; - } else if ((providedType as string).toUpperCase() === 'TIMESTAMP(12)') { - return { - type: 'TIMESTAMP', - timestampPrecision: '12', - }; } providedType = (providedType as string).toUpperCase(); @@ -2256,33 +2248,14 @@ export class BigQuery extends Service { if (res && res.jobComplete) { let rows: any = []; if (res.schema && res.rows) { - try { - /* - Without this try/catch block, calls to getRows will hang indefinitely if - a call to mergeSchemaWithRows_ fails because the error never makes it to - the callback. Instead, pass the error to the callback the user provides - so that the user can see the error. - */ - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const listParams = { - 'formatOptions.timestampOutputFormat': - queryReq.formatOptions?.timestampOutputFormat, - 'formatOptions.useInt64Timestamp': - queryReq.formatOptions?.useInt64Timestamp, - }; - if (options.skipParsing) { - rows = res.rows; - } else { - rows = BigQuery.mergeSchemaWithRows_(res.schema, res.rows, { - wrapIntegers: options.wrapIntegers || false, - parseJSON: options.parseJSON, - listParams, - }); - delete res.rows; - } - } catch (e) { - (callback as SimpleQueryRowsCallback)(e as Error, null, job); - return; + if (options.skipParsing) { + rows = res.rows; + } else { + rows = BigQuery.mergeSchemaWithRows_(res.schema, res.rows, { + wrapIntegers: options.wrapIntegers || false, + parseJSON: options.parseJSON, + }); + delete res.rows; } } this.trace_('[runJobsQuery] job complete'); @@ -2364,18 +2337,6 @@ export class BigQuery extends Service { if (options.job) { return undefined; } - const hasAnyFormatOpts = - options['formatOptions.timestampOutputFormat'] !== undefined || - options['formatOptions.useInt64Timestamp'] !== undefined; - const defaultOpts = hasAnyFormatOpts - ? {} - : { - timestampOutputFormat: 'ISO8601_STRING', - }; - const formatOptions = extend(defaultOpts, { - timestampOutputFormat: options['formatOptions.timestampOutputFormat'], - useInt64Timestamp: options['formatOptions.useInt64Timestamp'], - }); const req: bigquery.IQueryRequest = { useQueryCache: queryObj.useQueryCache, labels: queryObj.labels, @@ -2384,7 +2345,9 @@ export class BigQuery extends Service { maximumBytesBilled: queryObj.maximumBytesBilled, timeoutMs: options.timeoutMs, location: queryObj.location || options.location, - formatOptions, + formatOptions: { + useInt64Timestamp: true, + }, maxResults: queryObj.maxResults || options.maxResults, query: queryObj.query, useLegacySql: false, @@ -2514,9 +2477,6 @@ function convertSchemaFieldValue( wrapIntegers: boolean | IntegerTypeCastOptions; selectedFields?: string[]; parseJSON?: boolean; - listParams?: - | bigquery.tabledata.IListParams - | bigquery.jobs.IGetQueryResultsParams; }, ) { if (value === null) { @@ -2576,43 +2536,9 @@ function convertSchemaFieldValue( break; } case 'TIMESTAMP': { - /* - At this point, 'value' will equal the timestamp value returned from the - server. We need to parse this value differently depending on its format. - For example, value could be any of the following: - 1672574400123456 - 1672574400.123456 - 2023-01-01T12:00:00.123456789123Z - */ - const listParams = options.listParams; - const timestampOutputFormat = listParams - ? listParams['formatOptions.timestampOutputFormat'] - : undefined; - const useInt64Timestamp = listParams - ? listParams['formatOptions.useInt64Timestamp'] - : undefined; - if (timestampOutputFormat === 'ISO8601_STRING') { - // value is ISO string, create BigQueryTimestamp wrapping the string - value = BigQuery.timestamp(value); - } else if ( - useInt64Timestamp !== true && - timestampOutputFormat !== 'INT64' && - (useInt64Timestamp !== undefined || timestampOutputFormat !== undefined) - ) { - // NOTE: The additional - // (useInt64Timestamp !== undefined || timestampOutputFormat !== und...) - // check is to ensure that calls to the /query endpoint remain - // unaffected as they will not be providing any listParams. - // - // If the program reaches this point in time then - // value is float seconds so convert to BigQueryTimestamp - value = BigQuery.timestamp(Number(value)); - } else { - // Expect int64 micros (default or explicit INT64) - const pd = new PreciseDate(); - pd.setFullTime(PreciseDate.parseFull(BigInt(value) * BigInt(1000))); - value = BigQuery.timestamp(pd); - } + const pd = new PreciseDate(); + pd.setFullTime(PreciseDate.parseFull(BigInt(value) * BigInt(1000))); + value = BigQuery.timestamp(pd); break; } case 'GEOGRAPHY': { @@ -2628,7 +2554,6 @@ function convertSchemaFieldValue( value = BigQueryRange.fromSchemaValue_( value, schemaField.rangeElementType!.type!, - options.listParams, // Required to convert TIMESTAMP values ); break; } @@ -2706,14 +2631,6 @@ export class BigQueryRange { }; } - /** - * This method returns start and end values for RANGE typed values returned from - * the server. It decodes the server RANGE value into start and end values so - * they can be used to construct a BigQueryRange. - * @private - * @param {string} value The range value. - * @returns {string[]} The start and end of the range. - */ private static fromStringValue_(value: string): [start: string, end: string] { let cleanedValue = value; if (cleanedValue.startsWith('[') || cleanedValue.startsWith('(')) { @@ -2733,24 +2650,7 @@ export class BigQueryRange { return [start, end]; } - /** - * This method is only used by convertSchemaFieldValue and only when range - * values are passed into convertSchemaFieldValue. It produces a value that is - * delivered to the user for read calls and it needs to pass along listParams - * to ensure TIMESTAMP types are converted properly. - * @private - * @param {string} value The range value. - * @param {string} elementType The element type. - * @param {bigquery.tabledata.IListParams | bigquery.jobs.IGetQueryResultsParams} [listParams] The list parameters. - * @returns {BigQueryRange} - */ - static fromSchemaValue_( - value: string, - elementType: string, - listParams?: - | bigquery.tabledata.IListParams - | bigquery.jobs.IGetQueryResultsParams, - ): BigQueryRange { + static fromSchemaValue_(value: string, elementType: string): BigQueryRange { const [start, end] = BigQueryRange.fromStringValue_(value); const convertRangeSchemaValue = (value: string) => { if (value === 'UNBOUNDED' || value === 'NULL') { @@ -2758,7 +2658,6 @@ export class BigQueryRange { } return convertSchemaFieldValue({type: elementType}, value, { wrapIntegers: false, - listParams, }); }; return BigQuery.range( @@ -2834,16 +2733,6 @@ export class BigQueryTimestamp { } else if (typeof value === 'string') { if (/^\d{4}-\d{1,2}-\d{1,2}/.test(value)) { pd = new PreciseDate(value); - if (value.match(/\.\d{10,}/) && !Number.isNaN(pd.getTime())) { - /* - TODO: - When https://github.com/googleapis/nodejs-precise-date/pull/302 - is released and we have full support for picoseconds in PreciseData - then we can remove this if block. - */ - this.value = value; - return; - } } else { const floatValue = Number.parseFloat(value); if (!Number.isNaN(floatValue)) { diff --git a/handwritten/bigquery/src/job.ts b/handwritten/bigquery/src/job.ts index 22554a1d8f3..dc0b068c2ad 100644 --- a/handwritten/bigquery/src/job.ts +++ b/handwritten/bigquery/src/job.ts @@ -596,25 +596,14 @@ class Job extends Operation { let rows: any = []; if (resp.schema && resp.rows) { - try { - /* - Without this try/catch block, calls to /query endpoint will hang - indefinitely if a call to mergeSchemaWithRows_ fails because the - error never makes it to the callback. Instead, pass the error to the - callback the user provides so that the user can see the error. - */ - if (options.skipParsing) { - rows = resp.rows; - } else { - rows = BigQuery.mergeSchemaWithRows_(resp.schema, resp.rows, { - wrapIntegers, - parseJSON, - }); - delete resp.rows; - } - } catch (e) { - callback!(e as Error, null, null, resp); - return; + if (options.skipParsing) { + rows = resp.rows; + } else { + rows = BigQuery.mergeSchemaWithRows_(resp.schema, resp.rows, { + wrapIntegers, + parseJSON, + }); + delete resp.rows; } } diff --git a/handwritten/bigquery/src/table.ts b/handwritten/bigquery/src/table.ts index e92c6a6791d..62ed4521256 100644 --- a/handwritten/bigquery/src/table.ts +++ b/handwritten/bigquery/src/table.ts @@ -55,7 +55,6 @@ import {JobMetadata, JobOptions} from './job'; import bigquery from './types'; import {IntegerTypeCastOptions} from './bigquery'; import {RowQueue} from './rowQueue'; -import IDataFormatOptions = bigquery.IDataFormatOptions; // This is supposed to be a @google-cloud/storage `File` type. The storage npm // module includes these types, but is current installed as a devDependency. @@ -1867,42 +1866,25 @@ class Table extends ServiceObject { callback!(err, null, null, resp); return; } - try { - /* - Without this try/catch block, calls to getRows will hang indefinitely if - a call to mergeSchemaWithRows_ fails because the error never makes it to - the callback. Instead, pass the error to the callback the user provides - so that the user can see the error. - */ - if (options.skipParsing) { - rows = rows || []; - } else { - rows = BigQuery.mergeSchemaWithRows_( - this.metadata.schema, - rows || [], - { - wrapIntegers, - selectedFields, - parseJSON, - listParams: qs, - }, - ); - } - } catch (err) { - callback!(err as Error | null, null, null, resp); - return; + if (options.skipParsing) { + rows = rows || []; + } else { + rows = BigQuery.mergeSchemaWithRows_(this.metadata.schema, rows || [], { + wrapIntegers, + selectedFields, + parseJSON, + }); } callback!(null, rows, nextQuery, resp); }; - const hasAnyFormatOpts = - options['formatOptions.timestampOutputFormat'] !== undefined || - options['formatOptions.useInt64Timestamp'] !== undefined; - const defaultOpts = hasAnyFormatOpts - ? {} - : { - 'formatOptions.timestampOutputFormat': 'ISO8601_STRING', - }; - const qs = extend(defaultOpts, options); + + const qs = extend( + { + 'formatOptions.useInt64Timestamp': true, + }, + options, + ); + this.request( { uri: '/data', diff --git a/handwritten/bigquery/system-test/bigquery.ts b/handwritten/bigquery/system-test/bigquery.ts index 92550709de1..aced74c4b40 100644 --- a/handwritten/bigquery/system-test/bigquery.ts +++ b/handwritten/bigquery/system-test/bigquery.ts @@ -1041,7 +1041,7 @@ describe('BigQuery', () => { } }); - it('should create a table with timestampPrecision', async () => { + it.skip('should create a table with timestampPrecision', async () => { const table = dataset.table(generateName('timestamp-precision-table')); const schema = { fields: [ @@ -1495,14 +1495,9 @@ describe('BigQuery', () => { ], }, (err, rows) => { - try { - // Without this try block the test runner silently fails - assert.ifError(err); - assert.strictEqual(rows!.length, 1); - done(); - } catch (e) { - done(e); - } + assert.ifError(err); + assert.strictEqual(rows!.length, 1); + done(); }, ); }); @@ -1526,159 +1521,6 @@ describe('BigQuery', () => { }, ); }); - describe('High Precision Query System Tests', () => { - let bigquery: BigQuery; - const expectedTsValueNanoseconds = '2023-01-01T12:00:00.123456000Z'; - const expectedTsValuePicoseconds = - '2023-01-01T12:00:00.123456789123Z'; - const expectedErrorMessage = - 'Cannot specify both timestamp_as_int and timestamp_output_format.'; - - before(() => { - bigquery = new BigQuery(); - }); - - const testCases = [ - { - name: 'TOF: FLOAT64, UI64: true (error)', - timestampOutputFormat: 'FLOAT64', - useInt64Timestamp: true, - expectedTsValue: undefined, - expectedError: expectedErrorMessage, - }, - { - name: 'TOF: omitted, UI64: omitted (default INT64)', - timestampOutputFormat: undefined, - useInt64Timestamp: undefined, - expectedTsValue: expectedTsValuePicoseconds, - }, - { - name: 'TOF: omitted, UI64: true', - timestampOutputFormat: undefined, - useInt64Timestamp: true, - expectedTsValue: expectedTsValueNanoseconds, - }, - ]; - - testCases.forEach(testCase => { - it(`should handle ${testCase.name}`, async () => { - /* - The users use the new TIMESTAMP(12) type to indicate they want to - opt in to using timestampPrecision=12. The reason is that some queries - like `SELECT CAST(? as TIMESTAMP(12))` will fail if we set - timestampPrecision=12 and we don't want this code change to affect - existing users. Queries using TIMESTAMP_ADD are another example. - */ - const query = { - query: 'SELECT ? as ts', - params: [ - bigquery.timestamp('2023-01-01T12:00:00.123456789123Z'), - ], - types: ['TIMESTAMP(12)'], - }; - - const options: any = {}; - if (testCase.timestampOutputFormat !== undefined) { - options['formatOptions.timestampOutputFormat'] = - testCase.timestampOutputFormat; - } - if (testCase.useInt64Timestamp !== undefined) { - options['formatOptions.useInt64Timestamp'] = - testCase.useInt64Timestamp; - } - - try { - const [rows] = await bigquery.query(query, options); - if (testCase.expectedError) { - assert.fail( - `Query should have failed for ${testCase.name}, but succeeded`, - ); - } - assert.ok(rows.length > 0); - assert.ok(rows[0].ts.value !== undefined); - assert.strictEqual( - rows[0].ts.value, - testCase.expectedTsValue, - ); - } catch (err: any) { - if (!testCase.expectedError) { - throw err; - } - - const message = err.message; - assert.strictEqual( - message, - testCase.expectedError, - `Expected ${testCase.expectedError} error for ${testCase.name}, got ${message} (${err.message})`, - ); - } - }); - it(`should handle nested ${testCase.name}`, async () => { - /* - The users use the new TIMESTAMP(12) type to indicate they want to - opt in to using timestampPrecision=12. The reason is that some queries - like `SELECT CAST(? as TIMESTAMP(12))` will fail if we set - timestampPrecision=12 and we don't want this code change to affect - existing users. - */ - const query = { - query: 'SELECT ? obj', - params: [ - { - nested: { - a: bigquery.timestamp( - '2023-01-01T12:00:00.123456789123Z', - ), - }, - }, - ], - types: [ - { - nested: { - a: 'TIMESTAMP(12)', - }, - }, - ], - }; - - const options: any = {}; - if (testCase.timestampOutputFormat !== undefined) { - options['formatOptions.timestampOutputFormat'] = - testCase.timestampOutputFormat; - } - if (testCase.useInt64Timestamp !== undefined) { - options['formatOptions.useInt64Timestamp'] = - testCase.useInt64Timestamp; - } - - try { - const [rows] = await bigquery.query(query, options); - if (testCase.expectedError) { - assert.fail( - `Query should have failed for ${testCase.name}, but succeeded`, - ); - } - assert.ok(rows.length > 0); - assert.ok(rows[0].obj.nested.a.value !== undefined); - assert.strictEqual( - rows[0].obj.nested.a.value, - testCase.expectedTsValue, - ); - } catch (err: any) { - if (!testCase.expectedError) { - throw err; - } - - const message = err.message; - assert.strictEqual( - message, - testCase.expectedError, - `Expected ${testCase.expectedError} error for ${testCase.name}, got ${message} (${err.message})`, - ); - } - }); - }); - }); }); describe('named', () => { @@ -1973,161 +1815,6 @@ describe('BigQuery', () => { }, ); }); - describe('High Precision Query System Tests', () => { - let bigquery: BigQuery; - const expectedTsValueNanoseconds = '2023-01-01T12:00:00.123456000Z'; - const expectedTsValuePicoseconds = - '2023-01-01T12:00:00.123456789123Z'; - const expectedErrorMessage = - 'Cannot specify both timestamp_as_int and timestamp_output_format.'; - - before(() => { - bigquery = new BigQuery(); - }); - - const testCases = [ - { - name: 'TOF: FLOAT64, UI64: true (error)', - timestampOutputFormat: 'FLOAT64', - useInt64Timestamp: true, - expectedTsValue: undefined, - expectedError: expectedErrorMessage, - }, - { - name: 'TOF: omitted, UI64: omitted (default INT64)', - timestampOutputFormat: undefined, - useInt64Timestamp: undefined, - expectedTsValue: expectedTsValuePicoseconds, - }, - { - name: 'TOF: omitted, UI64: true', - timestampOutputFormat: undefined, - useInt64Timestamp: true, - expectedTsValue: expectedTsValueNanoseconds, - }, - ]; - - testCases.forEach(testCase => { - it(`should handle ${testCase.name}`, async () => { - /* - The users use the new TIMESTAMP(12) type to indicate they want to - opt in to using timestampPrecision=12. The reason is that some queries - like `SELECT CAST(? as TIMESTAMP(12))` will fail if we set - timestampPrecision=12 and we don't want this code change to affect - existing users. Queries using TIMESTAMP_ADD are another example. - */ - const query = { - query: 'SELECT @r AS ts', - params: { - r: bigquery.timestamp('2023-01-01T12:00:00.123456789123Z'), - }, - types: { - r: 'TIMESTAMP(12)', - }, - }; - - const options: any = {}; - if (testCase.timestampOutputFormat !== undefined) { - options['formatOptions.timestampOutputFormat'] = - testCase.timestampOutputFormat; - } - if (testCase.useInt64Timestamp !== undefined) { - options['formatOptions.useInt64Timestamp'] = - testCase.useInt64Timestamp; - } - - try { - const [rows] = await bigquery.query(query, options); - if (testCase.expectedError) { - assert.fail( - `Query should have failed for ${testCase.name}, but succeeded`, - ); - } - assert.ok(rows.length > 0); - assert.ok(rows[0].ts.value !== undefined); - assert.strictEqual( - rows[0].ts.value, - testCase.expectedTsValue, - ); - } catch (err: any) { - if (!testCase.expectedError) { - throw err; - } - - const message = err.message; - assert.strictEqual( - message, - testCase.expectedError, - `Expected ${testCase.expectedError} error for ${testCase.name}, got ${message} (${err.message})`, - ); - } - }); - it(`should handle nested ${testCase.name}`, async () => { - /* - The users use the new TIMESTAMP(12) type to indicate they want to - opt in to using timestampPrecision=12. The reason is that some queries - like `SELECT CAST(? as TIMESTAMP(12))` will fail if we set - timestampPrecision=12 and we don't want this code change to affect - existing users. - */ - const query = { - query: 'SELECT @r obj', - params: { - r: { - nested: { - a: bigquery.timestamp( - '2023-01-01T12:00:00.123456789123Z', - ), - }, - }, - }, - types: { - r: { - nested: { - a: 'TIMESTAMP(12)', - }, - }, - }, - }; - - const options: any = {}; - if (testCase.timestampOutputFormat !== undefined) { - options['formatOptions.timestampOutputFormat'] = - testCase.timestampOutputFormat; - } - if (testCase.useInt64Timestamp !== undefined) { - options['formatOptions.useInt64Timestamp'] = - testCase.useInt64Timestamp; - } - - try { - const [rows] = await bigquery.query(query, options); - if (testCase.expectedError) { - assert.fail( - `Query should have failed for ${testCase.name}, but succeeded`, - ); - } - assert.ok(rows.length > 0); - assert.ok(rows[0].obj.nested.a.value !== undefined); - assert.strictEqual( - rows[0].obj.nested.a.value, - testCase.expectedTsValue, - ); - } catch (err: any) { - if (!testCase.expectedError) { - throw err; - } - - const message = err.message; - assert.strictEqual( - message, - testCase.expectedError, - `Expected ${testCase.expectedError} error for ${testCase.name}, got ${message} (${err.message})`, - ); - } - }); - }); - }); }); }); diff --git a/handwritten/bigquery/system-test/timestamp_output_format.ts b/handwritten/bigquery/system-test/timestamp_output_format.ts deleted file mode 100644 index 0fe388e1e3b..00000000000 --- a/handwritten/bigquery/system-test/timestamp_output_format.ts +++ /dev/null @@ -1,216 +0,0 @@ -// Copyright 2026 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/bigquery'; -import {randomUUID} from 'crypto'; -import {RequestResponse} from '@google-cloud/common/build/src/service-object'; - -const bigquery = new BigQuery(); - -interface TestCase { - name: string; - timestampOutputFormat?: string; - useInt64Timestamp?: boolean; - expectedError?: string; - expectedTsValue?: string; -} - -describe('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 insertedTsValue = '2023-01-01T12:00:00.123456789123Z'; - const expectedTsValueNanoseconds = '2023-01-01T12:00:00.123456000Z'; - const expectedTsValuePicoseconds = '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: insertedTsValue}]); - }); - - after(async () => { - try { - await dataset.delete({force: true}); - } catch (e) { - console.error('Error deleting dataset:', e); - } - }); - - const testCases: TestCase[] = [ - { - name: 'should call getRows with TIMESTAMP_OUTPUT_FORMAT_UNSPECIFIED and useInt64Timestamp=true', - timestampOutputFormat: 'TIMESTAMP_OUTPUT_FORMAT_UNSPECIFIED', - useInt64Timestamp: true, - expectedTsValue: expectedTsValueNanoseconds, - }, - { - name: 'should call getRows with TIMESTAMP_OUTPUT_FORMAT_UNSPECIFIED and useInt64Timestamp=false', - timestampOutputFormat: 'TIMESTAMP_OUTPUT_FORMAT_UNSPECIFIED', - useInt64Timestamp: false, - expectedTsValue: expectedTsValueNanoseconds, - }, - { - name: 'should call getRows with FLOAT64 and useInt64Timestamp=true (expect error)', - timestampOutputFormat: 'FLOAT64', - useInt64Timestamp: true, - expectedError: - 'Cannot specify both use_int64_timestamp and timestamp_output_format.', - }, - { - name: 'should call getRows with FLOAT64 and useInt64Timestamp=false', - timestampOutputFormat: 'FLOAT64', - useInt64Timestamp: false, - expectedTsValue: expectedTsValueNanoseconds, - }, - { - name: 'should call getRows with INT64 and useInt64Timestamp=true', - timestampOutputFormat: 'INT64', - useInt64Timestamp: true, - expectedTsValue: expectedTsValueNanoseconds, - }, - { - name: 'should call getRows with INT64 and useInt64Timestamp=false', - timestampOutputFormat: 'INT64', - useInt64Timestamp: false, - expectedTsValue: expectedTsValueNanoseconds, - }, - { - name: 'should call getRows with ISO8601_STRING and useInt64Timestamp=true (expect error)', - timestampOutputFormat: 'ISO8601_STRING', - useInt64Timestamp: true, - expectedError: - 'Cannot specify both use_int64_timestamp and timestamp_output_format.', - }, - { - name: 'should call getRows with ISO8601_STRING and useInt64Timestamp=false', - timestampOutputFormat: 'ISO8601_STRING', - useInt64Timestamp: false, - expectedTsValue: expectedTsValuePicoseconds, - }, - // Additional test cases for undefined combinations - { - name: 'should call getRows with timestampOutputFormat undefined and useInt64Timestamp undefined', - timestampOutputFormat: undefined, - useInt64Timestamp: undefined, - expectedTsValue: expectedTsValuePicoseconds, - }, - { - name: 'should call getRows with timestampOutputFormat undefined and useInt64Timestamp=true', - timestampOutputFormat: undefined, - useInt64Timestamp: true, - expectedTsValue: expectedTsValueNanoseconds, - }, - { - name: 'should call getRows with timestampOutputFormat undefined and useInt64Timestamp=false', - timestampOutputFormat: undefined, - useInt64Timestamp: false, - expectedTsValue: expectedTsValueNanoseconds, - }, - { - name: 'should call getRows with TIMESTAMP_OUTPUT_FORMAT_UNSPECIFIED and useInt64Timestamp undefined', - timestampOutputFormat: 'TIMESTAMP_OUTPUT_FORMAT_UNSPECIFIED', - useInt64Timestamp: undefined, - expectedTsValue: expectedTsValueNanoseconds, - }, - { - name: 'should call getRows with FLOAT64 and useInt64Timestamp undefined (expect error)', - timestampOutputFormat: 'FLOAT64', - useInt64Timestamp: undefined, - expectedTsValue: expectedTsValueNanoseconds, - }, - { - name: 'should call getRows with INT64 and useInt64Timestamp undefined', - timestampOutputFormat: 'INT64', - useInt64Timestamp: undefined, - expectedTsValue: expectedTsValueNanoseconds, - }, - { - name: 'should call getRows with ISO8601_STRING and useInt64Timestamp undefined (expect error)', - timestampOutputFormat: 'ISO8601_STRING', - useInt64Timestamp: undefined, - expectedTsValue: expectedTsValuePicoseconds, - }, - ]; - - testCases.forEach( - ({ - name, - timestampOutputFormat, - useInt64Timestamp, - expectedError, - expectedTsValue, - }) => { - it(name, async () => { - const options: {[key: string]: any} = {}; - if (timestampOutputFormat !== undefined) { - options['formatOptions.timestampOutputFormat'] = - timestampOutputFormat; - } - if (useInt64Timestamp !== undefined) { - options['formatOptions.useInt64Timestamp'] = useInt64Timestamp; - } - - if (expectedError) { - try { - await table.getRows(options); - assert.fail('The call should have thrown an error.'); - } catch (e) { - assert.strictEqual((e as Error).message, expectedError); - } - } else { - const [rows] = await table.getRows(options); - assert(rows.length > 0); - assert.strictEqual(rows[0].ts.value, expectedTsValue); - } - }); - }, - ); - - it('should make a request with ISO8601_STRING when no format options are being used', done => { - void (async () => { - const originalRequest = table.request; - const requestPromise: Promise = new Promise( - (resolve, reject) => { - const innerPromise = new Promise((innerResolve, innerReject) => { - innerResolve({}); - }); - resolve(innerPromise as Promise); - }, - ); - table.request = reqOpts => { - table.request = originalRequest; - if ( - reqOpts.qs['formatOptions.timestampOutputFormat'] === 'ISO8601_STRING' - ) { - done(); - } else { - done( - new Error( - 'The default timestampOutputFormat should be ISO8601_STRING', - ), - ); - } - return requestPromise; - }; - await table.getRows({}); - })(); - }); -}); diff --git a/handwritten/bigquery/test/bigquery.ts b/handwritten/bigquery/test/bigquery.ts index 74fbbedf1c7..bc006e70660 100644 --- a/handwritten/bigquery/test/bigquery.ts +++ b/handwritten/bigquery/test/bigquery.ts @@ -42,7 +42,6 @@ import { TableField, Query, QueryResultsOptions, - QueryOptions, } from '../src'; import {SinonStub} from 'sinon'; import {PreciseDate} from '@google-cloud/precise-date'; @@ -3466,75 +3465,12 @@ describe('BigQuery', () => { }, jobCreationMode: 'JOB_CREATION_REQUIRED', formatOptions: { - timestampOutputFormat: 'ISO8601_STRING', + useInt64Timestamp: true, }, }; assert.deepStrictEqual(req, expectedReq); }); - describe('timestamp format options', () => { - const testCases: { - name: string; - opts: QueryOptions; - expected?: any; - bail?: boolean; - }[] = [ - { - name: 'TOF: omitted, UI64: omitted (default ISO8601_STRING)', - opts: {}, - expected: { - timestampOutputFormat: 'ISO8601_STRING', - }, - }, - { - name: 'TOF: omitted, UI64: true', - opts: { - ['formatOptions.useInt64Timestamp']: true, - }, - expected: { - useInt64Timestamp: true, - }, - }, - { - name: 'TOF: omitted, UI64: false (default ISO8601_STRING)', - opts: { - ['formatOptions.useInt64Timestamp']: false, - }, - expected: { - useInt64Timestamp: false, - }, - }, - ]; - - testCases.forEach(testCase => { - it(`should handle ${testCase.name}`, () => { - const req = bq.buildQueryRequest_(QUERY_STRING, testCase.opts); - - const expectedReq = { - query: QUERY_STRING, - useLegacySql: false, - requestId: req.requestId, - jobCreationMode: 'JOB_CREATION_OPTIONAL', - formatOptions: testCase.expected, - connectionProperties: undefined, - continuous: undefined, - createSession: undefined, - defaultDataset: undefined, - destinationEncryptionConfiguration: undefined, - labels: undefined, - location: undefined, - maxResults: undefined, - maximumBytesBilled: undefined, - preserveNulls: undefined, - reservation: undefined, - timeoutMs: undefined, - useQueryCache: undefined, - writeIncrementalResults: undefined, - }; - assert.deepStrictEqual(req, expectedReq); - }); - }); - }); it('should create a QueryRequest from a SQL string', () => { const req = bq.buildQueryRequest_(QUERY_STRING, {}); for (const key in req) { @@ -3548,7 +3484,7 @@ describe('BigQuery', () => { requestId: req.requestId, jobCreationMode: 'JOB_CREATION_OPTIONAL', formatOptions: { - timestampOutputFormat: 'ISO8601_STRING', + useInt64Timestamp: true, }, }; assert.deepStrictEqual(req, expectedReq); diff --git a/handwritten/bigquery/test/table.ts b/handwritten/bigquery/test/table.ts index 2e13f1572d6..bb3225459ea 100644 --- a/handwritten/bigquery/test/table.ts +++ b/handwritten/bigquery/test/table.ts @@ -2046,7 +2046,7 @@ describe('BigQuery/Table', () => { assert.strictEqual(reqOpts.uri, '/data'); assert.deepStrictEqual(reqOpts.qs, { ...options, - 'formatOptions.timestampOutputFormat': 'ISO8601_STRING', + 'formatOptions.useInt64Timestamp': true, }); callback(null, {}); }; @@ -2219,6 +2219,7 @@ describe('BigQuery/Table', () => { table.request = (reqOpts: DecorateRequestOptions, callback: Function) => { callback(null, { + 'formatOptions.useInt64Timestamp': true, pageToken, }); }; @@ -2228,7 +2229,7 @@ describe('BigQuery/Table', () => { assert.deepStrictEqual(nextQuery, { a: 'b', c: 'd', - 'formatOptions.timestampOutputFormat': 'ISO8601_STRING', + 'formatOptions.useInt64Timestamp': true, pageToken, }); // Original object isn't affected. @@ -2445,7 +2446,7 @@ describe('BigQuery/Table', () => { table.request = (reqOpts: DecorateRequestOptions, callback: Function) => { assert.deepStrictEqual(reqOpts.qs, { - 'formatOptions.timestampOutputFormat': 'ISO8601_STRING', + 'formatOptions.useInt64Timestamp': true, }); callback(null, {}); }; @@ -2469,7 +2470,7 @@ describe('BigQuery/Table', () => { table.request = (reqOpts: DecorateRequestOptions, callback: Function) => { assert.deepStrictEqual(reqOpts.qs, { - 'formatOptions.timestampOutputFormat': 'ISO8601_STRING', + 'formatOptions.useInt64Timestamp': true, }); callback(null, {}); };