From df957e70df20ce0d7712ad7005a66f7eb02e4962 Mon Sep 17 00:00:00 2001 From: feywind <57276408+feywind@users.noreply.github.com> Date: Mon, 16 Mar 2026 17:52:05 -0400 Subject: [PATCH] feat: allow the user to ask for the raw response rows when querying --- handwritten/bigquery/src/bigquery.ts | 4 +- handwritten/bigquery/src/job.ts | 5 +- handwritten/bigquery/test/bigquery.ts | 70 +++++++++++++++++++++++++++ handwritten/bigquery/test/job.ts | 48 ++++++++++++++++++ 4 files changed, 125 insertions(+), 2 deletions(-) diff --git a/handwritten/bigquery/src/bigquery.ts b/handwritten/bigquery/src/bigquery.ts index daa892cf174..4dfca768add 100644 --- a/handwritten/bigquery/src/bigquery.ts +++ b/handwritten/bigquery/src/bigquery.ts @@ -2273,7 +2273,9 @@ export class BigQuery extends Service { parseJSON: options.parseJSON, listParams, }); - delete res.rows; + if (!options.returnRawRows) { + delete res.rows; + } } catch (e) { (callback as SimpleQueryRowsCallback)(e as Error, null, job); return; diff --git a/handwritten/bigquery/src/job.ts b/handwritten/bigquery/src/job.ts index ddf7497e1cb..eb70ce6ae60 100644 --- a/handwritten/bigquery/src/job.ts +++ b/handwritten/bigquery/src/job.ts @@ -51,6 +51,7 @@ export type QueryResultsOptions = { job?: Job; wrapIntegers?: boolean | IntegerTypeCastOptions; parseJSON?: boolean; + returnRawRows?: boolean; } & PagedRequest & { /** * internal properties @@ -633,7 +634,9 @@ class Job extends Operation { }); delete nextQuery.startIndex; } - delete resp.rows; + if (!options.returnRawRows) { + delete resp.rows; + } callback!(null, rows, nextQuery, resp); }, ); diff --git a/handwritten/bigquery/test/bigquery.ts b/handwritten/bigquery/test/bigquery.ts index e3a134e85f1..72cef7aae0f 100644 --- a/handwritten/bigquery/test/bigquery.ts +++ b/handwritten/bigquery/test/bigquery.ts @@ -3243,6 +3243,76 @@ describe('BigQuery', () => { }); }); + it('should delete res.rows if returnRawRows is false', done => { + const rawRows = [{f: [{v: 'hi'}]}]; + const resp = { + jobComplete: true, + schema: { + fields: [{name: 'name', type: 'STRING'}], + }, + rows: rawRows, + }; + + const job = { + getQueryResults: (options: {}, callback: Function) => { + callback(null, [], null, resp); + }, + }; + + bq.runJobsQuery = (reqOpts: {}, callback: Function) => { + callback(null, job, resp); + }; + + bq.query( + { + query: 'SELECT * FROM table', + }, + {} as QueryResultsOptions, + (err: Error, rows: {}[], nextQuery: {}, response: any) => { + assert.ifError(err); + // the job Complete callback returned the resp + assert.deepStrictEqual(response.rows, undefined); + done(); + }, + ); + }); + + it('should not delete res.rows if returnRawRows is true', done => { + const rawRows = [{f: [{v: 'hi'}]}]; + const resp = { + jobComplete: true, + schema: { + fields: [{name: 'name', type: 'STRING'}], + }, + rows: rawRows, + }; + + const job = { + getQueryResults: (options: {}, callback: Function) => { + callback(null, [], null, resp); + }, + }; + + bq.runJobsQuery = (reqOpts: {}, callback: Function) => { + callback(null, job, resp); + }; + + bq.query( + { + query: 'SELECT * FROM table', + }, + { + returnRawRows: true, + } as QueryResultsOptions, + (err: Error, rows: {}[], nextQuery: {}, response: any) => { + assert.ifError(err); + // the job Complete callback returned the resp + assert.deepStrictEqual(response.rows, rawRows); + done(); + }, + ); + }); + it('should call job#getQueryResults with query options', done => { let queryResultsOpts = {}; const fakeJob = { diff --git a/handwritten/bigquery/test/job.ts b/handwritten/bigquery/test/job.ts index ced932d4b20..3f0ea6afe67 100644 --- a/handwritten/bigquery/test/job.ts +++ b/handwritten/bigquery/test/job.ts @@ -447,6 +447,54 @@ describe('BigQuery/Job', () => { ); }); + it('should delete resp.rows if returnRawRows is false', done => { + const options: QueryResultsOptions = {}; + + const rawRows = [{f: [{v: 'hi'}]}]; + const resp = { + jobComplete: true, + rows: rawRows, + schema: { + fields: [{name: 'name', type: 'STRING'}], + }, + }; + + job.bigQuery.request = (reqOpts: {}, callback: Function) => { + callback(null, resp); + }; + + job.getQueryResults(options, (err: Error, rows: {}, nextQuery: {}, response: any) => { + assert.ifError(err); + assert.deepStrictEqual(response.rows, undefined); + done(); + }); + }); + + it('should not delete resp.rows if returnRawRows is true', done => { + const options: QueryResultsOptions = { + returnRawRows: true, + }; + + const rawRows = [{f: [{v: 'hi'}]}]; + const resp = { + jobComplete: true, + rows: rawRows, + schema: { + fields: [{name: 'name', type: 'STRING'}], + }, + }; + + job.bigQuery.request = (reqOpts: {}, callback: Function) => { + callback(null, resp); + }; + + job.getQueryResults(options, (err: Error, rows: {}, nextQuery: {}, response: any) => { + assert.ifError(err); + assert.deepStrictEqual(response.rows, rawRows); + done(); + }); + }); + it('should populate nextQuery when more results exist', done => { job.getQueryResults( options,